Chart Hooks

Helm provides a hook mechanism to allow chart developers to intervene atcertain points in a release’s life cycle. For example, you can use hooks to:

  • Load a ConfigMap or Secret during install before any other charts are loaded.
  • Execute a Job to back up a database before installing a new chart, and thenexecute a second job after the upgrade in order to restore data.
  • Run a Job before deleting a release to gracefully take a service out ofrotation before removing it.Hooks work like regular templates, but they have special annotations that causeHelm to utilize them differently. In this section, we cover the basic usagepattern for hooks.

The Available Hooks

The following hooks are defined:

  • crd-install: In Helm 2, this executes after templates are rendered, but before the regularinstallation has been run. In Helm 3, this has been deprecated in favor of the crds/directory.
  • pre-install: Executes after templates are rendered, but before any resourcesare created in Kubernetes.
  • post-install: Executes after all resources are loaded into Kubernetes
  • pre-delete: Executes on a deletion request before any resources are deletedfrom Kubernetes.
  • post-delete: Executes on a deletion request after all of the release’sresources have been deleted.
  • pre-upgrade: Executes on an upgrade request after templates are rendered, butbefore any resources are loaded into Kubernetes (e.g. before a Kubernetesapply operation).
  • post-upgrade: Executes on an upgrade after all resources have been upgraded.
  • pre-rollback: Executes on a rollback request after templates are rendered, butbefore any resources have been rolled back.
  • post-rollback: Executes on a rollback request after all resources have beenmodified.

Hooks and the Release Lifecycle

Hooks allow you, the chart developer, an opportunity to perform operations atstrategic points in a release lifecycle. For example, consider the lifecycle fora helm install. By default, the lifecycle looks like this:

  • User runs helm install foo
  • The Helm library install API is called
  • After some verification, the library renders the foo templates
  • The library loads the resulting resources into Kubernetes
  • The library returns the release object (and other data) to the client
  • The client exitsHelm defines two hooks for the install lifecycle: pre-install andpost-install. If the developer of the foo chart implements both hooks, thelifecycle is altered like this:

  • User runs helm install foo

  • The Helm library install API is called
  • CRDs in the crds/ directory are installed
  • After some verification, the library renders the foo templates
  • The library prepares to execute the pre-install hooks (loading hookresources into Kubernetes)
  • The library sorts hooks by weight (assigning a weight of 0 by default) and byname for those hooks with the same weight in ascending order.
  • The library then loads the hook with the lowest weight first (negative topositive)
  • The library waits until the hook is “Ready” (except for CRDs)
  • The library loads the resulting resources into Kubernetes. Note that if the—wait flag is set, the library will wait until all resources are in aready state and will not run the post-install hook until they are ready.
  • The library executes the post-install hook (loading hook resources)
  • The library waits until the hook is “Ready”
  • The library returns the release object (and other data) to the client
  • The client exitsWhat does it mean to wait until a hook is ready? This depends on the resourcedeclared in the hook. If the resources is a Job kind, the library will waituntil the job successfully runs to completion. And if the job fails, the releasewill fail. This is a blocking operation, so the Helm client will pause whilethe Job is run.

For all other kinds, as soon as Kubernetes marks the resource as loaded (addedor updated), the resource is considered “Ready”. When many resources aredeclared in a hook, the resources are executed serially. If they have hookweights (see below), they are executed in weighted order. Otherwise, ordering isnot guaranteed. (In Helm 2.3.0 and after, they are sorted alphabetically. Thatbehavior, though, is not considered binding and could change in the future.) Itis considered good practice to add a hook weight, and set it to 0 if weight isnot important.

Hook resources are not managed with corresponding releases

The resources that a hook creates are not tracked or managed as part of therelease. Once Helm verifies that the hook has reached its ready state, it willleave the hook resource alone.

Practically speaking, this means that if you create resources in a hook, youcannot rely upon helm uninstall to remove the resources. To destroy suchresources, you need to either write code to perform this operation in apre-delete or post-delete hook or add "helm.sh/hook-delete-policy"annotation to the hook template file.

Writing a Hook

Hooks are just Kubernetes manifest files with special annotations in themetadata section. Because they are template files, you can use all of thenormal template features, including reading .Values, .Release, and.Template.

For example, this template, stored in templates/post-install-job.yaml,declares a job to be run on post-install:

  1. apiVersion: batch/v1
  2. kind: Job
  3. metadata:
  4. name: "{{ .Release.Name }}"
  5. labels:
  6. app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
  7. app.kubernetes.io/instance: {{ .Release.Name | quote }}
  8. app.kubernetes.io/version: {{ .Chart.AppVersion }}
  9. helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
  10. annotations:
  11. # This is what defines this resource as a hook. Without this line, the
  12. # job is considered part of the release.
  13. "helm.sh/hook": post-install
  14. "helm.sh/hook-weight": "-5"
  15. "helm.sh/hook-delete-policy": hook-succeeded
  16. spec:
  17. template:
  18. metadata:
  19. name: "{{ .Release.Name }}"
  20. labels:
  21. app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
  22. app.kubernetes.io/instance: {{ .Release.Name | quote }}
  23. helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
  24. spec:
  25. restartPolicy: Never
  26. containers:
  27. - name: post-install-job
  28. image: "alpine:3.3"
  29. command: ["/bin/sleep","{{ default "10" .Values.sleepyTime }}"]

What makes this template a hook is the annotation:

  1. annotations:
  2. "helm.sh/hook": post-install

One resource can implement multiple hooks:

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

Similarly, there is no limit to the number of different resources that mayimplement a given hook. For example, one could declare both a secret and aconfig map as a pre-install hook.

When subcharts declare hooks, those are also evaluated. There is no way for atop-level chart to disable the hooks declared by subcharts.

It is possible to define a weight for a hook which will help build adeterministic executing order. Weights are defined using the followingannotation:

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

Hook weights can be positive or negative numbers but must be represented asstrings. When Helm starts the execution cycle of hooks of a particular Kind itwill sort those hooks in ascending order.

It is also possible to define policies that determine when to deletecorresponding hook resources. Hook deletion policies are defined using thefollowing annotation:

  1. annotations:
  2. "helm.sh/hook-delete-policy": hook-succeeded

You can choose one or more defined annotation values: "hook-succeeded" specifies Helm should delete the hook after the hook issuccessfully executed. "hook-failed" specifies Helm should delete the hook if the hook failedduring execution.* "before-hook-creation" specifies Helm should delete the previous hook beforethe new hook is launched.

Automatically uninstall hook from previous release

When helm release being updated it is possible, that hook resource alreadyexists in cluster. By default helm will try to create resource and fail with"… already exists" error.

One might choose "helm.sh/hook-delete-policy": "before-hook-creation" over"helm.sh/hook-delete-policy": "hook-succeeded,hook-failed" because:

  • It is convenient to keep failed hook job resource in kubernetes for examplefor manual debug.
  • It may be necessary to keep succeeded hook resource in kubernetes for somereason.
  • At the same time it is not desirable to do manual resource deletion beforehelm release upgrade."helm.sh/hook-delete-policy": "before-hook-creation" annotation on hook causesHelm to remove the hook from previous release if there is one before the newhook is launched and can be used with another policy.