Helm
Helm
Definition: The package manager for Kubernetes (K8s), letting teams define, install, and upgrade complex Kubernetes applications as reusable, versioned bundles called “charts” instead of hand-writing and hand-applying sprawling YAML manifests. Helm was created by Deis, a PaaS startup later acquired by Microsoft in 2017, with its first release in 2015; the project was donated to the Cloud Native Computing Foundation in 2018 and has since become the de-facto standard for packaging and distributing software that runs on Kubernetes. Helm 3, released in 2019, removed the server-side Tiller component that defined Helm 2, simplifying both its security model and its architecture considerably.
Core Services & Concepts
- Charts — bundled, templated sets of Kubernetes manifests for an application, packaged with a
Chart.yamlmetadata file, defaultvalues.yaml, and atemplates/directory - Values files — configuration overrides (
values.yaml, or custom files passed with-f) that customize a chart for a specific environment without editing the chart’s templates themselves - Releases — a specific deployed instance of a chart in a cluster, identified by a release name and namespace, trackable and upgradeable as a single unit
- Revisions — every
helm upgradecreates a new numbered revision of a release, with the full history retained sohelm rollbackcan revert to any prior one - Templating engine — Go templates combined with the Sprig function library, letting
{{ .Values.replicaCount }}-style expressions, conditionals, and loops generate final YAML from a chart’s templates and supplied values - Dependencies (subcharts) — charts can declare other charts as dependencies in
Chart.yaml, letting a complex application (e.g. a web app plus its database) be composed from smaller, independently maintained charts - Hooks — lifecycle annotations (
pre-install,post-upgrade,pre-delete, etc.) that run specific Kubernetes jobs at defined points in a release’s lifecycle - OCI registry support — modern Helm can push and pull charts as OCI artifacts to and from standard container registries (ECR, GHCR, Docker Hub), converging chart distribution with image distribution
How It Works: The Templating and Release Model
helm installrenders a chart’s templates locally by mergingvalues.yamlwith any overrides, substituting the results into Go template expressions to produce plain Kubernetes YAML- The rendered manifests are submitted to the Kubernetes API, and Helm records the release as an object in the cluster (stored as a Secret by default in Helm 3), capturing the manifests, values, and metadata for that revision
helm upgradere-renders the chart with new values or a new chart version, computes what changed, and applies it using a three-way merge — comparing the previous manifest, the newly rendered manifest, and the live cluster state — similar in spirit tokubectl apply- Every install or upgrade creates a new revision in the release’s history, nothing is overwritten, which is what makes
helm rollback <release> <revision>possible helm rollbackworks by re-applying the manifests recorded for an earlier revision, effectively treating history as a stack of known-good states rather than recomputing anything from source
How Pricing Works
- Helm itself is free and open-source (Apache 2.0 license) under CNCF governance, no cost to install or run the CLI
- Artifact Hub, the central place to discover charts, is a free CNCF-hosted service, not a paid product
- Chart repositories cost only whatever it costs to host static files (or an OCI registry), which is often already part of existing infrastructure
- Individual charts may deploy commercial software with its own licensing (e.g. a chart installing a paid database), that cost comes from the software itself, not from Helm
- No usage-based billing exists anywhere in the core Helm workflow, the only spend is the underlying Kubernetes cluster and whatever the installed charts themselves cost to run
Pros
- Turns sprawling, repetitive Kubernetes YAML into reusable, parameterized, versioned packages
- Huge library of community-maintained charts for common software — databases, monitoring stacks, ingress controllers — installable in one command
- Makes upgrades and rollbacks of complex, multi-resource applications far simpler than manually tracking and reapplying YAML diffs
- Dependency management lets a complex application be composed from smaller, independently versioned subcharts
- Vendor-neutral, works identically across any conformant Kubernetes cluster regardless of cloud provider
Cons
- Combining Go templating syntax with YAML’s whitespace sensitivity is a well-known source of subtle, hard-to-debug rendering errors
- Poorly written or overly clever charts can obscure what’s actually being deployed, making debugging and review harder than reading plain manifests
- Helm 2’s Tiller component carried real security baggage (broad in-cluster permissions), a legacy that still shapes some teams’ wariness even though Helm 3 removed it entirely
- Large charts riddled with conditionals can become their own mini programming language, hard to reason about without rendering them first
- No first-class equivalent to Terraform’s
plan, previewing an upgrade’s actual effect on the cluster generally requires the separatehelm diffplugin
Comparison: Helm vs Kustomize vs Raw Kubernetes Manifests
| Helm | Kustomize | Raw Manifests | |
|---|---|---|---|
| Approach | Templated packages with values | Overlay-based patching, no templating | Hand-written YAML, no abstraction |
| Packaging | Versioned charts, shareable via repos/OCI | No packaging format, just YAML + patches | None, copy-paste or manual scripting |
| Config reuse | Values files per environment | Base + overlay directories per environment | Typically duplicated files per environment |
| Best fit | Distributing complex, reusable third-party or internal apps | Environment-specific tweaks to otherwise-static manifests | Small, simple deployments with little variation |
Best For
- Packaging and distributing complex, multi-resource Kubernetes applications as a single installable, upgradeable unit
- Standardizing how an organization deploys the same application across dev, staging, and production
- Installing third-party infrastructure software onto a cluster without hand-writing its Kubernetes manifests
Real Examples
- Nearly every popular open-source tool that runs on Kubernetes ships an official Helm chart, including Prometheus, Grafana, and cert-manager
- The Bitnami chart library is one of the most widely used sources of production-ready charts for common databases and application stacks
- The ingress-nginx project distributes its controller almost exclusively via its official Helm chart as the recommended installation method
Use Cases
- Installing third-party software (databases, monitoring stacks, ingress controllers) onto a Kubernetes cluster in a single command
- Templating an application’s Kubernetes configuration consistently across dev, staging, and production environments
- Packaging an organization’s internal applications for repeatable deployment across many clusters or customer environments
- Managing multi-service releases as one atomic, versioned unit with built-in rollback if an upgrade goes wrong
- Feeding rendered manifests into GitOps pipelines, where tools like Argo CD or Flux install charts as part of a continuous delivery workflow
Integration Notes & Common Pitfalls
- Always run
helm templateorhelm install --dry-runbefore a real install/upgrade, rendering locally first catches broken values before they ever touch the cluster - Install the
helm-diffplugin for anything touching production, native Helm doesn’t show a plan-style preview of what an upgrade will actually change - Pin chart versions explicitly and commit
Chart.lock, an unpinned dependency updating mid-project can silently change what gets deployed - Be deliberate about hook failure handling, a failed lifecycle hook can leave orphaned Kubernetes resources behind if not cleaned up carefully
- Watch for resource ownership conflicts when two releases manage overlapping resources, Helm tracks ownership via annotations and will refuse or clash if that overlaps unexpectedly
Code Example
# Chart.yaml
apiVersion: v2
name: my-app
version: 0.1.0
appVersion: "1.4.0"
dependencies:
- name: postgresql
version: "13.x.x"
repository: "https://charts.bitnami.com/bitnami"
---
# values.yaml
replicaCount: 2
image:
repository: myorg/my-app
tag: "1.4.0"
service:
port: 80
---
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-my-app
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ .Release.Name }}
template:
metadata:
labels:
app: {{ .Release.Name }}
spec:
containers:
- name: my-app
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
ports:
- containerPort: {{ .Values.service.port }}
Code Example: CLI Workflow
# Add a chart repository and refresh its index
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
# Preview rendered manifests without installing anything
helm template my-release ./my-app --values values-prod.yaml
# Install, or upgrade if the release already exists (idempotent in CI)
helm upgrade --install my-release ./my-app -f values-prod.yaml
# Check what would change before a real upgrade (helm-diff plugin)
helm diff upgrade my-release ./my-app -f values-prod.yaml
# Roll back to the previous revision after a bad upgrade
helm rollback my-release
Ecosystem
- Artifact Hub — the CNCF-hosted central search engine for Helm charts across many repositories, the successor to the retired Helm Hub
- Bitnami charts — one of the largest, most widely used libraries of production-ready charts for common open-source software
- Helm plugins — extensions like
helm-diff(preview changes before upgrading) andhelm-secrets(encrypted values integration) that fill gaps in the core CLI - OCI registries — any standard container registry supporting OCI artifacts can now double as a chart registry, reducing the need for separate chart-hosting infrastructure
Best Practices
- Render with
helm templateor--dry-runbefore every real install or upgrade, especially against production - Use
helm difffor production upgrades, treating it as the closest available equivalent to Terraform’s plan step - Pin chart and dependency versions, and commit
Chart.lockso installs are reproducible across machines and CI - Keep values layered by environment (
values.yamlplusvalues-prod.yaml) rather than maintaining several fully separate charts - Extract repeated template logic into named templates in
_helpers.tplto keep individual manifest templates readable
FAQ
Does Helm still use Tiller? No — Tiller was the server-side component in Helm 2 that required broad in-cluster permissions; Helm 3 (2019) removed it entirely, making Helm a client-only tool that acts using the invoking user’s own Kubernetes RBAC permissions.
What’s the difference between a release and a revision? A release is the overall named, deployed instance of a chart in a cluster; a revision is one specific version of that release’s history, incremented on every install or upgrade, which is what rollback targets.
Can I preview what a helm upgrade will change before running it?
Not natively with full detail, helm template and --dry-run render the output, but seeing an actual diff against the live cluster generally requires the separate helm-diff plugin.
How do chart dependencies (subcharts) work?
A chart declares other charts as dependencies in Chart.yaml, and Helm pulls and bundles them so a complex application can be composed from smaller, independently maintained charts installed together as one release.
Where are Helm charts actually hosted?
Either in traditional chart repositories (a static index.yaml plus packaged .tgz files) or, increasingly, in standard OCI-compliant container registries alongside container images.
Common Interview Questions
- “Explain Helm’s release and revision model, and how rollback works” — expect an answer covering versioned release history and reapplying a prior revision’s recorded manifests
- “Why was Tiller removed in Helm 3?” — expect discussion of the security risk of a broadly privileged in-cluster server component and the shift to client-side RBAC-scoped operations
- “What is a Helm hook, and can you give an example?” — expect an explanation of lifecycle annotations like
pre-installorpost-upgradetied to Kubernetes jobs - “What’s the difference between
helm templateandhelm install?” — expect a distinction between purely local rendering versus rendering plus actually applying manifests to a live cluster
History
- Created by Deis, a PaaS startup, with its first release in 2015 as a way to simplify installing applications on Kubernetes
- Helm 2 (2016) introduced Tiller, a server-side in-cluster component that handled installs and upgrades on the client’s behalf
- Microsoft acquired Deis in 2017, continuing investment in Helm as part of its broader Kubernetes and Azure strategy
- Helm was donated to the Cloud Native Computing Foundation in 2018, moving it under the same vendor-neutral governance as Kubernetes itself
- Helm 3 shipped in November 2019, removing Tiller entirely, adding JSONSchema values validation and library charts, and laying groundwork for OCI registry support
Related Terms
Referenced by