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