Helm: The Kubernetes Package Manager and Templating Engine

Helm is the package manager for Kubernetes. It allows DevOps engineers to define, version, share, install, and upgrade complex Kubernetes applications using parameterized Helm Charts and declarative values files.


⚡ Quick Dive

Helm CLI Quick Reference

Command Action Example
helm create <name> Scaffold a new standardized chart directory structure helm create my-app
helm repo add <name> <url> Register a remote chart repository helm repo add bitnami https://charts.bitnami.com/bitnami
helm install <rel> <chart> Install chart as a new release helm install redis bitnami/redis -n database
helm upgrade --install Idempotently upgrade or install release if missing helm upgrade --install myapp ./my-app -f values-prod.yaml
helm rollback <rel> <rev> Rollback release to a previous revision number helm rollback myapp 2
helm template <chart> Render templates locally to stdout without applying helm template myapp ./my-app -f values.yaml
helm lint <chart> Validate chart syntax, schema, and best practices helm lint ./my-app
helm history <rel> List all past release revisions and deployment statuses helm history myapp

Chart Directory Anatomy

my-app/
├── Chart.yaml          # Metadata (name, version, appVersion, dependencies)
├── values.yaml         # Default configuration values for templates
├── values.schema.json  # Optional JSON schema to validate values
├── charts/             # Packaged dependency charts (subcharts)
└── templates/          # Kubernetes YAML templates with Go templating
    ├── _helpers.tpl    # Reusable template partials / named templates
    ├── deployment.yaml # Parameterized Deployment manifest
    ├── service.yaml    # Parameterized Service manifest
    └── NOTES.txt       # User guide printed upon installation

📖 Extended Guide

1. Templating Mechanics & Best Practices

Helm uses Go template syntax ({{ ... }}) combined with the Sprig template function library.

Common Template Directives:

# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "my-app.fullname" . }}
  labels:
    {{- include "my-app.labels" . | nindent 4 }}
spec:
  replicas: {{ .Values.replicaCount | default 1 }}
  selector:
    matchLabels:
      {{- include "my-app.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "my-app.selectorLabels" . | nindent 8 }}
    spec:
      containers:
        - name: {{ .Chart.Name }}
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          {{- if .Values.resources }}
          resources:
            {{- toYaml .Values.resources | nindent 12 }}
          {{- end }}
  • nindent <spaces>: Indents strings by $N$ spaces and adds a leading newline (preserves strict YAML whitespace formatting).
  • toYaml <object>: Converts structured Go data types (maps, lists) directly into formatted YAML blocks.
  • include <named_template> .: Evaluates a helper template defined in _helpers.tpl within the current context (.).

2. Multi-Environment Deployments with Values Files

Never hardcode environment configurations in templates. Maintain clean, decoupled values files:

my-app/
├── values.yaml           # Base defaults
├── values-dev.yaml       # Dev overrides (1 replica, low CPU)
├── values-staging.yaml   # Staging overrides
└── values-prod.yaml      # Prod overrides (5 replicas, strict resource quotas, TLS enabled)
# Deploy to production with base + prod overrides
helm upgrade --install myapp ./my-app \
  --namespace production \
  --create-namespace \
  -f values.yaml \
  -f values-prod.yaml \
  --atomic \
  --wait \
  --timeout 5m

[!TIP] Production Safety (--atomic): Always include --atomic and --wait in automated CI/CD pipelines. If pods fail to become ready within the timeout, Helm automatically rolls back the release to the previous working revision.