# templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-config
labels:
{{- include "mychart.labels" . | nindent 4 }}
data:
food: {{ .Values.favorite.food | upper | quote }}
{{- if .Values.debug }}
debug: "true"
{{- end }}
| Part | Example |
|---|---|
| Built-in objects | .Values, .Release.Name, .Release.Namespace, .Chart.Version, .Files, .Capabilities |
| Pipelines, functions | {{ .Values.food \| default "rice" \| upper \| quote }} |
| Flow control | if/else, range (loop over list/dict), with; variables {{- $name := .Release.Name }} |
| Helpers | define in _helpers.tpl, called with include "mychart.labels" . then nindent |
{{- / -}} |
Trim whitespace/newlines on the left/right |
flowchart LR D["values.yaml (defaults)"] --> M["Final values"] F["-f prod-values.yaml"] --> M S["--set replicaCount=2"] --> M M --> T["Template"] --> R["Manifest"]
Precedence: values.yaml < -f files (a later file beats an earlier one) < --set.
Hooks (helm.sh/hook: pre-install, post-upgrade…) run Jobs/Pods at points of the release lifecycle; helm test runs the test pods in templates/tests/.
Traps
- Forgetting the dot (
Values.xinstead of.Values.x) or passing the wrong context toinclude(missing.). - Wrong indentation when inserting several lines: use
nindent. {{-eating a newline so two YAML lines get glued together.
| Command | Meaning |
|---|---|
helm upgrade web bitnami/nginx -n web -f values.yaml --set replicaCount=2 |
Upgrade with new values |
helm history web -n web |
List revisions |
helm rollback web 1 -n web |
Go back to revision 1 |
Functions you will use often
| Function | Example | Purpose |
|---|---|---|
toYaml |
{{- toYaml .Values.resources \| nindent 12 }} |
Insert a whole block of values |
required |
{{ required "image.repository is required" .Values.image.repository }} |
Fail rendering with a clear message |
default |
{{ .Values.port \| default 8080 }} |
Fallback value |
tpl |
{{ tpl .Values.extraConfig . }} |
Render a template string stored in values |
sha256sum |
{{ include (print $.Template.BasePath "/configmap.yaml") . \| sha256sum }} |
Checksum annotation that restarts pods when config changes |
lookup |
{{ lookup "v1" "Secret" .Release.Namespace "db" }} |
Read an existing object from the cluster during install |
lookup returns nothing under helm template, because there is no cluster connection.
Loops and scope
env:
{{- range $key, $value := .Values.env }}
- name: {{ $key }}
value: {{ $value | quote }}
{{- end }}
Inside range and with, the dot . changes to the current item; use $ to reach the top-level context, for example {{ $.Release.Name }}.
Reading files
.Files.Get "config/app.conf" reads a file packaged in the chart, and (.Files.Glob "dashboards/*.json").AsConfig turns a set of files into ConfigMap data. Files listed in .helmignore are not available.
Debugging templates
| Command | Shows |
|---|---|
helm template web ./mychart --debug |
Rendered output plus the error location |
helm install web ./mychart --dry-run=server |
Validates against the live cluster without changing it |
helm get manifest web -n web |
What a deployed release actually contains |
helm diff upgrade web ./mychart -n web |
Changes an upgrade would make (helm-diff plugin) |
Hook details
Hooks accept helm.sh/hook-weight to order several hooks, and helm.sh/hook-delete-policy (before-hook-creation, hook-succeeded, hook-failed) to clean up the hook Jobs. A pre-upgrade hook is a common place to run database migrations before new pods start.