mirror of https://github.com/helm/helm
Merge pull request #1375 from technosophos/docs/719-best-practices
docs(*): refresh docspull/1389/head
commit
d61d5acb9a
@ -0,0 +1,150 @@
|
||||
# Hooks
|
||||
|
||||
Helm provides a _hook_ mechanism to allow chart developers to intervene
|
||||
at certain 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 backup up a database before installing a new chart,
|
||||
and then execute a second job after the upgrade in order to restore
|
||||
data.
|
||||
- Run a Job before deleting a release to gracefully take a service out
|
||||
of rotation before removing it.
|
||||
|
||||
Hooks work like regular templates, but they have special annotations
|
||||
that cause Helm to utilize them differently. In this section, we cover
|
||||
the basic usage pattern for hooks.
|
||||
|
||||
## The Available Hooks
|
||||
|
||||
The following hooks are defined:
|
||||
|
||||
- pre-install: Executes after templates are rendered, but before any
|
||||
resources are created in Kubernetes.
|
||||
- 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 loaded into Kubernetes (e.g.
|
||||
before a kuberntes apply operation).
|
||||
- post-upgrade: Executes on an upgrade after all resources have been
|
||||
upgraded.
|
||||
|
||||
## Hooks and the Release Lifecycle
|
||||
|
||||
Hooks allow you, the chart developer, an opportunity to perform
|
||||
operations at strategic points in a release lifecycle. For example,
|
||||
consider the lifecycle for a `helm install`. By default, the lifecycle
|
||||
looks like this:
|
||||
|
||||
1. User runs `helm install foo`
|
||||
2. Chart is loaded into Tiller
|
||||
3. After some verification, Tiller renders the `foo` templates
|
||||
4. Tiller loads the resulting resources into Kubernetes
|
||||
5. Tiller returns the release name (and other data) to the client
|
||||
6. The client exits
|
||||
|
||||
Helm defines two hooks for the `install` lifecycle: `pre-install` and
|
||||
`post-install`. If the developer of the `foo` chart implements both
|
||||
hooks, the lifecycle is altered like this:
|
||||
|
||||
1. User runs `helm install foo`
|
||||
2. Chart is loaded into Tiller
|
||||
3. After some verification, Tiller renders the `foo` templates
|
||||
4. Tiller executes the `pre-install` hook (loading hook resources into
|
||||
Kubernetes)
|
||||
5. Tiller waits until the hook is "Ready"
|
||||
6. Tiller loads the resulting resources into Kubernetes
|
||||
7. Tiller executes the `post-install` hook (loading hook resources)
|
||||
8. Tiller waits until the hook is "Ready"
|
||||
9. Tiller returns the release name (and other data) to the client
|
||||
10. The client exits
|
||||
|
||||
What does it mean to wait until a hook is ready? This depends on the
|
||||
resource declared in the hook. If the resources is a `Job` kind, Tiller
|
||||
will wait until the job successfully runs to completion. And if the job
|
||||
fails, the release will fail. This is a _blocking operation_, so the
|
||||
Helm client will pause while the Job is run.
|
||||
|
||||
For all other kinds, as soon as Kubernetes marks the resource as loaded
|
||||
(added or updated), the resource is considered "Ready". When many
|
||||
resources are declared in a hook, the resources are executed serially,
|
||||
but the order of their execution is not guaranteed.
|
||||
|
||||
### Hook resources are unmanaged
|
||||
|
||||
The resources that a hook creates are not tracked or managed as part of the
|
||||
release. Once Tiller verifies that the hook has reached its ready state, it
|
||||
will leave the hook resource alone.
|
||||
|
||||
Practically speaking, this means that if you create resources in a hook, you
|
||||
cannot rely upon `helm delete` to remove the resources. To destroy such
|
||||
resources, you need to write code to perform this operation in a `pre-delete`
|
||||
or `post-delete` hook.
|
||||
|
||||
## Writing a Hook
|
||||
|
||||
Hooks are just Kubernetes manfiest files with special annotations in the
|
||||
`metadata` section. Because they are template files, you can use all of
|
||||
the normal 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`:
|
||||
|
||||
```yaml
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: "{{.Release.Name}}"
|
||||
labels:
|
||||
heritage: {{.Release.Service | quote }}
|
||||
release: {{.Release.Name | quote }}
|
||||
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
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
name: "{{.Release.Name}}"
|
||||
labels:
|
||||
heritage: {{.Release.Service | quote }}
|
||||
release: {{.Release.Name | quote }}
|
||||
chart: "{{.Chart.Name}}-{{.Chart.Version}}"
|
||||
spec:
|
||||
restartPolicy: Never
|
||||
containers:
|
||||
- name: post-install-job
|
||||
image: "alpine:3.3"
|
||||
command: ["/bin/sleep","{{default "10" .Values.sleepyTime}}"]
|
||||
|
||||
```
|
||||
|
||||
What makes this template a hook is the annotation:
|
||||
|
||||
```
|
||||
annotations:
|
||||
"helm.sh/hook": post-install
|
||||
```
|
||||
|
||||
One resource can implement multiple hooks:
|
||||
|
||||
```
|
||||
annotations:
|
||||
"helm.sh/hook": post-install,post-upgrade
|
||||
```
|
||||
|
||||
Similarly, there is no limit to the number of different resources that
|
||||
may implement a given hook. For example, one could declare both a secret
|
||||
as a config map as a pre-install hook. It is important to keep in mind,
|
||||
though, that there are no ordering guarantees about hooks.
|
||||
|
||||
When subcharts declare hooks, those are also evaluated. There is no way
|
||||
for a top-level chart to disable the hooks declared by subcharts. And
|
||||
again, there is no guaranteed ordering.
|
||||
|
@ -0,0 +1,71 @@
|
||||
# Chart Development Tips and Tricks
|
||||
|
||||
This guide covers some of the tips and tricks Helm chart developers have
|
||||
learned while building production-quality charts.
|
||||
|
||||
## Quote Strings, Don't Quote Integers
|
||||
|
||||
When you are working with string data, you are always safer quoting the
|
||||
strings than leaving them as bare words:
|
||||
|
||||
```
|
||||
name: {{.Values.MyName | quote }}
|
||||
```
|
||||
|
||||
But when working with integers _do not quote the values._ That can, in
|
||||
many cases, cause parsing errors inside of Kubernetes.
|
||||
|
||||
```
|
||||
port: {{ .Values.Port }}
|
||||
```
|
||||
|
||||
## Using the 'include' Function
|
||||
|
||||
Go provides a way of including one template in another using a built-in
|
||||
`template` directive. However, the built-in function cannot be used in
|
||||
Go template pipelines.
|
||||
|
||||
To make it possible to include a template, and then perform an operation
|
||||
on that template's output, Helm has a special `include` function:
|
||||
|
||||
```
|
||||
{{ include "toYaml" $value | indent 2 }}
|
||||
```
|
||||
|
||||
The above includes a template called `toYaml`, passes it `$value`, and
|
||||
then passes the output of that template to the `indent` function.
|
||||
|
||||
Because YAML ascribes significance to indentation levels and whitespace,
|
||||
this is one great way to include snippets of code, but handle
|
||||
indentation in a relevant context.
|
||||
|
||||
## Using "Partials" and Template Includes
|
||||
|
||||
Sometimes you want to create some reusable parts in your chart, whether
|
||||
they're blocks or template partials. And often, it's cleaner to keep
|
||||
these in their own files.
|
||||
|
||||
In the `templates/` directory, any file that begins with an
|
||||
underscore(`_`) is not expected to ouput a Kubernetes manifest file. So
|
||||
by convention, helper templates and partials are placed in a
|
||||
`_helpers.tpl` file.
|
||||
|
||||
## YAML is a Superset of JSON
|
||||
|
||||
According to the YAML specification, YAML is a superset of JSON. That
|
||||
means that any valid JSON structure ought to be valid in YAML.
|
||||
|
||||
This has an advantage: Sometimes template developers may find it easier
|
||||
to express a datastructure with a JSON-like syntax rather than deal with
|
||||
YAML's whitespace sensitivity.
|
||||
|
||||
As a best practice, templates should follow a YAML-like syntax _unless_
|
||||
the JSON syntax substantially reduces the risk of a formatting issue.
|
||||
|
||||
## Be Careful with Generating Random Values
|
||||
|
||||
There are functions in Helm that allow you to generate random data,
|
||||
cryptographic keys, and so on. These are fine to use. But be aware that
|
||||
during upgrades, templates are re-executed. When a template run
|
||||
generates data that differs from the last run, that will trigger an
|
||||
update of that resource.
|
Loading…
Reference in new issue