CoursesHelmIntermediate

The templating engine

Go templates and the release context.

Intermediate14 min · lesson 5 of 12

Helm renders templates with the Go template engine, augmented by the Sprig function library and a set of built-in objects. Inside {{ }} you access data: .Values (user config), .Release (name, namespace, revision, isInstall/isUpgrade), .Chart (Chart.yaml fields), .Capabilities (cluster/API versions), and .Files (bundled files). Combining these produces manifests that adapt to both the chart’s values and the release context.

templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-{{ .Chart.Name }}
labels:
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
spec:
replicas: {{ .Values.replicaCount }}
template:
spec:
containers:
- name: app
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"

Control flow and scope

Templates support conditionals ({{ if }}), loops ({{ range }}), and variables ({{ $x := }}). The with block narrows scope to a sub-object, which cleans up deep paths — but inside it, the dot (.) now refers to that object, so a common bug is losing access to .Values or .Release inside a with/range. The fix is to save the root ($) or reference values through it. Understanding scope is most of Helm-template debugging.

templates snippet
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }} # . is now .Values.ingress.annotations
{{- end }}
{{- end }}
Inside with/range, the dot changes meaning
A with or range block rebinds . to the current object, so .Values or .Release stops working inside it — a top source of “nil pointer” template errors. Reach the root with the global $ (e.g. $.Release.Name) or capture variables before the block. When a template errors only inside a loop or with, suspect the scope of the dot first.