Helm
Kubernetes' package manager: charts of templated manifests, values that override per environment, and releases with a revision history you can roll back. An upgrade without a rollback is an outage.
on this pageshowhide
guide
overview
~1 minHelm packages Kubernetes manifests as **charts**: Go templates plus a file of default values, rendered on your machine and applied to the cluster as a named **release** whose every revision is recorded. Interviewers use it to find out whether you can trace what happens between a values file and a running Pod, and whether you know what Helm stops knowing once the command exits. A good Helm answer keeps three things apart: what the chart renders, what the release record says was applied, and what is actually live in the cluster. The hub follows a chart from disk to production. [Chart structure](/topics/cloud-helm-chart-structure) is the layout every other section refers to. [Templating and values](/topics/cloud-helm-templating-values) is the render pipeline, where most Helm bugs live and where questions dig deepest. [Releases and upgrades](/topics/cloud-helm-releases-upgrades) is the largest section: the state machine behind install, upgrade, rollback and uninstall, and what it leaves behind when a step fails. [Hooks and tests](/topics/cloud-helm-hooks-tests) covers migration Jobs and smoke tests; [dependencies and repositories](/topics/cloud-helm-dependencies-repos) covers subcharts, lockfiles and distribution. The operator's side is [operating and triage](/topics/cloud-helm-operations), [chart trust and secrets](/topics/cloud-helm-security) and [delivery and extensibility](/topics/cloud-helm-delivery); the author's side is [authoring for reuse](/topics/cloud-helm-authoring). [Alternatives and boundaries](/topics/cloud-helm-alternatives) asks when a chart is the wrong tool. Junior rounds stay on commands and files: which value wins, what `helm upgrade --install` is for, where a release lives. Senior rounds turn into incident and design conversations — a release stuck mid-upgrade, a CRD that never changed, a controller fighting Helm over a field, a values file other teams now depend on. Learn the chart layout and the render pipeline first, then the release lifecycle. Hooks and dependencies make sense after that; security, delivery and authoring build on all three.
primer
### Rendering happens on the client Since Helm 3 there is no in-cluster component. The CLI loads the chart, merges values, runs the templates and sends ordinary Kubernetes objects to the API server, using the credentials of whoever ran the command. Two consequences follow. Most rendering bugs can be reproduced without a cluster, by rendering and reading the YAML. And the permissions a release gets are the installer's, not the chart's, which is why installing a chart is a trust decision. ### Values are the chart's interface A chart's defaults and the caller's overrides are merged into one untyped map before any template sees it, in a fixed order that decides which setting wins. Nothing checks that a key is used or spelled right unless the chart ships a JSON schema. For an author, the default values file is a public API: renaming or moving a key breaks every consumer's override file, and interviewers expect you to version it that way. ### Templates generate text, not objects The template engine knows nothing about YAML. It pastes strings into a document that is parsed only afterwards, so indentation, whitespace trimming and quoting decide whether the output is the object you meant, a different one, or invalid. Named templates and helpers exist to keep labels and names consistent across files, and a helper wrong in one place is wrong everywhere. ### A release is a record, not a watcher Each install, upgrade or rollback writes a new **revision** into the release's namespace, holding the chart, the supplied values, the rendered manifest and a status. History, rollback and the next upgrade's comparison all read from that record. Once the command ends, nothing watches the cluster: hand edits, controller changes and deleted objects are invisible to Helm until it runs again. The record also keeps every value you passed, secrets included. ### Every upgrade ends in a single verdict An upgrade renders, compares against the previous stored manifest, applies the difference, optionally waits, and ends as deployed or failed. The ways it breaks are few and worth knowing by name — a failing hook, an API-server rejection, a field that cannot change, an apiVersion the cluster no longer serves, a timeout, or a process killed mid-write that leaves a pending status behind. Each leaves the cluster in a different state and calls for a different next command. ### Helm deliberately leaves some things alone Helm will not update or delete CRDs shipped in `crds/`, will not undo what a hook already did, will not adopt objects it did not create without their ownership metadata or an explicit instruction, and a rollback re-applies manifests without touching data. Senior answers name these boundaries before proposing a fix. ### A chart is a versioned artifact Charts carry a SemVer version separate from the application's, are packaged into archives, published to a repository index or an OCI registry, and depend on other charts through version ranges pinned by a lockfile. Treat a chart release like a library release: its version must tell consumers when an upgrade will break them.
- Chart
- A directory, or packaged archive, holding Chart.yaml, templates and default values that together describe one installable application for Kubernetes.
- Chart version
- The SemVer version of the chart package itself, used for resolution and archive names; independent of the version of the application it deploys.
- values.yaml
- The chart's default configuration. Callers override it with -f files and --set flags; the merged result is what templates read as .Values.
- Values schema
- An optional values.schema.json that Helm validates the merged values against before rendering, turning type errors and typos into failures.
- Named template
- A reusable template fragment defined with define, usually in a helpers file, and called from many manifests to keep names and labels consistent.
- Built-in objects
- The top-level data Helm hands every template, such as .Values, .Release, .Chart, .Files and .Capabilities.
- Release
- One installed instance of a chart in a namespace, identified by name. The same chart can be installed as many releases.
- Revision
- One numbered entry in a release's history, written by each install, upgrade or rollback.
- Release record
- The stored form of a revision, a Secret by default, holding the chart, supplied values, rendered manifest and status.
- Hook
- A manifest annotated to run at a lifecycle point, such as before an upgrade, outside the release's ordinary manifest set.
- Subchart
- A chart bundled inside another as a dependency, rendered as part of the parent's release and configured through the parent's values.
- Umbrella chart
- A parent chart whose main job is to install several subcharts together as one release.
- Chart.lock
- The lockfile recording the exact dependency versions resolved from Chart.yaml ranges, so later builds fetch the same subcharts.
- OCI registry
- A container registry used to store and pull charts as OCI artifacts, addressed with oci:// references instead of a repository index.
- Post-renderer
- An external program that receives Helm's rendered manifests and returns modified ones, which then become the release's manifest.
Follow one `helm upgrade` through the system. Helm first resolves the chart — a local directory, an archive, a name looked up in a cached repository index, or an `oci://` reference — along with the subcharts vendored under `charts/`. It merges values from the chart's defaults, each parent and subchart, and the caller's files and flags, validates the result against a schema if one exists, and renders every template with the built-in objects bound. It loads the previous revision from the release record, runs any pre-upgrade hooks and waits for them, applies the difference between the old stored manifest and the new render, waits as the chosen strategy says, runs post-upgrade hooks, and writes the new revision with its final status. Every section of the hub attaches to one step of that path: - **Chart structure, dependencies and repositories** decide what gets loaded before rendering starts. - **Templating and values** is the merge and render; **authoring for reuse** is the same step seen from the chart author's chair. - **Releases and upgrades, hooks and tests** are the apply, wait and record steps and their failure modes. - **Operating and triage** reads the record back and compares it with the live cluster. - **Delivery** changes who runs the path — a person, a pipeline, or a GitOps controller that may render the chart itself and never write a release record. - **Security** asks whose templates run in the render and whose credentials perform the apply. A few lines of one template show how much of that path a single manifest carries: ```yaml metadata: name: {{ include "web.fullname" . }} labels: {{- include "web.labels" . | nindent 4 }} spec: template: metadata: annotations: checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} spec: containers: - name: web image: "{{ .Values.image.repository }}:{{ required "set image.tag" .Values.image.tag }}" ``` The helper calls keep names and labels identical across files; if the same helper also feeds a selector, a version label inside it becomes an immutable-field failure on the next upgrade. The checksum turns a config edit into a Pod-template change, so the rollout is the workload controller's, not Helm's. The `required` call moves a missing tag from an image-pull error in the cluster to a failed render on the laptop.
- Chart Structure →
What a chart is on disk: metadata, templates, defaults and CRDs. Every other section refers to these files.
- Templating & Values →
The render pipeline from supplied values to emitted YAML, where most Helm bugs start and interviews dig deepest.
- Releases & Upgrades →
What install, upgrade and rollback write to the cluster and the release record, and how each can fail.
- Hooks & Tests →
Lifecycle hooks and chart tests; they make sense only once the release lifecycle they plug into is clear.
- Dependencies & Repositories →
Subcharts, lockfiles, repositories and OCI registries: where a chart's parts come from and where it gets published.
- Operating & Triage →
Reading a release somebody else installed and turning a failed upgrade message into the next command.
Treating
helm statusorhelm listas the truth about the cluster: they report the last recorded operation, not whether live objects still match it.Calling
b64encprotection for a password passed in values: it is encoding, and the plaintext also sits in every retained release record.Expecting a new chart version's CRD change to land on
helm upgrade, when CRDs incrds/are installed once and never updated by Helm.Assuming a rollback undoes a migration: it re-applies old manifests, while schema changes made by a hook Job stay in the database.
Putting version-bearing labels into a Deployment selector through a shared helper, so the next chart bump hits an immutable-field error.
Answering a stuck pending release by deleting release Secrets by hand before checking whether another Helm process is still running.
Relying on a misspelled override without a values schema: the typo is merged silently, and the template keeps rendering the default.
Deploying an unrendered third-party chart: render it with your real values first, because its templates run with your credentials.
Describing Helm as a reconciler: it applies once and exits, so drift persists until somebody runs it again — see Charts Versus Operators.
This guide assumes **Helm 4**, released in late 2025, with Helm 3 still common in production and in interview questions. Three eras still come up: - **Helm 2** ran a server-side component, Tiller, inside the cluster. Questions about Tiller's permissions or release storage in Tiller's namespace describe Helm 2 and should be answered as history. - **Helm 3** removed Tiller, kept release records in each release's namespace, introduced chart `apiVersion: v2`, and later made OCI registry support generally available (3.8). Most tutorials, pipelines and charts in the wild were written against it. - **Helm 4** changed several defaults that older answers get wrong: it moved to server-side apply, so field-ownership conflicts surface as errors rather than silent overwrites; `--wait` names a strategy instead of being a plain switch; `helm list` shows every status by default; and plugin installs verify signatures unless you opt out. It reads Helm 3 release records in place and still installs v2 charts, so moving the CLI needs no data migration. When an answer depends on apply mode, wait behaviour or flag names, say which major version you mean; [Moving to Helm 4](/topics/cloud-helm-operations-helm3-to-helm4) covers the differences in detail.
Helm is usually placed against three alternatives. **Kustomize**, built into kubectl, patches complete YAML with overlays instead of generating it from templates; it is easier to review and keeps no release history, while Helm parameterises harder and records every revision. **Operators** run a controller that keeps reconciling custom resources; they suit software whose day-two operations need logic, where a chart only installs and upgrades on demand. **Plain manifests** win when nothing varies between deployments. Around it sit the tools it is combined with. GitOps controllers such as Argo CD and Flux take a chart and values from Git and deploy them continuously, and whether a release record exists depends on how the controller drives the chart. Helmfile and umbrella charts are two answers to deploying many releases together. Chart repositories, OCI registries and discovery sites such as Artifact Hub are where charts are published and found, and linting plus rendered-diff checks in CI are where they are reviewed. [Alternatives and Boundaries](/topics/cloud-helm-alternatives) argues each choice in both directions.
explore
- Chart Structure20 questions
- Chart Metadata4 questions
- Templates & Helpers4 questions
- Defaults & Schema4 questions
- CRD Lifecycle4 questions
- Packaging a Chart4 questions
- Templating & Values35 questions
- Values Precedence4 questions
- Reusing Previous Values4 questions
- Built-in Objects4 questions
- Named Templates4 questions
- Template Functions4 questions
- Whitespace & Indentation4 questions
- Scope & Control Flow3 questions
- Capabilities & Lookup4 questions
- Debugging a Render4 questions
- Releases & Upgrades46 questions
- Install & Upgrade4 questions
- Release Storage5 questions
- Server-Side Apply4 questions
- Ownership & Adoption4 questions
- Install Ordering4 questions
- Wait Strategies4 questions
- Rollback on Failure4 questions
- Rollback & History4 questions
- Immutable Fields5 questions
- Stuck Releases4 questions
- Uninstall & Leftovers4 questions
- Dependencies & Repositories30 questions
- Declaring Subcharts4 questions
- Conditions & Tags4 questions
- Lockfile & Vendoring4 questions
- Subchart Values5 questions
- Chart Repositories4 questions
- OCI Registries5 questions
- Publishing a Chart4 questions
- Hooks & Tests19 questions
- Hook Events4 questions
- Hook Ordering4 questions
- Hook Cleanup3 questions
- Migration Jobs4 questions
- Chart Tests4 questions
- Alternatives & Boundaries12 questions
- Versus Kustomize4 questions
- Charts Versus Operators4 questions
- Deciding Against a Chart4 questions
- Operating & Triage24 questions
- Inspecting a Release4 questions
- API Deprecations4 questions
- Failed Upgrade Triage4 questions
- Moving to Helm 44 questions
- Client Environment4 questions
- Drift & Change Preview4 questions
- Chart Trust & Secrets20 questions
- Provenance & Signing4 questions
- Installer Permissions4 questions
- Secrets in Values4 questions
- Third-Party Charts4 questions
- Rendering Untrusted Values4 questions
- Delivery & Extensibility20 questions
- Charts in a Pipeline4 questions
- GitOps Rendering4 questions
- Post-Renderers4 questions
- Environment Promotion4 questions
- CLI Plugins4 questions
- Authoring for Reuse24 questions
questions
250 · 10 sectionsIn a Helm Chart.yaml, what is the difference between version and appVersion?
basics
~20 sversion is the chart package's own version and must be valid SemVer 2; Helm names the tarball, indexes and resolves the chart from it. appVersion is a free-form label naming the application release the chart ships, and Helm never parses it.
How does Helm treat a chart's crds/ directory differently from templates/?
basics
~10 sFiles under crds/ are plain YAML that Helm never renders as templates. Helm applies them before anything in templates/, skips any CustomResourceDefinition already present in the cluster, and never updates or deletes them.
What does helm package produce, and what determines the archive's filename?
basics
~20 shelm package compresses a chart directory into a gzipped tar named <name>-<version>.tgz, with both parts read from Chart.yaml. The version must be valid SemVer 2, and the archive unpacks into one directory named for the chart.
Which files under a Helm chart's templates/ directory do not become Kubernetes manifests?
basics
~20 sHelm evaluates every file under templates/, but output from a file whose name begins with an underscore or a dot never becomes a manifest. NOTES.txt becomes the release notes, and a file rendering to only whitespace is dropped.
What does `helm show values` print for a Helm chart, and why is values.yaml the chart's public API?
basics
~20 shelm show values prints a chart's values.yaml exactly as the author wrote it, comments included, without installing or rendering anything. That file is the chart's default surface: every key a consumer may override, and the value they get if they do not.
In a Helm chart, which built-in objects are bound before the templates render?
basics
~10 sHelm binds .Values, .Release, .Chart, .Files, .Capabilities, .Template and, in a parent chart, .Subcharts. .Values holds the merged user values, .Release describes this install, and .Chart mirrors Chart.yaml with capitalized field names.
Why does Helm's `lookup` function return nothing when a chart is rendered with `helm template`?
basics
~20 shelm template never contacts an API server, so Helm's lookup has nothing to query and returns an empty map rather than failing. Only a render that reaches a cluster — a real install, an upgrade, or --dry-run=server — fills it in.
How do you render a Helm chart to YAML locally, and what does helm template --show-only do?
basics
~20 shelm template <release-name> <chart> renders the chart with the values you pass and prints the resulting YAML to stdout — no cluster call, no release record. Adding -s/--show-only templates/job.yaml limits the output to that one template file's manifests.
In a Helm chart template, how do the `default` and `required` functions differ?
basics
~20 sHelm's default function substitutes a fallback when a values entry is empty, so the render continues. required does the opposite: it aborts the whole render with the message you wrote. Use default for optional settings, required where no safe fallback exists.
In a Helm chart, what is the difference between `{{ include "x" . }}` and `{{ template "x" . }}`?
basics
~20 sinclude is a function Helm adds: it renders a named template and returns the output as a string, so it can be piped into other functions. template is a Go template action that writes straight to the output and yields no value.
A `helm upgrade` fails with `field is immutable` — what happened, and what state is the release left in?
basics
~20 sThe Kubernetes API server rejected the write because the chart's new manifest changes a field that cannot change after the object was created — a Deployment's spec.selector is the classic one. Helm records the attempt as a failed revision and the live object keeps its old spec.
What does `helm upgrade --install` do, and why do CI pipelines prefer it to `helm install`?
basics
~20 shelm upgrade --install upgrades a release when one with that name already exists in the namespace and installs it when none does. Pipelines use it because the same command works on the first deploy and every deploy after it.
In what order does Helm apply the resources rendered from a chart's templates/ directory?
basics
~10 sHelm sorts every rendered manifest by Kubernetes kind using a fixed, hard-coded list: Namespace first, then config and RBAC, then Service, then workloads, then Ingress. File names under templates/ do not decide the order.
Why does helm install fail with "exists and cannot be imported into the current release"?
basics
~20 sAn object of that kind and name is already in the cluster and does not carry this release's Helm ownership metadata. Helm refuses to overwrite anything it cannot prove belongs to the release being applied.
Where does Helm store the record of a release, and what is inside it?
basics
~20 sHelm writes one Secret per release revision into the release's own namespace, named sh.helm.release.v1.<name>.v<rev> with type helm.sh/release.v1. It carries the chart, the values supplied, the rendered manifest and the status, as JSON that is gzipped and base64-encoded.
In a Helm Chart.yaml dependency, what does the condition field do, and what happens if its values path is absent?
basics
~20 scondition names a dotted values path, such as database.enabled, on a Chart.yaml dependency entry. If that path resolves to a boolean, it decides whether Helm renders that subchart at all. If the path is absent, the condition is ignored and the dependency stays enabled.
What does an entry in a Helm chart's Chart.yaml dependencies list declare?
basics
~20 sEach dependencies entry declares one subchart the chart bundles: name is the chart to fetch, version is a SemVer range the fetched chart must satisfy, and repository says where to fetch it from. Optional fields such as alias refine that.
How does Helm's oci:// reference address a chart, on the command line and in a Chart.yaml dependency?
basics
~20 sAn oci:// reference is a registry path whose last segment is the chart name and whose tag is the chart version. Commands take the whole path; a Chart.yaml dependency puts the path without the chart name in repository, and the chart name in name.
How do you publish a packaged Helm chart so others can install it with helm repo add?
basics
~20 sCollect the packaged .tgz files in one directory, run helm repo index on that directory to generate index.yaml, and serve the directory over HTTP. A chart repository is static files - no chart-server software is required.
What does `helm repo add` store locally, and why does a newly published chart version stay invisible until `helm repo update`?
basics
~20 shelm repo add saves a name-to-URL entry in your local repositories.yaml and downloads that repository's index.yaml into a cache directory. Helm resolves chart names from that cached copy and never refreshes it on its own, so a version published after your last helm repo update is invisible.
What does `helm test` do when you run it against an installed release?
basics
~20 shelm test looks up an installed release, creates the manifests in it that carry the helm.sh/hook: test annotation - usually Pods - waits for them to finish in the release namespace, and reports pass or fail through its exit code.
What does the helm.sh/hook annotation do to a manifest in a Helm chart's templates/ directory?
basics
~20 sIt turns that manifest into a lifecycle hook. Helm keeps it out of the release manifest and applies it on its own at the named point, such as pre-install or post-upgrade, waiting for it to succeed before the operation continues.
How does a Helm chart run a database schema migration before the new pods start?
basics
~20 sShip the migration as a Kubernetes Job template inside the chart, annotated with helm.sh/hook set to pre-install,pre-upgrade. Helm applies that Job and waits for it to complete before applying the chart's own manifests, so the schema changes before any new pod starts.
What do the three values of Helm's helm.sh/hook-delete-policy do, and which applies when it is omitted?
basics
~20 sbefore-hook-creation deletes an object of the same kind and name just before the hook is created; hook-succeeded deletes it once the hook succeeds; hook-failed deletes it when the hook fails. With the annotation absent, Helm applies before-hook-creation.
Helm defines nine helm.sh/hook events — which of them fire during helm upgrade, and which cannot?
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.
How do Helm and Kustomize differ in how they produce the final manifests applied to a cluster?
basics
~20 sHelm renders a chart's Go templates against values, so the final YAML is generated from files that are not YAML. Kustomize patches complete YAML instead. Helm also stores each apply as a release; kubectl apply -k stores nothing.
Why is helm upgrade described as a one-shot apply rather than a reconcile loop?
basics
~20 shelm upgrade runs once: it renders the chart, sends the result to the API server, records a new release revision and exits. Nothing then watches the cluster, so drift survives until somebody runs Helm again.
Why can you run helm rollback on a release but not undo a kubectl apply -k the same way?
basics
~20 sEach helm install or upgrade stores the rendered manifest, its values and a status as a release revision in a namespace Secret, so helm rollback can re-apply an earlier one. kubectl apply -k stores nothing; undoing it means rebuilding the older source.
What does dropping a Helm release for plain kubectl apply actually cost you?
basics
~20 sYou lose the release record: the stored manifest and values per revision, helm history and helm rollback, membership tracking that prunes removed resources and cleans up on uninstall, hook ordering, helm test, and the wait behaviour Helm applies after writing.
When do plain Kubernetes manifests applied with kubectl beat writing a Helm chart?
basics
~20 sWhen there is one deployment target and nothing genuinely varies between deployments. A chart then adds Chart.yaml, templates/ and a values indirection to produce the YAML you already wrote, and reviewers must render it to see what ships.
How does the Helm CLI decide which cluster and namespace a command targets?
basics
~20 sHelm keeps no target state of its own. It acts on the kubeconfig's current context unless --kube-context overrides it, and targets the namespace from -n, else HELM_NAMESPACE, else the namespace recorded on that context, else default.
When you replace the Helm 3 CLI with Helm 4, what happens to releases already installed in the cluster?
basics
~20 sNothing has to be done to them. Helm 4 adopts Helm 3 releases in place: the release record is still a Secret in the same format and v2 charts still install, so there is no migration tool and nothing to convert.
What does `helm list` show by default, and how do its namespace and status flags change that?
basics
~20 shelm list shows releases in one namespace - the current kube context's, or the one -n names; -A lists every namespace. Helm 4 lists all statuses by default, so flags like --failed narrow the list rather than widening it.
Why does helm upgrade still fail on a removed apiVersion after the chart was fixed to emit the supported one?
basics
~20 sBecause Helm must decode the previous release's stored manifest on every upgrade, and that text is frozen at install time. Fixing the chart changes what you render, not the retired apiVersion already recorded with the live release.
Why does `helm status` still report a release as deployed after someone hand-edits its live objects?
basics
~20 sHelm stores the manifest it applied in the release record and never watches the cluster afterwards. helm status reads that record, so it reports the outcome of the last operation, not whether the live objects still match it.
Helm runs entirely client-side — which identity actually creates a release's Kubernetes objects?
basics
~20 sThe caller's own kubeconfig identity. Helm 3 and 4 ship no in-cluster server component: the CLI renders the chart locally, then writes every rendered object — and the release record — as whoever ran the command.
What does b64enc in a Helm chart's Secret template protect, and what does it not?
basics
~20 sNothing confidential. b64enc is base64 encoding, needed only because a Kubernetes Secret's data field must hold base64 text. It is reversible by anyone, and the same plaintext still sits in the values file and in the stored release record.
Why does a Helm chart write {{ .Values.image.tag | quote }} instead of the bare value?
basics
~20 sA values entry is caller input pasted into YAML before anything parses it. Unquoted, its characters are read as YAML syntax: 1.10 becomes 1.1, off becomes a boolean, a newline can add fields. quote forces one string scalar.
Before installing a third-party Helm chart, how do you see every object it will create?
basics
~20 sRender it before you trust it: helm template, run with the values you will actually install with, prints every manifest the chart applies and touches no cluster. Add --include-crds — the chart's crds/ directory is excluded by default.
Does helm install verify a chart's provenance by default, and how do you turn it on?
basics
~20 sNo. Helm checks a chart's OpenPGP signature only when you pass --verify, and only if the publisher signed the chart with helm package --sign so a .prov file exists, and the public key sits in the keyring you point --keyring at.
Why run both helm lint and helm template as merge checks on a chart?
basics
~20 shelm lint loads the chart, renders it and reports structural problems as an exit code, so it works as a pass/fail gate. helm template prints the manifests the chart produces, so a reviewer can diff the YAML the change actually generates.
How does applying helm template output with kubectl differ from running helm install?
basics
~20 shelm template only renders a chart to YAML on stdout; helm install renders it, applies it, and records the release in the namespace. Objects applied from rendered YAML have no release record, so helm list, helm history and helm rollback see nothing.
What does Helm's --post-renderer flag do to a chart's rendered manifests?
basics
~20 sHelm pipes its rendered manifest stream into another program's stdin and uses the YAML that program returns on stdout. That returned YAML becomes the release's manifest, so you can patch a chart you do not own without forking it.
How do you run one Helm chart across dev, staging and production without forking it?
basics
~20 sKeep one chart whose values.yaml holds the defaults true everywhere, then pass a small per-environment file at deploy time: helm upgrade -f values/prod.yaml. Only keys that genuinely differ live in that file; the chart is identical everywhere.
Why do deploy jobs run helm upgrade --install rather than helm install?
basics
~20 shelm install fails when the release name already exists and helm upgrade fails when it does not, so neither is safe to re-run. helm upgrade --install picks whichever applies, letting one deploy job serve a first deploy and every later one.