Helm Charts¶
On this page
Helm is the package manager for Kubernetes. Charts template your manifests, values parameterize them, and releases track what's installed so you can upgrade and roll back.
Basics¶
Helm packages Kubernetes manifests into versioned, reusable units called charts. Instead of hand-editing dozens of YAML files per environment, you template them once and supply different values.
Key terms¶
| Term | Meaning |
|---|---|
| Chart | A package of templated K8s manifests + metadata + default values. |
| Values | Configuration that fills the templates (values.yaml, --set, -f). |
| Release | An installed instance of a chart in a cluster (named, versioned, revisioned). |
| Repository | A place to host/share charts (HTTP or OCI registry). |
| Template | A manifest with Go templating + Sprig functions. |
Helm 3 is client-only (no Tiller); it talks straight to the Kubernetes API and stores release state as Secrets in the cluster.
Chart structure¶
mychart/
├── Chart.yaml # name, version, appVersion, dependencies
├── values.yaml # default configuration
├── templates/
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── _helpers.tpl # reusable template snippets
│ └── NOTES.txt # post-install message
├── charts/ # vendored sub-charts (dependencies)
└── templates/tests/ # `helm test` hooks
Templating¶
Templates use {{ .Values.x }}, {{ .Release.Name }}, {{ .Chart.Name }}, control flow
(if/range/with), named templates (define/include), and Sprig helper functions.
# templates/deployment.yaml (excerpt)
spec:
replicas: {{ .Values.replicaCount }}
template:
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
resources:
{{- toYaml .Values.resources | nindent 12 }}
Cheatsheet¶
# Repos (classic HTTP repo)
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm search repo nginx
helm search hub wordpress # search Artifact Hub
# Install / upgrade / rollback
helm install web ./mychart -n app --create-namespace
helm install web bitnami/nginx -f prod-values.yaml
helm upgrade --install web ./mychart -n app \
--set replicaCount=3 --atomic --wait
helm list -n app
helm status web -n app
helm history web -n app
helm rollback web 2 -n app # revert to revision 2
helm uninstall web -n app
# Author & debug
helm create mychart
helm lint ./mychart
helm template web ./mychart -f prod-values.yaml # render locally, no cluster
helm install web ./mychart --dry-run --debug
helm get values web -n app
helm get manifest web -n app
# Dependencies
helm dependency update ./mychart # pull sub-charts in Chart.yaml
# OCI registries (modern)
helm push mychart-1.0.0.tgz oci://ghcr.io/moin/charts
helm install web oci://ghcr.io/moin/charts/mychart --version 1.0.0
Thumb Rules¶
Rules of thumb
helm upgrade --installis your default — it works whether or not the release exists.- Use
--atomic --waitso a failed upgrade rolls back automatically instead of leaving a half-broken release. helm template/--dry-run --debugbefore applying to see exactly what will be created.- Pin chart versions (
--version) in CI; don't float on whatever's latest. - Keep one
values.yamlper environment and layer with-f base.yaml -f prod.yaml. - Don't put secrets in plain
values.yaml. Use helm-secrets/SOPS or external secret stores. appVersion≠ chartversion. Bump chart version on any template change.- Prefer upstream charts you understand; vendor/fork rather than over-patch with
--setsprawl.
Use Cases¶
- Installing off-the-shelf software (databases, ingress controllers, monitoring stacks) in one command.
- Packaging your own apps for repeatable, multi-environment deploys.
- Templating across environments (dev/stage/prod) from one chart + many values files.
- Release lifecycle management — versioned upgrades and instant rollbacks.
- GitOps building block — Argo CD/Flux render Helm charts as part of pipelines.
- Umbrella charts — compose a whole platform from sub-charts.
Common Issues¶
UPGRADE FAILED / release stuck in pending-upgrade
A previous upgrade was interrupted. Inspect helm history, then helm rollback to the
last good revision. Using --atomic prevents getting stuck here.
Template renders wrong / nil pointer evaluating interface
A value referenced in a template isn't set. Provide a default (| default), guard with
if, and validate with helm template --debug.
Indentation / YAML errors after templating
Misused nindent/indent, or toYaml without proper indentation. Render locally and
eyeball the output; nindent N adds a newline + N spaces.
Immutable field error on upgrade
Changing an immutable field (e.g. a Deployment selector, a PVC size on some StorageClasses). You may need to delete/recreate the resource.
CRDs not installed / out of date
Helm installs CRDs from crds/ only on first install and won't upgrade them. Manage CRD
upgrades explicitly.
Resources left behind after uninstall
Resources with helm.sh/resource-policy: keep, or CRDs/PVCs Helm intentionally doesn't
delete. Clean up manually if needed.
Best Practices¶
- Default to
helm upgrade --install --atomic --waitfor safe, idempotent deploys. - Lint and
helm templatein CI; addhelm testhooks for smoke tests. - Version charts semantically; keep a changelog; pin versions in deployments.
- Layer values files per environment; keep secrets out of Git (SOPS/External Secrets).
- Use
_helpers.tplfor consistent labels/names; follow the recommended label conventions. - Vendor dependencies with a lockfile (
Chart.lock) for reproducibility. - Prefer OCI registries for distributing charts alongside images.
- Document
values.yamlthoroughly — it's your chart's public API.
Official Sources¶
- Helm Documentation — https://helm.sh/docs/
- Charts guide — https://helm.sh/docs/topics/charts/
- Chart template guide — https://helm.sh/docs/chart_template_guide/
- Best practices — https://helm.sh/docs/chart_best_practices/
- Helm commands reference — https://helm.sh/docs/helm/
- Artifact Hub (find charts) — https://artifacthub.io/
- Sprig template functions — https://masterminds.github.io/sprig/