Helm Fundamentals
Master the Kubernetes package manager. Learn Helm charts, Go templates, values, releases, repositories, and debugging.
1. Why Helm?
Deploying even a moderately complex application to Kubernetes requires multiple YAML files: a Deployment, a Service, a ConfigMap, Secrets, Ingress rules, HPA configs, PVCs, and more. Managing this manually is tedious, error-prone, and hard to version.
Helm is the package manager for Kubernetes (like apt for Ubuntu or brew for macOS). It packages all related Kubernetes manifests into a single, versioned, configurable Chart that can be installed with a single command, upgraded atomically, and rolled back if something goes wrong.
2. Core Concepts
- Chart: A package of pre-configured Kubernetes resources. Contains templates, a
Chart.yaml(metadata), and avalues.yaml(defaults). Charts can depend on other charts (subcharts). - Release: A running instance of a Chart in a cluster. Installing the same chart multiple times creates independent releases with unique names (e.g.,
myapp-prodandmyapp-staging). - Repository: A HTTP server hosting a collection of charts. Can be public (Bitnami, Artifact Hub) or private (your own registry).
- Values: Configuration inputs for a Chart. Defined in
values.yaml. Users override them at install/upgrade time without modifying the templates. - Revision: Every install, upgrade, or rollback creates a new revision. Stored as Kubernetes Secrets, enabling rollback to any prior state.
3. Chart Structure
my-chart/ โโโ Chart.yaml # Chart metadata (name, version, description, dependencies) โโโ values.yaml # Default configuration values โโโ charts/ # Subcharts and chart dependencies go here โโโ templates/ # Kubernetes YAML templates (Go template syntax) โ โโโ deployment.yaml โ โโโ service.yaml โ โโโ ingress.yaml โ โโโ _helpers.tpl # Named templates / helper functions (not rendered to K8s) โ โโโ NOTES.txt # Post-install usage notes printed to the user โโโ .helmignore # Files to exclude from chart packaging (like .gitignore)
4. Chart.yaml and values.yaml
apiVersion: v2 # Helm 3 chart format name: my-webserver description: A Helm chart for Nginx-based web server type: application # 'application' or 'library' version: 1.2.0 # Chart version (bump on every change!) appVersion: "1.25.0" # Version of the app being deployed dependencies: - name: postgresql # Subchart dependency version: "13.2.0" repository: "https://charts.bitnami.com/bitnami" condition: postgresql.enabled # Only install if values.postgresql.enabled=true
replicaCount: 2
image:
repository: nginx
tag: "1.25"
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
ingress:
enabled: false
host: ""
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
postgresql:
enabled: true
auth:
password: "changeme" # Users override this with --set or a secrets manager! 5. Go Templates in Helm
Helm processes templates using the Go templating engine. Templates use {{ }} delimiters and have access to chart values and built-in objects.
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ '{{' }} .Release.Name {{ '}}' }}-web # Uses the Helm release name
labels:
{{ '{{-' }} include "my-chart.labels" . | nindent 4 {{ '}}' }} # Call a named template
spec:
replicas: {{ '{{' }} .Values.replicaCount {{ '}}' }} # From values.yaml
selector:
matchLabels:
app: {{ '{{' }} .Release.Name {{ '}}' }}-web
template:
metadata:
labels:
app: {{ '{{' }} .Release.Name {{ '}}' }}-web
spec:
containers:
- name: nginx
image: "{{ '{{' }} .Values.image.repository {{ '}}' }}:{{ '{{' }} .Values.image.tag {{ '}}' }}"
imagePullPolicy: {{ '{{' }} .Values.image.pullPolicy {{ '}}' }}
ports:
- containerPort: 80
resources: {{ '{{-' }} toYaml .Values.resources | nindent 10 {{ '}}' }}
{{ '{{-' }} if .Values.ingress.enabled {{ '}}' }} # Conditional block
env:
- name: HOSTNAME
value: {{ '{{' }} .Values.ingress.host | quote {{ '}}' }}
{{ '{{-' }} end {{ '}}' }} Common Template Functions
| Function | Use |
|---|---|
{{ .Values.key }} | Access a value from values.yaml |
{{ .Release.Name }} | The Helm release name |
{{ .Chart.Version }} | The chart version |
{{ toYaml .Values.obj | nindent 8 }} | YAML-encode a value and indent |
{{ default "fallback" .Values.opt }} | Use fallback if value is empty |
{{ required "msg" .Values.key }} | Fail installation if value is not set |
6. The Helm Workflow
# Add and search repositories helm repo add bitnami https://charts.bitnami.com/bitnami helm repo update helm search repo nginx # Review chart defaults before installing helm show values bitnami/nginx > my-values.yaml # Edit this file helm show readme bitnami/nginx # Install with custom values helm install my-nginx bitnami/nginx \ -f my-values.yaml \ --set replicaCount=3 \ # Inline override (takes precedence) --namespace production \ --create-namespace \ --atomic # Auto-rollback if install fails # Inspect a running release helm list -A # All namespaces helm status my-nginx helm get values my-nginx # What values were set? helm history my-nginx # See all revisions # Upgrade a release helm upgrade my-nginx bitnami/nginx \ --reuse-values \ # Keep existing values, only change what's in -set --set image.tag=1.26 # Rollback to previous revision helm rollback my-nginx 1 # Rollback to revision 1 # Dry-run and debug (render templates without applying) helm template my-nginx bitnami/nginx --debug helm install my-nginx bitnami/nginx --dry-run # Uninstall helm uninstall my-nginx # Removes all K8s resources created by the release
7. Helm 3 vs Helm 2 โ Key Differences
If you read older tutorials, you may encounter Tiller โ a server-side component that Helm 2 required. This was a significant security risk (cluster admin access). Helm 3 eliminated Tiller entirely.
- โ
No Tiller: Helm 3 runs entirely client-side, using your
kubeconfigcredentials directly. - โ Release secrets: Release history is stored as Kubernetes Secrets (instead of a Tiller in-cluster DB).
- โ 3-way merge: Helm 3 uses a 3-way strategic merge patch for upgrades (considers current state, previous state, and desired state).
- โ
JSON Schema validation: Charts can include a
values.schema.jsonto validate user inputs at install time.