C.W.K.
Stream
Lesson 05 of 08 · published

Helm — Templated YAML for Kubernetes

~12 min · yaml, helm, kubernetes, templating

Level 0Plaintext
0 XP0/64 lessons0/12 achievements
0/100 XP to next level100 XP to go0% complete

YAML with Go templates layered on top

Helm is Kubernetes' package manager. A chart is a directory of YAML templates. helm install renders the templates against a values.yaml file and applies the result. Same K8s manifests at the bottom; a templating layer in the middle lets one chart deploy to dev/staging/prod with different values.

Chart layout

  • Chart.yaml — chart metadata.
  • values.yaml — default values (the chart's API).
  • templates/ — YAML templates with {{ .Values.x }} substitution.
  • charts/ — sub-charts.

The string-quoting trap

Helm templates output text. The result is then parsed as YAML. So a template that emits a bare value gets re-typed by YAML — {{ .Values.port }} with port: 8000 becomes the integer 8000, even where K8s expects a string. Quote the rendered output explicitly: {{ .Values.port | quote }} or wrap in quotes.

The 'rendered YAML is sometimes invalid YAML' problem: Helm templates can produce broken YAML (missing newlines, double-pipes, mistabbed blocks). Always run helm template ./chart and pipe through kubeconform or yq . in CI — render-time validation, not just deploy-time.

Code

Chart layout·text
pippa-chart/
├── Chart.yaml
├── values.yaml
└── templates/
    ├── deployment.yaml
    ├── service.yaml
    ├── configmap.yaml
    └── _helpers.tpl
values.yaml + a template·yaml
# values.yaml
image:
  repository: ghcr.io/cwk/pippa
  tag: '1.0'
replicas: 3
port: 8000
logLevel: info

# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}
spec:
  replicas: {{ .Values.replicas }}
  template:
    spec:
      containers:
        - name: api
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
          ports:
            - containerPort: {{ .Values.port }}
          env:
            - name: LOG_LEVEL
              value: {{ .Values.logLevel | quote }}
Render + validate before installing·bash
# Render to stdout (no cluster contact)
helm template my-release ./pippa-chart

# Render with a values override
helm template my-release ./pippa-chart -f prod-values.yaml

# Render and validate the rendered YAML against K8s schemas
helm template my-release ./pippa-chart | kubeconform -summary -strict

# Lint the chart
helm lint ./pippa-chart
Override values per environment·yaml
# prod-values.yaml
replicas: 10
logLevel: warn
image:
  tag: '1.0.42'

External links

Exercise

Take a Kubernetes manifest with hard-coded values (replicas, image tag, env). Convert it to a 1-template Helm chart with a values.yaml. Render with helm template against two values files (dev + prod) and diff the outputs. Validate both renders with kubeconform. The 'one chart, two deploys' pattern is the entire point.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.