github.com/koderover/helm@v2.17.0+incompatible/docs/charts_hooks.md (about) 1 # Hooks 2 3 Helm provides a _hook_ mechanism to allow chart developers to intervene 4 at certain points in a release's life cycle. For example, you can use 5 hooks to: 6 7 - Load a ConfigMap or Secret during install before any other charts are 8 loaded. 9 - Execute a Job to back up a database before installing a new chart, 10 and then execute a second job after the upgrade in order to restore 11 data. 12 - Run a Job before deleting a release to gracefully take a service out 13 of rotation before removing it. 14 15 Hooks work like regular templates, but they have special annotations 16 that cause Helm to utilize them differently. In this section, we cover 17 the basic usage pattern for hooks. 18 19 Hooks are declared as an annotation in the metadata section of a manifest: 20 21 ```yaml 22 apiVersion: ... 23 kind: .... 24 metadata: 25 annotations: 26 "helm.sh/hook": "pre-install" 27 # ... 28 ``` 29 30 ## The Available Hooks 31 32 The following hooks are defined: 33 34 - pre-install: Executes after templates are rendered, but before any 35 resources are created in Kubernetes. 36 - post-install: Executes after all resources are loaded into Kubernetes 37 - pre-delete: Executes on a deletion request before any resources are 38 deleted from Kubernetes. 39 - post-delete: Executes on a deletion request after all of the release's 40 resources have been deleted. 41 - pre-upgrade: Executes on an upgrade request after templates are 42 rendered, but before any resources are loaded into Kubernetes (e.g. 43 before a Kubernetes apply operation). 44 - post-upgrade: Executes on an upgrade after all resources have been 45 upgraded. 46 - pre-rollback: Executes on a rollback request after templates are 47 rendered, but before any resources have been rolled back. 48 - post-rollback: Executes on a rollback request after all resources 49 have been modified. 50 - crd-install: Adds CRD resources before any other checks are run. This is used 51 only on CRD definitions that are used by other manifests in the chart. 52 - test-success: Executes when running `helm test` and expects the pod to 53 return successfully (return code == 0). 54 - test-failure: Executes when running `helm test` and expects the pod to 55 fail (return code != 0). 56 57 ## Hooks and the Release Lifecycle 58 59 Hooks allow you, the chart developer, an opportunity to perform 60 operations at strategic points in a release lifecycle. For example, 61 consider the lifecycle for a `helm install`. By default, the lifecycle 62 looks like this: 63 64 1. User runs `helm install foo` 65 2. Chart is loaded into Tiller 66 3. After some verification, Tiller renders the `foo` templates 67 4. Tiller loads the resulting resources into Kubernetes 68 5. Tiller returns the release name (and other data) to the client 69 6. The client exits 70 71 Helm defines two hooks for the `install` lifecycle: `pre-install` and 72 `post-install`. If the developer of the `foo` chart implements both 73 hooks, the lifecycle is altered like this: 74 75 1. User runs `helm install foo` 76 2. Chart is loaded into Tiller 77 3. After some verification, Tiller renders the `foo` templates 78 4. Tiller prepares to execute the `pre-install` hooks (loading hook resources into 79 Kubernetes) 80 5. Tiller sorts hooks by weight (assigning a weight of 0 by default) and by name for those hooks with the same weight in ascending order. 81 6. Tiller then loads the hook with the lowest weight first (negative to positive) 82 7. Tiller waits until the hook is "Ready" (except for CRDs) 83 8. Tiller loads the resulting resources into Kubernetes. Note that if the `--wait` 84 flag is set, Tiller will wait until all resources are in a ready state 85 and will not run the `post-install` hook until they are ready. 86 9. Tiller executes the `post-install` hook (loading hook resources) 87 10. Tiller waits until the hook is "Ready" 88 11. Tiller returns the release name (and other data) to the client 89 12. The client exits 90 91 What does it mean to wait until a hook is ready? This depends on the 92 resource declared in the hook. If the resources is a `Job` kind, Tiller 93 will wait until the job successfully runs to completion. And if the job 94 fails, the release will fail. This is a _blocking operation_, so the 95 Helm client will pause while the Job is run. 96 97 For all other kinds, as soon as Kubernetes marks the resource as loaded 98 (added or updated), the resource is considered "Ready". When many 99 resources are declared in a hook, the resources are executed serially. If they 100 have hook weights (see below), they are executed in weighted order. Otherwise, 101 ordering is not guaranteed. (In Helm 2.3.0 and after, they are sorted 102 alphabetically. That behavior, though, is not considered binding and could change 103 in the future.) It is considered good practice to add a hook weight, and set it 104 to `0` if weight is not important. 105 106 107 ### Hook resources are not managed with corresponding releases 108 109 The resources that a hook creates are not tracked or managed as part of the 110 release. Once Tiller verifies that the hook has reached its ready state, it 111 will leave the hook resource alone. 112 113 Practically speaking, this means that if you create resources in a hook, you 114 cannot rely upon `helm delete` to remove the resources. To destroy such 115 resources, you need to either write code to perform this operation in a `pre-delete` 116 or `post-delete` hook or add `"helm.sh/hook-delete-policy"` annotation to the hook template file. 117 118 ## Writing a Hook 119 120 Hooks are just Kubernetes manifest files with special annotations in the 121 `metadata` section. Because they are template files, you can use all of 122 the normal template features, including reading `.Values`, `.Release`, 123 and `.Template`. 124 125 For example, this template, stored in `templates/post-install-job.yaml`, 126 declares a job to be run on `post-install`: 127 128 ```yaml 129 apiVersion: batch/v1 130 kind: Job 131 metadata: 132 name: "{{.Release.Name}}" 133 labels: 134 app.kubernetes.io/managed-by: {{.Release.Service | quote }} 135 app.kubernetes.io/instance: {{.Release.Name | quote }} 136 app.kubernetes.io/version: {{ .Chart.AppVersion }} 137 helm.sh/chart: "{{.Chart.Name}}-{{.Chart.Version}}" 138 annotations: 139 # This is what defines this resource as a hook. Without this line, the 140 # job is considered part of the release. 141 "helm.sh/hook": post-install 142 "helm.sh/hook-weight": "-5" 143 "helm.sh/hook-delete-policy": hook-succeeded 144 spec: 145 template: 146 metadata: 147 name: "{{.Release.Name}}" 148 labels: 149 app.kubernetes.io/managed-by: {{.Release.Service | quote }} 150 app.kubernetes.io/instance: {{.Release.Name | quote }} 151 helm.sh/chart: "{{.Chart.Name}}-{{.Chart.Version}}" 152 spec: 153 restartPolicy: Never 154 containers: 155 - name: post-install-job 156 image: "alpine:3.3" 157 command: ["/bin/sleep","{{default "10" .Values.sleepyTime}}"] 158 159 ``` 160 161 What makes this template a hook is the annotation: 162 163 ``` 164 annotations: 165 "helm.sh/hook": post-install 166 ``` 167 168 One resource can implement multiple hooks: 169 170 ``` 171 annotations: 172 "helm.sh/hook": post-install,post-upgrade 173 ``` 174 175 Similarly, there is no limit to the number of different resources that 176 may implement a given hook. For example, one could declare both a secret 177 and a config map as a pre-install hook. 178 179 When subcharts declare hooks, those are also evaluated. There is no way 180 for a top-level chart to disable the hooks declared by subcharts. 181 182 It is possible to define a weight for a hook which will help build a 183 deterministic executing order. Weights are defined using the following annotation: 184 185 ``` 186 annotations: 187 "helm.sh/hook-weight": "5" 188 ``` 189 190 Hook weights can be positive or negative numbers but must be represented as 191 strings. When Tiller starts the execution cycle of hooks of a particular kind (ex. the `pre-install` hooks or `post-install` hooks, etc.) it will sort those hooks in ascending order. 192 193 It is also possible to define policies that determine when to delete corresponding hook resources. Hook deletion policies are defined using the following annotation: 194 195 ``` 196 annotations: 197 "helm.sh/hook-delete-policy": hook-succeeded 198 ``` 199 200 You can choose one or more defined annotation values: 201 202 * `"hook-succeeded"` specifies Tiller should delete the hook after the hook is successfully executed. 203 * `"hook-failed"` specifies Tiller should delete the hook if the hook failed during execution. 204 * `"before-hook-creation"` specifies Tiller should delete the previous hook before the new hook is launched. 205 206 By default Tiller will wait for 60 seconds for a deleted hook to no longer exist in the API server before timing out. This 207 behavior can be changed using the `helm.sh/hook-delete-timeout` annotation. The value is the number of seconds Tiller 208 should wait for the hook to be fully deleted. A value of 0 means Tiller does not wait at all. 209 210 ### Defining a CRD with the `crd-install` Hook 211 212 Custom Resource Definitions (CRDs) are a special kind in Kubernetes. They provide 213 a way to define other kinds. 214 215 On occasion, a chart needs to both define a kind and then use it. This is done 216 with the `crd-install` hook. 217 218 The `crd-install` hook is executed very early during an installation, before 219 the rest of the manifests are verified. CRDs can be annotated with this hook so 220 that they are installed before any instances of that CRD are referenced. In this 221 way, when verification happens later, the CRDs will be available. 222 223 Here is an example of defining a CRD with a hook, and an instance of the CRD: 224 225 ```yaml 226 apiVersion: apiextensions.k8s.io/v1beta1 227 kind: CustomResourceDefinition 228 metadata: 229 name: crontabs.stable.example.com 230 annotations: 231 "helm.sh/hook": crd-install 232 spec: 233 group: stable.example.com 234 version: v1 235 scope: Namespaced 236 names: 237 plural: crontabs 238 singular: crontab 239 kind: CronTab 240 shortNames: 241 - ct 242 ``` 243 244 And: 245 246 ```yaml 247 apiVersion: stable.example.com/v1 248 kind: CronTab 249 metadata: 250 name: {{ .Release.Name }}-inst 251 ``` 252 253 Both of these can now be in the same chart, provided that the CRD is correctly 254 annotated. 255 256 ### Automatically delete hook from previous release 257 258 When a helm release, that uses a hook, is being updated, it is possible that the hook resource might already exist in the cluster. In such circumstances, by default, helm will fail trying to install the hook resource with an `"... already exists"` error. 259 260 A common reason why the hook resource might already exist is that it was not deleted following use on a previous install/upgrade. There are, in fact, good reasons why one might want to keep the hook: for example, to aid manual debugging in case something went wrong. In this case, the recommended way of ensuring subsequent attempts to create the hook do not fail is to define a `"hook-delete-policy"` that can handle this: `"helm.sh/hook-delete-policy": "before-hook-creation"`. This hook annotation causes any existing hook to be removed, before the new hook is installed. 261 262 If it is preferred to actually delete the hook after each use (rather than have to handle it on a subsequent use, as shown above), then this can be achieved using a delete policy of `"helm.sh/hook-delete-policy": "hook-succeeded,hook-failed"`. 263 264