Helm defines nine helm.sh/hook events — which of them fire during helm upgrade, and which cannot?
answer
- Each event belongs to one command
- An upgrade fires two of the nine
- The first deploy is not an upgrade
- A rollback has its own pair of events
- pre-install,pre-upgrade on one annotation
basics
~20 sOnly pre-upgrade and post-upgrade fire on helm upgrade. The install, delete, rollback and test events belong to their own commands, so a hook that must run on both the first deploy and every later one has to list two events.
solid answer
~40 sThe nine events pair to commands: `pre-install`/`post-install` for `helm install`, `pre-upgrade`/`post-upgrade` for `helm upgrade`, `pre-rollback`/`post-rollback` for `helm rollback`, `pre-delete`/`post-delete` for `helm uninstall`, and `test` for `helm test`. An upgrade therefore fires only the two upgrade events — install hooks never re-run, and a rollback does **not** replay upgrade hooks even though it rewrites the same resources. The trap is `helm upgrade --install`: against a release that does not exist yet it performs an install, so the *install* hooks run and a migration Job annotated only `pre-upgrade` silently never runs on the first deploy. That is why the common annotation is `helm.sh/hook: pre-install,pre-upgrade` — one manifest, both events, comma-separated.
code
yaml · 15 linesapiVersion: batch/v1
kind: Job
metadata:
name: gateway-schema
annotations:
"helm.sh/hook": pre-install,pre-upgrade
spec:
backoffLimit: 0
template:
spec:
restartPolicy: Never
containers:
- name: migrate
image: registry.example.com/gateway-migrator:4.11.2
args: ["migrate", "up"]go deeper
Recall that the events are named after the commands: install, upgrade, rollback, delete, plus test. Knowing that pre-upgrade does not fire on a first install is the single most useful fact to carry away.
Be able to list the nine and say which command fires each, then explain the helm upgrade --install case out loud: no release yet means an install, so install hooks run. Mention the comma-separated multi-event annotation.
Bring the consequence: a migration hook wired to the wrong event fails only on fresh environments, and a rollback never replays upgrade hooks, so schema compatibility — not a clever hook — is what makes rollback safe.
Own the convention across a fleet of charts: which events every chart's lifecycle Jobs are required to name, whether pre-rollback is ever allowed to mutate data, and how a first deploy into a new environment is rehearsed before it is real.
### The nine events and their commands Helm's hook events are not free-floating labels; each is owned by exactly one command. | Event | Fires when | |---|---| | `pre-install` | `helm install`, after rendering, before any resource is created | | `post-install` | `helm install`, after all of the release's resources are applied | | `pre-upgrade` | `helm upgrade`, after rendering, before any resource is updated | | `post-upgrade` | `helm upgrade`, after all resources have been updated | | `pre-rollback` | `helm rollback`, after rendering the target revision, before it is applied | | `post-rollback` | `helm rollback`, after the target revision has been applied | | `pre-delete` | `helm uninstall`, before any resource is deleted | | `post-delete` | `helm uninstall`, after all resources are deleted | | `test` | `helm test`, against an already-installed release | So `helm upgrade` fires exactly two of the nine. Everything else is inert for that command — the install hooks are not re-run, the test hook is not applied, and the delete hooks are untouched. ### The upgrade --install trap `helm upgrade --install` is the idiom every pipeline uses, because it is a single command that works whether or not the release exists. That is exactly what makes it a trap: when the release does not exist, Helm performs an **install**, and an install fires install hooks. A chart whose schema-migration Job is annotated only `pre-upgrade` will therefore run that Job on the second deploy and every deploy after it, and never on the first — the one deploy where an empty database most needs it. The symptom is a workload that crash-loops on a fresh namespace and comes up fine everywhere the chart has been deployed before. Annotate `pre-install,pre-upgrade` and the problem disappears. ```yaml metadata: annotations: "helm.sh/hook": pre-install,pre-upgrade ``` A comma-separated list on one annotation is the supported form; you do not need two copies of the manifest. ### Rollback does not replay upgrade hooks `helm rollback` re-applies a previous revision's stored manifest, which means it writes the same kinds of objects an upgrade writes. It nevertheless fires `pre-rollback` and `post-rollback`, never the upgrade events. This matters most for data. If your only migration hook is `pre-upgrade`, a rollback restores the old application image against a database the old code may not understand, and nothing runs to reverse the schema change. Helm does not solve that for you; the chart author has to decide, deliberately, whether a `pre-rollback` hook exists and what it does — and in practice most teams answer it by making migrations backward compatible instead. ### Uninstall and test `pre-delete` and `post-delete` are the only chance a chart gets to do something on the way out — deregister from a discovery service, snapshot state, release a lease. They fire on `helm uninstall`, before and after the release's resources are removed. `test` is different in kind from all the others: a manifest annotated `helm.sh/hook: test` is rendered and stored with every operation but applied by nothing except `helm test`, run by a human or a pipeline against a release that is already installed. ### How Helm gets there At each event Helm applies that event's hooks and blocks until they report ready before continuing — for a Job, until it has completed. A hook that fails stops the operation; the rest of that phase does not proceed. Nothing about this changed between Helm 3 and Helm 4, and the event names have been stable for the life of Helm 3. ### The rule of thumb Write the annotation from the *command*, not from the intent. "Run before the app starts" is not an event; `helm install` and `helm upgrade` are two different commands and you must name both if you mean both. Charts that get this wrong usually work in the environment they were developed in — where the release already exists — and break the first time someone deploys them somewhere new.
- A pipeline runs helm upgrade --install against a namespace for the first time. Which hooks run?The install hooks. With no existing release, that command performs an install, so `pre-install` and `post-install` fire and the upgrade events do not. A chart whose migration Job is annotated only `pre-upgrade` therefore skips migrating on exactly the deploy where the database is empty — which is why the annotation is almost always written `pre-install,pre-upgrade`.
- Does helm rollback re-run the pre-upgrade hooks, since it rewrites the same resources?No. A rollback fires `pre-rollback` and `post-rollback` only. Nothing automatically reverses what an upgrade hook did, so if your migration ran forward on the way up, the rollback puts the old image in front of the new schema. Either write a deliberate `pre-rollback` hook or, far more commonly, keep migrations backward compatible so the old code still works.
- Can anything other than helm test apply a manifest annotated helm.sh/hook: test?No. The `test` event is not part of install, upgrade, rollback or uninstall; those operations render and store the manifest but never apply it. It is applied only when `helm test` is run against an installed release, which is what makes it safe to ship a test Pod inside a production chart.
saying these in an interview costs you the question
- Says pre-install hooks also fire on every upgrade
- Assumes helm upgrade --install always fires upgrade hooks
- Expects a rollback to replay the pre-upgrade migration
- Thinks helm uninstall runs post-upgrade hooks
- Believes one annotation cannot name two events
- Claims a test hook runs during install