Helm Hooks - A way to hack into helm life cycle

 
Helm Hooks

Introduction

When we were migrating from a bare-metal environment to a Kubernetes environment(replacing for example an rpm to helm charts), we needed a mechanism to even migrate the pre and post-install scripts into a helm pre-post steps.
For this, we found out an alternative in helm which is referred to as hooks. 
Hooks is treated as a special annotation in helm. Helm handles hooks in its own specific way

Available Hooks

Annotation Value

Description

pre-install

Executes before any resource is loaded/created

post-install

Executes after all resources are loaded into Kubernetes

pre-delete

Executes on a deletion request before any resources are deleted from Kubernetes

post-delete

Executes on a deletion request after all of the release's resources have been deleted

pre-upgrade

Executes on an upgrade request after templates are rendered, but before any resources are updated

post-upgrade

Executes on an upgrade request after all resources have been upgraded

pre-rollback

Executes on a rollback request after templates are rendered, but before any resources are rolled back

post-rollback

Executes on a rollback request after all resources have been modified

test

Executes when the Helm test subcommand is invoked


Note: Resource here represents any kind for example a job, a pod and so on

Hooks example

Hooks are defined in a charts metadata section.
Consider following example for defining hooks:

apiVersion: batch/v1
kind: Job
metadata:
  name: "{{ .Release.Name }}"
  labels:
    app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
    app.kubernetes.io/instance: {{ .Release.Name | quote }}
    app.kubernetes.io/version: {{ .Chart.AppVersion }}
    helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
  annotations:
  # This is what defines this resource as a hook. Without this line, the
  # job is considered part of the release.
    "helm.sh/hook": post-install
    "helm.sh/hook-weight": "-5"
    "helm.sh/hook-delete-policy": hook-succeeded


The example provided above acts as a post-install hook which means when all the resources like job, deployment, service, and others are run/executed, this resource, for now a job, will then be run.
Similarly, there is no limit on the resources that can implement a hook.

Hooks Weight

There were scenarios wherein several pre-install hooks were to be executed in an order. For this, helm has provided a way to define weight for hooks. Following is how a weight is defined. Weight value can be negative or positive.

Example of hook weight:

annotations:
  "helm.sh/hook-weight": "5"


Depending on the weight provided, each resource will then be executed
Consider the following example

post-install-job-1

apiVersion: batch/v1
kind: Job
metadata:
  name: "{{ .Release.Name }}"
  labels:
    app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
    app.kubernetes.io/instance: {{ .Release.Name | quote }}
    app.kubernetes.io/version: {{ .Chart.AppVersion }}
    helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    annotations:
    # This is what defines this resource as a hook. Without this line, the
    # job is considered part of the release.
    "helm.sh/hook": post-install
    "helm.sh/hook-weight": "-5"
    "helm.sh/hook-delete-policy": hook-succeeded
spec:
  template:
    metadata:
      name: "{{ .Release.Name }}"
      labels:
        app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
        app.kubernetes.io/instance: {{ .Release.Name | quote }}
        helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    spec:
      restartPolicy: Never
      containers:
      - name: post-install-job-1
        image: "alpine:3.3"
        command: ["/bin/sleep","{{ default "10" .Values.sleepyTime }}"]


post-install-job-2

apiVersion: batch/v1
kind: Job
metadata:
  name: "{{ .Release.Name }}"
  labels:
    app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
    app.kubernetes.io/instance: {{ .Release.Name | quote }}
    app.kubernetes.io/version: {{ .Chart.AppVersion }}
    helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    annotations:
    # This is what defines this resource as a hook. Without this line, the
    # job is considered part of the release.
    "helm.sh/hook": post-install
    "helm.sh/hook-weight": "0"
    "helm.sh/hook-delete-policy": hook-succeeded
spec:
  template:
    metadata:
      name: "{{ .Release.Name }}"
      labels:
        app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
        app.kubernetes.io/instance: {{ .Release.Name | quote }}
        helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    spec:
      restartPolicy: Never
      containers:
      - name: post-install-job-2
        image: "alpine:3.3"
        command: ["/bin/sleep","{{ default "10" .Values.sleepyTime }}"]


post-install-job-3

apiVersion: batch/v1
kind: Job
metadata:
  name: "{{ .Release.Name }}"
  labels:
    app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
    app.kubernetes.io/instance: {{ .Release.Name | quote }}
    app.kubernetes.io/version: {{ .Chart.AppVersion }}
    helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    annotations:
    # This is what defines this resource as a hook. Without this line, the
    # job is considered part of the release.
    "helm.sh/hook": post-install
    "helm.sh/hook-weight": "3"
    "helm.sh/hook-delete-policy": hook-succeeded
spec:
  template:
    metadata:
      name: "{{ .Release.Name }}"
      labels:
        app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
        app.kubernetes.io/instance: {{ .Release.Name | quote }}
        helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    spec:
      restartPolicy: Never
      containers:
      - name: post-install-job-3
        image: "alpine:3.3"
        command: ["/bin/sleep","{{ default "10" .Values.sleepyTime }}"]


In the above given examples, the order of execution of the hooks will be as post-install-job-1, post-install-job-2, post-install-job-3.

Note: One resource can implement multiple hooks.

annotations:
  "helm.sh/hook": post-install,post-upgrade


Hooks deletion

To manage system resources properly, helm even provides ways to delete each hook depending on certain criteria/policy.

Following is the way to define a hook deletion policy

annotations:
  "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded


Hooks deletion policy

Following are the available hook deletion policy:

Annotation Value

Description

before-hook-creation

Delete the previous resource before a new hook is launched (default)

hook-succeeded

Delete the resource after the hook is successfully executed

hook-failed

Delete the resource if the hook failed during execution


Note: If no hook deletion policy annotation is specified, the before-hook-creation behavior applies by default.

References

Post a Comment

0 Comments