Skip to content
Blog

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:

ConceptAnalogyWhat it is
Chart.deb / npm packageA template bundle of Kubernetes manifests + metadata
ReleaseInstalled instanceOne deployed instance of a chart in a cluster
Repositoryapt/npm registryWhere charts are stored and shared
ValuesConfig fileParameters 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

  1. Templating kills YAML duplication. One chart, many environments:

    image:
      repository: registry.example.com/myapp
      tag: {{ .Values.image.tag }}
    replicas: {{ .Values.replicaCount }}
  2. Install/uninstall is atomic and tracked. helm uninstall myapp removes every resource the release created — no orphaned ConfigMaps or forgotten Ingresses.

  3. Upgrades and rollbacks are first-class. Every helm upgrade records history; helm rollback myapp 3 reverts to release revision 3 in seconds — recovering from a bad deploy without git archaeology.

  4. The ecosystem is enormous. helm search hub accesses 800+ charts from bitnami, prometheus-community, ingress-nginx, and more. Why write your own PostgreSQL chart when a battle-tested one exists?

  5. 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, not img.repo), document them in values.yaml comments, and treat breaking changes like breaking API changes — they deserve a chart version bump.
  • Respect the Chart.yaml version semver. appVersion tracks the packaged application; version tracks the chart itself. Bump both meaningfully.
  • Use _helpers.tpl for 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 install manually in production.

When you don’t need Helm

  • A single Deployment and Service — two kubectl apply files 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

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.