Skip to content

Hands-on: Helm, Kustomize and Kluctl versions of the same app in sharifndlovu123/devops-directive-kubernetes-course (sections "Helm" and "Deploying to multiple environments"). Helm basics are in 2. Local Kubernetes Tools.

Raw YAML works for one cluster. Real systems deploy the same application to several environments (staging, production) with small differences: image tag, hostnames, replica counts, secrets. The tools below manage that.

Tools at a glance

Tool Model Good at Watch out for
Kustomize Overlays: a base plus per-environment patches Built into kubectl; no templating language; easy start Patching gets verbose and awkward for some changes
Helm Charts: templated packages with values.yaml Huge ecosystem of third-party charts; versioned releases and rollback Go templating boilerplate; heavy for simple apps
Kluctl Hybrid of templating and overlays, with diff and a GitOps controller Previews exactly what will change; handles third-party deps Smaller community
Timoni Typed config in CUE Type safety and validation; ships config with the app Steep learning curve (CUE plus the tool)
cdk8s Define resources in TypeScript, Python, Java or Go Loops, functions, tests Another build step; generated YAML to review
Pulumi General-purpose languages for Kubernetes and cloud One tool for infrastructure and cluster Needs state management
flowchart LR
    SRC[App definition: base manifests / chart] --> T{Tool}
    T --> S[staging values]
    T --> P[production values]
    S --> CS[(Staging cluster)]
    P --> CP[(Production cluster)]

Helm

A chart bundles templates, default values.yaml and metadata. A release is one installed instance of a chart.

$ helm repo add bitnami https://charts.bitnami.com/bitnami
$ helm install db bitnami/postgresql -n data --create-namespace -f values.yaml
$ helm upgrade db bitnami/postgresql -n data -f values.yaml
$ helm list -n data
$ helm rollback db 1 -n data
$ helm template ./mychart -f values-prod.yaml      # render YAML without installing

Two uses: - Third-party software: install databases, ingress controllers and monitoring from existing charts, overriding a few values - Your own app: helm create scaffolds a chart; a minimal one needs only a Deployment, Service and a few values (image tag, hostname)

# templates/deployment.yaml (fragment)
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
replicas: {{ .Values.replicas }}

Tips: pin chart versions, keep per-environment values-<env>.yaml, run helm lint and helm template in CI, and review what a chart really creates before installing it in production.


Kustomize

Plain YAML in a base, plus overlays that patch it:

app/
  base/
    deployment.yaml
    service.yaml
    kustomization.yaml
  overlays/
    staging/kustomization.yaml
    production/kustomization.yaml
# overlays/production/kustomization.yaml
resources:
  - ../../base
images:
  - name: api
    newName: registry.example.com/api
    newTag: "1.8.2"
replicas:
  - name: api
    count: 4
patches:
  - path: ingress-host.yaml
$ kubectl kustomize overlays/production        # render
$ kubectl apply -k overlays/production         # apply

Strong when the differences are small and structured (image tag, replica count, host name).


Kluctl

Combines the best of both: Jinja-style templating, an overlay-like target per environment, a diff before every deploy, and a GitOps controller.

$ kluctl diff -t staging       # what would change
$ kluctl deploy -t production

A .kluctl.yaml defines targets (staging, production); deployment.yaml lists the components. The course uses it for a complete multi-service deployment, including third-party dependencies, and reuses it for the GitOps example (Upgrades, CI-CD and GitOps).


Choosing

Situation Pick
Installing someone else's software Helm (use their chart)
Few environments, few differences, want no extra tooling Kustomize
Want a clear diff and one tool for templates, overlays and GitOps Kluctl
Strongly typed config, shipping config with the app Timoni (CUE)
Need real loops, abstractions and unit tests cdk8s or Pulumi
Everything already in Pulumi or Terraform Stay in that tool (2. Terraform)

Practices that apply to all of them: - One source of truth in Git; environments differ by parameters, not copies of manifests - Keep secrets out of values files (Developer Experience, Secrets and Debugging) - Promote the same image through environments by changing its tag, never rebuilding per environment - Validate in CI: kubectl apply --dry-run=server, kubeconform, policy checks - Pair with CI/CD and GitOps (1. CI-CD Pipelines)