Managing Helm Charts and Releases Without the Headaches
Helm is the de facto package manager for Kubernetes: it bundles manifests into versioned, parameterized charts and tracks installed instances as releases. Used carelessly it becomes a source of mysterious drift; used with discipline it makes deployments boring in the best way.
The mental model
- Chart — a package of templated manifests plus default values.
- Values — the parameters that fill in the templates.
- Release — a named, versioned installation of a chart in a cluster.
- Revision — each upgrade bumps the release revision, enabling rollback.
Anatomy of a chart
mychart/
Chart.yaml # name, version, appVersion
values.yaml # default values
templates/ # templated manifests
deployment.yaml
service.yaml
_helpers.tpl # reusable template snippets
charts/ # vendored subcharts
Templates use Go templating against values: {{ .Values.image.tag }}. Keep logic in templates minimal and push complexity into values.yaml where it is reviewable.
Values and overrides
Defaults live in values.yaml; environments override what differs. Layer files instead of forking charts:
helm install api ./mychart \
-f values.yaml \
-f values-prod.yaml \
--set image.tag=1.8.0
Later files and --set flags win. Resist the urge to override dozens of values on the command line — put them in a per-environment values file you can review and version.
Install, upgrade, and the safety net
Use upgrade --install so the same command works first time and every time after:
helm upgrade --install api ./mychart \
-f values-prod.yaml \
--atomic --timeout 5m
Two flags do a lot of work here. --atomic rolls back automatically if the upgrade fails, so you never sit in a half-applied state. --timeout bounds how long Helm waits for resources to become ready.
See what will change first
Render templates locally before touching the cluster, and diff against what is live (with the helm-diff plugin):
helm template api ./mychart -f values-prod.yaml | less
helm diff upgrade api ./mychart -f values-prod.yaml
Release history and rollback
Helm records every revision, which is the feature that makes upgrades low-risk.
helm history api
helm rollback api 3
Rolling back to a known-good revision is one command — no scrambling to reconstruct old manifests.
Common pitfalls
- Manual edits to Helm-managed objects. Editing a Deployment that Helm owns causes drift; the next upgrade may overwrite or conflict with your change. Change values and upgrade instead.
- Forgetting CRDs. Helm installs CRDs from the
crds/directory but does not upgrade or delete them. Manage CRD lifecycle deliberately. - Stuck releases. A failed install can leave a release in
pending-install. Inspect withhelm status, and clean up rather than forcing a second install on top. - Secrets in values files. Do not commit plaintext secrets in
values-prod.yaml; reference a secret manager or use an external secrets operator. - Unpinned dependencies. Pin subchart versions in
Chart.yamlso a freshhelm dependency updatedoes not silently pull a new major.
Helm with GitOps
Pairing Helm with a GitOps tool (Argo CD, Flux) keeps the cluster reconciled to a Git-defined desired state, which eliminates the drift that comes from ad-hoc helm upgrade runs on someone's laptop. The chart and values live in Git; the controller applies them.
Inspecting releases at a glance
When an upgrade misbehaves, the questions are always the same: which revision is live, what changed, and what did it actually deploy? Kubexer surfaces release history, revisions, and the rendered values so you can spot the bad revision and roll back without spelunking through CLI output — the same Helm workflow, with the state laid out in front of you.
Wrapping up
Use upgrade --install --atomic, layer values files per environment, diff before you apply, keep secrets out of values, and lean on revision history for painless rollbacks. Helm rewards a disciplined, version-controlled workflow and punishes manual fiddling.