mirror of
https://github.com/helmfile/helmfile.git
synced 2026-09-30 20:41:38 +02:00
* feat: add --write-output flag to helmfile fetch for air-gapped environments Add --write-output flag to helmfile fetch that outputs a modified helmfile.yaml with chart references updated to point to downloaded local chart paths. Combined with --output-dir, this enables preparing all charts for deployment in air-gapped environments. Usage: helmfile fetch --output-dir ./charts --write-output > helmfile-airgapped.yaml Fixes #2571 Signed-off-by: yxxhero <yxxhero@users.noreply.github.com> Signed-off-by: yxxhero <aiopsclub@163.com> * docs: restructure documentation and improve newcomer experience Split the monolithic index.md (1990 lines) into focused topic pages, update mkdocs.yml navigation, and add missing documentation for undocumented code features. Structure changes: - Extract configuration.md (helmfile.yaml reference) - Extract cli.md (CLI commands and flags) - Extract templating.md (template syntax and env vars) - Extract environments.md (environment configuration) - Extract releases.md (DAG, needs, selectors) - Extract hooks.md (lifecycle hooks) - Extract integrations.md (ArgoCD, Azure ACR, OCI) - Slim index.md to ~270 line landing page with step-by-step tutorial Newcomer improvements: - Add 5-step Getting Started tutorial with explanations - Reorganize nav: Getting Started now shows core learning path (Writing Helmfile → Values → Environments → Releases) - Add Quick Reference table to configuration.md - Simplify writing-helmfile.md title Code-vs-docs gap fixes: - Document 23 undocumented release fields (valuesTemplate, setTemplate, forceNamespace, adopt, trackMode, etc.) - Document 6 undocumented helmDefaults fields (enableDNS, forceConflicts, skipRefresh, takeOwnership, etc.) - Document print-env command and missing CLI flags - Document kubectlApply hook field - Document environment defaults field and merge order - Document kubedogQPS/kubedogBurst advanced settings - Document template partials (_*.tpl) auto-loading Cleanup: - Fix Docker image version from v0.156.0 to v1.1.0 - Fix heading nesting in advanced-features.md - Update experimental-features.md with current features - Fix broken cross-references and anchor links Signed-off-by: yxxhero <aiopsclub@163.com> * Revert changes to pkg/app from docs/restructure-and-improve branch Signed-off-by: yxxhero <aiopsclub@163.com> * docs: add create subcommand to README and CLI reference Signed-off-by: yxxhero <aiopsclub@163.com> --------- Signed-off-by: yxxhero <yxxhero@users.noreply.github.com> Signed-off-by: yxxhero <aiopsclub@163.com>
295 lines
9.5 KiB
Markdown
295 lines
9.5 KiB
Markdown
# Hooks
|
||
|
||
## Hooks
|
||
|
||
A Helmfile hook is a per-release extension point that is composed of:
|
||
|
||
* `events`
|
||
* `command`
|
||
* `args`
|
||
* `showlogs`
|
||
* `kubectlApply` (alternative to `command`/`args`)
|
||
|
||
Helmfile triggers various `events` while it is running.
|
||
Once `events` are triggered, associated `hooks` are executed, by running the `command` with `args`. The standard output of the `command` will be displayed if `showlogs` is set and it's value is `true`.
|
||
|
||
Hooks exec order follows the order of definition in the helmfile state.
|
||
|
||
Currently supported `events` are:
|
||
|
||
* `prepare`
|
||
* `preapply`
|
||
* `presync`
|
||
* `preuninstall`
|
||
* `postuninstall`
|
||
* `postsync`
|
||
* `cleanup`
|
||
|
||
Hooks associated to `prepare` events are triggered after each release in your helmfile is loaded from YAML, before execution.
|
||
`prepare` hooks are triggered on the release as long as it is not excluded by the helmfile selector(e.g. `helmfile -l key=value`).
|
||
|
||
Hooks associated to `presync` events are triggered before each release is synced (installed or upgraded) on the cluster.
|
||
This is the ideal event to execute any commands that may mutate the cluster state as it will not be run for read-only operations like `lint`, `diff` or `template`.
|
||
|
||
`preapply` hooks are triggered before a release is uninstalled, installed, or upgraded as part of `helmfile apply`.
|
||
This is the ideal event to hook into when you are going to use `helmfile apply` for every kind of change. Note that preapply hooks will only run if at least one release has changes to apply. Be sure to make each `preapply` hook command idempotent. Otherwise, rerunning `helmfile apply` on a transient failure may end up either breaking your cluster, or the hook that runs for the second time will never succeed.
|
||
|
||
`preuninstall` hooks are triggered immediately before a release is uninstalled as part of `helmfile apply`, `helmfile sync`, `helmfile delete`, and `helmfile destroy`.
|
||
|
||
`postuninstall` hooks are triggered immediately after successful uninstall of a release while running `helmfile apply`, `helmfile sync`, `helmfile delete`, `helmfile destroy`.
|
||
|
||
`postsync` hooks are triggered after each release is synced (installed or upgraded) on the cluster, regardless if the sync was successful or not.
|
||
This is the ideal place to execute any commands that may mutate the cluster state as it will not be run for read-only operations like `lint`, `diff` or `template`.
|
||
|
||
`cleanup` hooks are triggered after each release is processed.
|
||
This is the counterpart to `prepare`, as any release on which `prepare` has been triggered gets `cleanup` triggered as well.
|
||
|
||
The following is an example hook that just prints the contextual information provided to hook:
|
||
|
||
```yaml
|
||
releases:
|
||
- name: myapp
|
||
chart: mychart
|
||
# *snip*
|
||
hooks:
|
||
- events: ["prepare", "cleanup"]
|
||
showlogs: true
|
||
command: "echo"
|
||
args: ["{{`{{.Environment.Name}}`}}", "{{`{{.Release.Name}}`}}", "{{`{{.HelmfileCommand}}`}}\
|
||
"]
|
||
```
|
||
|
||
Let's say you ran `helmfile --environment prod sync`, the above hook results in executing:
|
||
|
||
```
|
||
echo {{Environment.Name}} {{.Release.Name}} {{.HelmfileCommand}}
|
||
```
|
||
|
||
Whereas the template expressions are executed thus the command becomes:
|
||
|
||
```
|
||
echo prod myapp sync
|
||
```
|
||
|
||
Now, replace `echo` with any command you like, and rewrite `args` that actually conforms to the command, so that you can integrate any command that does:
|
||
|
||
* templating
|
||
* linting
|
||
* testing
|
||
|
||
Hooks expose additional template expressions:
|
||
|
||
`.Event.Name` is the name of the hook event.
|
||
|
||
`.Event.Error` is the error generated by a failed release, exposed for `postsync` hooks only when a release fails, otherwise its value is `nil`.
|
||
|
||
You can use the hooks event expressions to send notifications to platforms such as `Slack`, `MS Teams`, etc.
|
||
|
||
The following example passes arguments to a script which sends a notification:
|
||
|
||
```yaml
|
||
releases:
|
||
- name: myapp
|
||
chart: mychart
|
||
# *snip*
|
||
hooks:
|
||
- events:
|
||
- presync
|
||
- postsync
|
||
showlogs: true
|
||
command: notify.sh
|
||
args:
|
||
- --event
|
||
- '{{`{{ .Event.Name }}`}}'
|
||
- --status
|
||
- '{{`{{ if .Event.Error }}failure{{ else }}success{{ end }}`}}'
|
||
- --environment
|
||
- '{{`{{ .Environment.Name }}`}}'
|
||
- --namespace
|
||
- '{{`{{ .Release.Namespace }}`}}'
|
||
- --release
|
||
- '{{`{{ .Release.Name }}`}}'
|
||
```
|
||
|
||
For templating, imagine that you created a hook that generates a helm chart on-the-fly by running an external tool like ksonnet, kustomize, or your own template engine.
|
||
It will allow you to write your helm releases with any language you like, while still leveraging goodies provided by helm.
|
||
|
||
### Hooks, Kubectl and Environments
|
||
|
||
Hooks can also be used in combination with small tasks using `kubectl` directly,
|
||
e.g.: in order to install a custom storage class.
|
||
|
||
In the following example, a specific release depends on a custom storage class.
|
||
Further, all enviroments have a default kube context configured where releases are deployed into.
|
||
The `.Environment.KubeContext` is used in order to apply / remove the YAML to the correct context depending on the environment.
|
||
|
||
`environments.yaml`:
|
||
|
||
```yaml
|
||
environments:
|
||
dev:
|
||
values:
|
||
- ../values/default.yaml
|
||
- ../values/dev.yaml
|
||
kubeContext: dev-cluster
|
||
prod:
|
||
values:
|
||
- ../values/default.yaml
|
||
- ../values/prod.yaml
|
||
kubeContext: prod-cluster
|
||
```
|
||
|
||
`helmfile.yaml`:
|
||
|
||
```yaml
|
||
bases:
|
||
- ./environments.yaml
|
||
|
||
---
|
||
releases:
|
||
- name: myService
|
||
namespace: my-ns
|
||
installed: true
|
||
chart: mychart
|
||
version: "1.2.3"
|
||
values:
|
||
- ../services/my-service/values.yaml.gotmpl
|
||
hooks:
|
||
- events: ["presync"]
|
||
showlogs: true
|
||
command: "kubectl"
|
||
args:
|
||
- "apply"
|
||
- "-f"
|
||
- "./custom-storage-class.yaml"
|
||
- "--context"
|
||
- "{{`{{.Environment.KubeContext}}`}}"
|
||
- events: ["postuninstall"]
|
||
showlogs: true
|
||
command: "kubectl"
|
||
args:
|
||
- "delete"
|
||
- "-f"
|
||
- "./custom-storage-class.yaml"
|
||
- "--context"
|
||
- "{{`{{.Environment.KubeContext}}`}}"
|
||
```
|
||
|
||
### Global Hooks
|
||
|
||
In contrast to the per release hooks mentioned above these are run only once at the very beginning and end of the execution of a helmfile command and only the `prepare` and `cleanup` hooks are available respectively.
|
||
|
||
They use the same syntax as per release hooks, but at the top level of your helmfile:
|
||
|
||
```yaml
|
||
hooks:
|
||
- events: ["prepare", "cleanup"]
|
||
showlogs: true
|
||
command: "echo"
|
||
args: ["{{`{{.Environment.Name}}`}}", "{{`{{.HelmfileCommand}}`}}\
|
||
"]
|
||
```
|
||
|
||
### Helmfile + Kustomize
|
||
|
||
Do you prefer `kustomize` to write and organize your Kubernetes apps, but still want to leverage helm's useful features
|
||
like rollback, history, and so on? This section is for you!
|
||
|
||
The combination of `hooks` and [helmify-kustomize](https://gist.github.com/mumoshu/f9d0bd98e0eb77f636f79fc2fb130690)
|
||
enables you to integrate [kustomize](https://github.com/kubernetes-sigs/kustomize) into Helmfile.
|
||
|
||
That is, you can use `kustomize` to build a local helm chart from a kustomize overlay.
|
||
|
||
Let's assume you have a kustomize project named `foo-kustomize` like this:
|
||
|
||
```
|
||
foo-kustomize/
|
||
├── base
|
||
│ ├── configMap.yaml
|
||
│ ├── deployment.yaml
|
||
│ ├── kustomization.yaml
|
||
│ └── service.yaml
|
||
└── overlays
|
||
├── default
|
||
│ ├── kustomization.yaml
|
||
│ └── map.yaml
|
||
├── production
|
||
│ ├── deployment.yaml
|
||
│ └── kustomization.yaml
|
||
└── staging
|
||
├── kustomization.yaml
|
||
└── map.yaml
|
||
|
||
5 directories, 10 files
|
||
```
|
||
|
||
Write `helmfile.yaml`:
|
||
|
||
```yaml
|
||
- name: kustomize
|
||
chart: ./foo
|
||
hooks:
|
||
- events: ["prepare", "cleanup"]
|
||
command: "../helmify"
|
||
args: ["{{`{{if eq .Event.Name \"prepare\"}}build{{else}}clean{{end}}`}}", "{{`{{.Release.Ch\
|
||
art}}`}}", "{{`{{.Environment.Name}}`}}"]
|
||
```
|
||
|
||
Run `helmfile --environment staging sync` and see it results in helmfile running `kustomize build foo-kustomize/overlays/staging > foo/templates/all.yaml`.
|
||
|
||
Voilà! You can mix helm releases that are backed by remote charts, local charts, and even kustomize overlays.
|
||
|
||
### kubectlApply Hook
|
||
|
||
Instead of specifying `command` and `args`, you can use the `kubectlApply` field to run `kubectl apply` directly:
|
||
|
||
```yaml
|
||
releases:
|
||
- name: myapp
|
||
chart: mychart
|
||
hooks:
|
||
- events: ["presync"]
|
||
showlogs: true
|
||
kubectlApply:
|
||
filename: manifests/custom-resource.yaml
|
||
```
|
||
|
||
Or apply a kustomize overlay:
|
||
|
||
```yaml
|
||
hooks:
|
||
- events: ["presync"]
|
||
showlogs: true
|
||
kubectlApply:
|
||
kustomize: overlays/default/
|
||
```
|
||
|
||
The `kubectlApply` field accepts either:
|
||
* `filename:` - runs `kubectl apply -f <value>`
|
||
* `kustomize:` - runs `kubectl apply -k <value>`
|
||
|
||
**Note:** `filename` and `kustomize` cannot be used together. When `kubectlApply` is set, the `command` field is ignored with a warning.
|
||
|
||
### Hook Template Data
|
||
|
||
Hooks have access to the following template data:
|
||
|
||
Per-release hooks:
|
||
* `{{ .Environment.Name }}` - the environment name
|
||
* `{{ .Environment.KubeContext }}` - the environment kube context
|
||
* `{{ .Release.Name }}` - the release name
|
||
* `{{ .Release.Namespace }}` - the release namespace
|
||
* `{{ .Release.Labels }}` - the release labels
|
||
* `{{ .Release.Chart }}` - the release chart
|
||
* `{{ .Values }}` - state values
|
||
* `{{ .HelmfileCommand }}` - the helmfile command name (e.g., `sync`, `apply`)
|
||
* `{{ .Event.Name }}` - the hook event name
|
||
* `{{ .Event.Error }}` - the error (available in `postsync` hooks when a release fails)
|
||
|
||
Global hooks:
|
||
* `{{ .Environment.Name }}` - the environment name
|
||
* `{{ .HelmfileCommand }}` - the helmfile command name
|
||
* `{{ .Event.Name }}` - the hook event name
|
||
* `{{ .Event.Error }}` - the error
|
||
|