In a Helm chart, what do .Release.IsInstall, .Release.IsUpgrade and .Release.Revision report?
answer
- They describe the operation, not the chart
- One is true on a first deploy only
- The number bound is the one being created
- A guarded object vanishes from the next manifest
- Install gives 1, upgrade gives the next
basics
~20 sThey describe the operation currently rendering. On install, IsInstall is true, IsUpgrade is false and Revision is 1. On upgrade the first two swap and Revision is the number of the revision being created, one higher than the current one.
solid answer
~40 sHelm binds these three on `.Release` before rendering so a template can branch on the operation. `helm install` gives `IsInstall: true`, `IsUpgrade: false`, `Revision: 1`. `helm upgrade` gives `IsInstall: false`, `IsUpgrade: true`, and `Revision` set to the revision about to be created - the current one plus one, not the current one. `helm upgrade --install` on a release that does not yet exist takes the install path, so `IsInstall` is true there. The trap is using them to emit a resource only on install: the object is then absent from the next upgrade's manifest, and Helm deletes objects that the previous manifest had and the new one lacks, so the first upgrade removes it. Gate a one-time job with a hook, not with `IsInstall`, unless deletion is what you want.
code
yaml · 10 linesspec:
template:
metadata:
annotations:
ledger.example.com/release-revision: {{ .Release.Revision | quote }}
ledger.example.com/first-deploy: {{ .Release.IsInstall | quote }}
spec:
containers:
- name: ledger
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}go deeper
Memorise the two states: install gives IsInstall true and Revision 1; upgrade gives IsUpgrade true and a higher Revision. Know that .Release.Name and .Release.Namespace do not change between them.
Explain that Revision is the revision being created, and that upgrade --install picks its path from whether the release exists. Be ready to describe what a conditional resource does to the next manifest.
Demonstrate the deletion trap: a resource that renders only on install disappears on the first upgrade and Helm removes it. Say why a hook is the right tool for a once-only task, and why rollback shows a stale revision inside its manifest.
Set the guidance: these fields shape an object's contents, hooks control an object's lifetime. Decide whether charts in your estate may branch on the operation at all, since it makes install and upgrade produce structurally different manifests.
### What the three fields are for `.Release` is the built-in object that describes the operation in flight rather than the chart. Three of its members change with the operation: `IsInstall`, `IsUpgrade` and `Revision`. They exist so a template can produce different YAML for a first install than for a subsequent upgrade - seeding a database only once, skipping a migration job on the very first deploy, or stamping a revision number into an annotation. ### The values, precisely On `helm install`: `IsInstall` is `true`, `IsUpgrade` is `false`, and `Revision` is `1`. On `helm upgrade`: `IsInstall` is `false`, `IsUpgrade` is `true`, and `Revision` is the number of the revision that this operation is *creating*. If the release is currently at revision 6, the templates render with `Revision: 7`. Getting this backwards is the classic mistake: the render happens before the new revision is stored, but the number bound is the new one, not the old one. On `helm upgrade --install` the answer depends on the cluster, not the flag. If no release of that name exists, Helm runs the install path and `IsInstall` is true; if one exists, it is an upgrade like any other. A chart that assumes "the flag means upgrade" is wrong roughly once per environment - on the very first deploy of each. `helm template` renders offline, and by default renders as if installing: `IsInstall` true, `Revision` 1. It can be asked to render in upgrade mode instead, which matters when you are trying to reproduce what a real upgrade would have produced. `helm rollback` is the interesting case, because it does not re-render at all. Rollback re-applies the manifest that was stored with the target revision. Anything a template computed from these three fields is frozen at the value it had when that revision was originally rendered, even though the release record itself gains a brand-new, higher revision number. So a release at revision 9 rolled back to revision 4 becomes revision 10, while every annotation inside its manifest still says 4. `.Release` also carries three members that do not vary with the operation: `Name`, the release name fixed at install time; `Namespace`, the namespace the operation targets; and `Service`, which is always the literal string `Helm`. ### The deletion trap The single most-asked follow-up on this topic is what happens to a resource guarded by `IsInstall`. Consider a payments ledger chart that seeds its schema with a Job: {{- if .Release.IsInstall }} apiVersion: batch/v1 kind: Job ... {{- end }} That does exactly what the author wanted on install: the Job renders and runs. Then someone runs an upgrade. The Job is not in the new render, so it is not in the new manifest. Helm compares the previous release's manifest with the new one and deletes what has disappeared - so the first upgrade *deletes the Job*, along with whatever record of the seed run its completion carried. If the Job is still running, the delete lands on a live object. That behaviour is correct and by design - it is how removing a template from a chart removes the resource - but it is almost never what an `IsInstall` guard was written for. The right tool for a one-time task tied to a phase is a hook, whose lifetime Helm manages with the hook annotations, rather than a conditional whose only effect is to make an object vanish from the next manifest. The mirror-image trap is a resource guarded by `IsUpgrade`. It never exists after an install, appears on the first upgrade, and now behaves like a normal managed object, so a later render that drops it deletes it again. ### Where they are safe Where these fields genuinely earn their place is in *content*, not in existence. Putting `{{ .Release.Revision }}` into a pod-template annotation is a common way to force a rollout on every upgrade of a 41-service platform chart even when nothing else in the pod spec changed - the pod template hash changes, so the workload rolls. Setting a value differently on install than on upgrade (a bootstrap flag, a "skip migration" env var) is fine too, because the object still exists in both manifests. The rule of thumb: use `IsInstall` and `IsUpgrade` to change what is *inside* an object, and use hooks to control what only happens *once*. Use `Revision` for annotations and change-detection, never as part of a resource's name, because a name that moves every upgrade is a delete-and-recreate every upgrade.
- A template emits a seed Job only when .Release.IsInstall is true. What happens on the first upgrade?The Job is absent from the new render, so it is absent from the new manifest, and Helm deletes resources the previous manifest had and the new one lacks - the upgrade deletes the Job. If it is still running, the delete hits a live object. A one-time task belongs in a hook, whose lifecycle Helm manages explicitly, rather than behind an `IsInstall` guard.
- During helm upgrade, is .Release.Revision the current revision or the new one?The new one. A release sitting at revision 6 renders its upgrade templates with `Revision: 7`, because the value bound is the revision the operation is creating. That is what makes it usable as a rollout-forcing annotation: it differs from the value baked into the previous manifest.
- What do these fields evaluate to during helm rollback?Nothing re-evaluates them. Rollback re-applies the manifest stored with the target revision rather than re-rendering the chart, so whatever those fields produced when that revision was first rendered is what gets applied. Meanwhile the release history gains a new, higher revision number, so the recorded revision and the number inside the manifest legitimately disagree.
- With helm upgrade --install, which of IsInstall and IsUpgrade is true?It depends on whether a release of that name already exists, not on the flag. First run on a fresh namespace takes the install path and `IsInstall` is true; every run after that is an upgrade. Charts that assume the flag always means upgrade break exactly once per environment - on its first deploy.
saying these in an interview costs you the question
- Says Revision is the current revision during an upgrade
- Assumes upgrade --install always sets IsUpgrade true
- Uses IsInstall to make a one-time Job, unaware it is deleted
- Thinks rollback re-renders templates with new values
- Claims .Release carries an install timestamp
- Puts .Release.Revision into a resource name