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.yaml metadata file, default values.yaml, and a templates/ 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 upgrade creates a new numbered revision of a release, with the full history retained so helm rollback can 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 install renders a chart’s templates locally by merging values.yaml with 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 upgrade re-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 to kubectl 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 rollback works 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 separate helm diff plugin

Comparison: Helm vs Kustomize vs Raw Kubernetes Manifests

HelmKustomizeRaw Manifests
ApproachTemplated packages with valuesOverlay-based patching, no templatingHand-written YAML, no abstraction
PackagingVersioned charts, shareable via repos/OCINo packaging format, just YAML + patchesNone, copy-paste or manual scripting
Config reuseValues files per environmentBase + overlay directories per environmentTypically duplicated files per environment
Best fitDistributing complex, reusable third-party or internal appsEnvironment-specific tweaks to otherwise-static manifestsSmall, 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 template or helm install --dry-run before a real install/upgrade, rendering locally first catches broken values before they ever touch the cluster
  • Install the helm-diff plugin 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) and helm-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 template or --dry-run before every real install or upgrade, especially against production
  • Use helm diff for production upgrades, treating it as the closest available equivalent to Terraform’s plan step
  • Pin chart and dependency versions, and commit Chart.lock so installs are reproducible across machines and CI
  • Keep values layered by environment (values.yaml plus values-prod.yaml) rather than maintaining several fully separate charts
  • Extract repeated template logic into named templates in _helpers.tpl to 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-install or post-upgrade tied to Kubernetes jobs
  • “What’s the difference between helm template and helm 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

Dig deeper