By this point, deploying one real application means a Deployment, a Service, an Ingress, a ConfigMap, maybe an HPA and a PVC — a handful of separate YAML files, mostly identical between environments except for a few values. Helm exists to stop hand-copying and hand-editing that whole set every time.
3 min read
A real application deployed to staging and production needs essentially the same set of objects from this domain — a Deployment (lesson 1's territory), a Service, an Ingress (lesson 4), a ConfigMap (lesson 3), maybe an HPA (lesson 6) — differing only in a handful of values: replica count, resource limits, the hostname in the Ingress, which image tag to run. Maintaining separate near-identical copies of every YAML file per environment means every real change has to be made — and easily forgotten — in multiple places.
Helm packages a related set of Kubernetes manifests into a chart, templated so the same chart can be deployed differently per environment by changing only a small set of values:
# templates/deployment.yaml (part of the chart)
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-app
spec:
replicas: {{ .Values.replicaCount }}
template:
spec:
containers:
- name: app
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
resources:
requests:
cpu: {{ .Values.resources.requests.cpu }}# values-staging.yaml
replicaCount: 1
image:
tag: "staging-latest"
resources:
requests:
cpu: "100m"# values-production.yaml
replicaCount: 5
image:
tag: "v1.2.0"
resources:
requests:
cpu: "500m"helm install my-app ./my-chart -f values-production.yamlThe templates themselves stay identical between environments — only the values file changes, which is exactly what eliminates the duplicated, easy-to-desync YAML this lesson opened with.
Each helm install (or helm upgrade) creates a tracked release —
Helm remembers exactly which values produced the currently-deployed state,
which is what makes helm rollback possible: reverting to a previous
release's exact configuration without needing to manually reconstruct
what it was. This is a genuinely different capability than kubectl apply
alone provides, since plain kubectl has no built-in concept of "the
previous version of this whole set of objects."
Helm's other major use is installing well-maintained, pre-built charts for common software — a production-grade Postgres deployment (building on lesson 7's StatefulSet concepts), a monitoring stack, an Ingress controller (lesson 4's missing piece) — via public chart repositories, without hand-writing the (often substantial) YAML such a real deployment actually needs:
helm repo add bitnami https://charts.bitnami.com/bitnami
helm install my-postgres bitnami/postgresql -f my-values.yamlHelm templates and tracks releases; it doesn't replace understanding what
the underlying objects actually do — a Helm chart for a Deployment is
still fundamentally the same Deployment object from lesson 1, templated
for convenience, not a different underlying mechanism. Debugging a chart
that isn't behaving as expected usually means rendering its actual output
(helm template shows the raw YAML a chart would produce) and reading it
with the same understanding this domain has built lesson by lesson, not
treating Helm as an opaque abstraction layer that removes the need for
that understanding.
Every object this domain covered — ConfigMaps, Ingress, HPAs, StatefulSets, DaemonSets, Jobs, PVCs, RBAC rules — is, underneath, the same pattern from lesson 1: desired state written to etcd via the API server, reconciled by a controller built specifically for that object type. Helm doesn't change that model at all; it just makes writing and maintaining the YAML that expresses that desired state less repetitive across environments and applications.
Check your understanding
A quick comprehension check — not tracked, not graded, just for you.
1. What core problem does Helm solve when deploying the same application to multiple environments?
2. What capability does a Helm release provide that plain kubectl apply doesn't have built in?
3. Why doesn't using Helm remove the need to understand the underlying Kubernetes objects it templates?
Kubernetes