๐Ÿ‘ค
โš“ Module 6 โ€ข 5 Labs โ€ข Est. 45 min โ€ข Intermediate

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 a values.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-prod and myapp-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

Chart directory 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

Chart.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
values.yaml
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.

templates/deployment.yaml
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

graph LR; VH[values.yaml\n+ overrides] --> HE[Helm Engine] TPL[templates/*.yaml] --> HE HE -.->|Renders YAML| API[Kubernetes API Server] API --> R1[(Revision 1\nInstall)] R1 -->|helm upgrade| R2[(Revision 2\nUpgrade)] R2 -->|helm rollback| R1 style HE fill:#0f172a,stroke:#38bdf8,stroke-width:2px,color:#fff
bash โ€” Full 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 kubeconfig credentials 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.json to validate user inputs at install time.
โ–ถ Terminal Simulator
โ–ฒ
K8s.Learn Simulator connected.
Type 'help' for available commands.
root@k8s-master:~#