Frontend Labs
⋯

Chapter 61 -- Helm and packaging Kubernetes applications

In one sentence

Helm is a package manager for Kubernetes -- it turns a directory of templated YAML into a versioned, install/upgrade/rollback-able "chart," for the same reason apt exists instead of everyone compiling and copying binaries by hand.

Why this matters

A real application is rarely one Deployment. It's a Deployment, a Service, a ConfigMap, maybe a Secret, an Ingress, a HorizontalPodAutoscaler -- 6 to 15 YAML files that all need to agree with each other (same labels, same names, same namespace) and that change slightly between environments (dev uses 1 replica and no autoscaling, prod uses 5 and does). Copy-pasting these YAML files between environments and hand-editing the differences is exactly the class of manual, error-prone, "someone forgot to update the image tag in staging" work that Helm exists to eliminate.

For a manager: Helm charts are also how most third-party software gets installed onto Kubernetes today (Prometheus, cert-manager, ingress controllers, databases) -- "just helm install it" is the standard onboarding instruction across the ecosystem, so basic Helm literacy is close to a baseline expectation for anyone operating a cluster, not a specialist skill.

How it actually works

   A CHART is a directory:

     mychart/
       Chart.yaml          -- name, version, description
       values.yaml         -- default configuration values
       templates/
         deployment.yaml   -- Go-template YAML, referencing .Values.*
         service.yaml
         configmap.yaml
       charts/              -- bundled dependencies (sub-charts)

   templates/deployment.yaml might contain:

     replicas: {{ .Values.replicaCount }}
     image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"

   values.yaml (the defaults):
     replicaCount: 1
     image:
       repository: myapp
       tag: latest

   A production override, values-prod.yaml:
     replicaCount: 5
     image:
       tag: v2.4.1

The commands that matter day to day:

helm install myapp ./mychart -f values-prod.yaml   # first install
helm upgrade myapp ./mychart -f values-prod.yaml   # apply changes
helm rollback myapp 3                              # back to revision 3
helm history myapp                                 # see revisions
helm template ./mychart -f values-prod.yaml         # render YAML,
                                                     # don't apply --
                                                     # use this to review
                                                     # exactly what
                                                     # would be sent to
                                                     # the cluster
helm uninstall myapp

Every helm upgrade is a new numbered revision, tracked by Helm as a Secret in the cluster -- which is what makes helm rollback possible: it isn't magic, it's "re-apply the exact rendered YAML from revision N."

Real-world example

The Kubernetes package ecosystem's default answer to "how do I run Prometheus" or "how do I run an nginx ingress controller" is, almost universally, a Helm chart from the project's own repository or from Artifact Hub (the successor to the old central "stable" Helm chart repository). This is not incidental: Helm charts became the de facto distribution format precisely because hand-writing 10+ YAML files for Prometheus's Deployment, Services, RBAC rules, ConfigMaps, and PersistentVolumeClaims -- correctly, for your specific cluster's storage class and resource limits -- is enough work that essentially nobody wants to do it themselves. A commonly repeated cautionary lesson in platform engineering, though, is helm install-ing a chart without reading values.yaml first: charts often ship reasonable defaults for a generic cluster, but a default like persistence.enabled: false on a database chart or a resources: {} with no limits can silently mean "this loses its data on every restart" or "this can consume unbounded memory on your node" -- and because Helm makes installation so effortless, teams routinely encounter these gaps only once the workload is already running in production. The practical rule that has emerged across SRE teams is: helm template and read the rendered output before ever running helm install on anything you didn't author yourself.

Try it yourself

# Requires helm installed and a cluster (minikube/kind is fine).
helm create demochart
ls demochart/templates/

# Render without installing -- read this output before ever installing
# a chart you didn't write
helm template demochart

helm install demo ./demochart
helm list
helm upgrade demo ./demochart --set replicaCount=3
helm history demo
helm rollback demo 1
helm uninstall demo

Common mistakes

  • Running helm install on an unfamiliar third-party chart without first running helm template to see exactly what it creates -- including RBAC permissions and resource limits (or their absence).
  • Editing a running application's Kubernetes objects directly with kubectl edit after it was installed via Helm -- the next helm upgrade silently overwrites the manual change, because Helm has no idea it happened.
  • Treating values.yaml defaults as production-appropriate without reading them, especially replicaCount, resources, and persistence settings.
  • Not pinning chart versions (helm install myapp repo/chart without --version), so the same install command produces a different chart version, with different defaults, weeks later.

Check yourself

  1. What does helm rollback myapp 3 actually do, mechanically -- what is Helm re-applying?
  2. Why does hand-editing a Helm-managed Kubernetes object with kubectl edit cause problems later, even if the edit itself is correct?
  3. Why is helm template recommended before helm install for a chart you didn't write yourself?

Further reading

  • Helm official documentation, "Helm Charts" and "Using Helm" (helm.sh/docs)
  • Artifact Hub (artifacthub.io) -- the community index of published Helm charts
  • CNCF, "Helm" project page and graduation announcement (Helm graduated as a CNCF project in 2020)

Generated from real-life-os-guide.md · 8 Oct 2026 16:36