What Is Helm? The Kubernetes Package Manager Explained
YAML sprawl is the Kubernetes tax. Helm solves it with packages, templating, releases, and rollbacks — here's how it works and how to ship your first chart.
Published on • October 11, 2026
AI Assistant

A production Kubernetes app isn’t one YAML file — it’s a Deployment, a Service, a ConfigMap, an Ingress, a ServiceAccount, maybe a CronJob and a PDB, each with environment-specific values for staging and production. Copy-pasting that folder across environments is where drift and 2 a.m. typos begin. Helm is the package manager that turns that folder into a versioned, parameterized, installable — and uninstallable — unit.
What Helm actually is
The Helm documentation describes it as “the package manager for Kubernetes,” and the analogy to apt, yum, or npm is accurate: you install packages, upgrade them, roll them back, and share them through registries.
Four concepts cover the whole model:
| Concept | Analogy | What it is |
|---|---|---|
| Chart | .deb / npm package | A template bundle of Kubernetes manifests + metadata |
| Release | Installed instance | One deployed instance of a chart in a cluster |
| Repository | apt/npm registry | Where charts are stored and shared |
| Values | Config file | Parameters that customize the templates |
helm install myapp ./chart --set image.tag=v2.1 creates a release named myapp. The same chart can be installed twice with different values (myapp-staging, myapp-prod) — the chart is the code, the release is the running deployment with its own state.
(Helm 4 is out as of this writing — the core model above is unchanged, but check the Helm 4 overview if you’re starting fresh.)
Why teams adopt it
-
Templating kills YAML duplication. One chart, many environments:
image: repository: registry.example.com/myapp tag: {{ .Values.image.tag }} replicas: {{ .Values.replicaCount }} -
Install/uninstall is atomic and tracked.
helm uninstall myappremoves every resource the release created — no orphaned ConfigMaps or forgotten Ingresses. -
Upgrades and rollbacks are first-class. Every
helm upgraderecords history;helm rollback myapp 3reverts to release revision 3 in seconds — recovering from a bad deploy without git archaeology. -
The ecosystem is enormous.
helm search hubaccesses 800+ charts from bitnami, prometheus-community, ingress-nginx, and more. Why write your own PostgreSQL chart when a battle-tested one exists? -
The loop with GitOps is natural. Flux and Argo CD both speak Helm natively — chart in Git, values per environment, cluster state reconciled.
Hands-on: your first chart
helm create myapp # scaffolds a complete chart
tree myapp
myapp/
├── Chart.yaml # metadata + version
├── values.yaml # default configuration
├── templates/
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ └── _helpers.tpl
└── charts/ # sub-charts (dependencies)
The generated chart is already a working app template. Customize values.yaml:
replicaCount: 3
image:
repository: registry.example.com/myapp
tag: "2.1.0"
service:
port: 80
ingress:
enabled: true
host: app.example.com
Then run the lifecycle:
helm lint myapp # static checks
helm template myapp . # render manifests without applying
helm install myapp . -n prod # deploy
helm upgrade myapp . -n prod --set image.tag=2.2.0
helm history myapp -n prod # see revisions
helm rollback myapp 1 -n prod # oops, go back
helm uninstall myapp -n prod # remove everything
The helm template step deserves special love: rendering manifests locally (or in CI with kubeconform applied to the output) catches template errors before they reach a cluster.
Chart design principles
- Values are your API. Name them consistently (
image.repository, notimg.repo), document them invalues.yamlcomments, and treat breaking changes like breaking API changes — they deserve a chart version bump. - Respect the
Chart.yamlversion semver.appVersiontracks the packaged application;versiontracks the chart itself. Bump both meaningfully. - Use
_helpers.tplfor named templates (labels, fullname conventions) rather than copy-pasting label blocks — the scaffold already shows the pattern. - Make environments differ only in values. If staging needs a different chart than production, the chart is wrong — not the environment.
- Don’t fight GitOps. In Argo CD/Flux setups, CI renders or applies; humans rarely run
helm installmanually in production.
When you don’t need Helm
- A single Deployment and Service — two
kubectl applyfiles are simpler than a chart. - Kustomize users — Kustomize (built into
kubectl) takes the overlay approach instead of templating; both are legitimate, mixing them casually isn’t. - True application config — Helm manages deployment parameters; runtime configuration still belongs in ConfigMaps/Secrets or your app’s own config system.
Debugging a misbehaving release
helm status myapp -n prod # release state + recent events
helm get manifest myapp -n prod # exact YAML applied (last revision)
helm get values myapp -n prod # the values used at install time
kubectl rollout undo deploy/myapp # when you need a manual escape hatch
helm get manifest is the truth of what Helm last applied — invaluable when someone wonders “what’s actually running?”
Where to go next
- The Helm documentation — quickstart, chart developer guide, and the template function reference.
- The Artifact Hub — search the chart ecosystem.
helm create+ the official chart template guide for writing your own.
Helm won’t fix a badly designed application manifest — but once your app has a real deployment surface, it converts YAML sprawl into a versioned artifact with install, upgrade, and rollback semantics you can build a delivery process on.