In Chapter 2, you learned basic Helm syntax: {{ .Values.replicaCount }} inserts a value into your manifest. This is enough to deploy, but not enough to build production charts. You'll encounter situations where you need to store values, transform text, make decisions about what to render, and repeat blocks. That's where Go templating becomes essential.
Go templating is the foundation of every Helm chart. Master this, and you'll write charts that adapt to any environment, validate inputs, and eliminate boilerplate across dozens of Kubernetes manifests.
This lesson covers 9 core templating concepts in 3 groups:
Prerequisites: You should be comfortable with:
Time estimate: 45-60 minutes (work through concepts, then try exercises)
Consider a Deployment that needs environment variables for different use cases:
In development, you might want just the first two variables. In production, you need both plus additional security constraints. In staging, you need different log levels.
Static manifests force you to maintain separate files. Go templating lets you write once:
Then specify different values files for each environment. This lesson teaches the template syntax that makes this possible.
Template variables store intermediate values so you don't repeat expressions. The syntax is $varName := expression.
Output:
(when values.yaml contains environment: dev)
Output:
(when replicaCount: 5)
Why is this useful? Without variables, you'd repeat .Values.replicaCount multiple times. With variables, you assign once and reference $replicaCount throughout.
Pipelines use the | operator to pass output from one function to the next. Like shell pipes, they transform values step by step.
Output:
(when serviceName: task-api)
The upper function transforms text to uppercase.
becomes cleaner with pipelines:
But more commonly, you chain string functions:
Output:
Step by step:
Output:
The indent 4 function adds 4 spaces to every line of output.
Output:
Output:
The with block changes the current context (.) to a nested value, reducing repetition.
Output:
Inside the with block, .name refers to .Values.container.name, and .image refers to .Values.container.image. This is cleaner when you have many nested properties.
This renders the entire Ingress block ONLY if .Values.ingress is defined.
You've now learned the three core data handling patterns:
Quick self-check: Can you...
If yes, continue to the Logic concepts. If not, re-read the examples above—these patterns appear in every production chart.
Go templates use named comparison operators instead of symbols.
Cheat sheet:
Output:
Control what renders based on conditions.
Output:
(when persistence.enabled: true)
Or nothing if persistence.enabled: false or not set.
Output:
(if imagePullPolicy is set, use it; otherwise use IfNotPresent)
Output (for tier: staging):
The range function iterates over lists or maps.
Output:
Inside the range block, . refers to each item (changing on each iteration).
Output:
With maps, use $key, $value to access both the key and value.
Output:
You've now learned how to control what gets rendered:
Common mistake: Forgetting that Go uses eq not ==. If your conditional isn't working, check your operator syntax.
Quick self-check: Can you...
The final three concepts (7-9) are about context and formatting—less critical for basic charts but essential for production.
Helm provides special variables you can use inside templates.
{{ .Release.Name }} is the name you provide when installing: helm install my-release ./my-chart
Output would be: metadata: name: my-release
{{ .Chart.Name }} is from Chart.yaml (e.g., "task-api") {{ .Chart.Version }} is from Chart.yaml (e.g., "1.0.0") {{ .Release.Service }} is always "Helm" for Helm-deployed resources
Output:
.Capabilities lets you check what Kubernetes API versions are available on the target cluster.
Template rendering often produces unwanted blank lines. The - character in {{- and -}} strips whitespace.
The {{- removes spaces/newlines BEFORE the block. The -}} removes spaces/newlines AFTER the block.
Output (correct indentation):
Without {{-, you'd get extra blank lines that break YAML indentation.
Named templates (also called "partials") let you define reusable template code. You'll explore this deeply in Chapter 4, but the basic syntax is:
Then include it elsewhere:
Output:
This eliminates copying labels across multiple manifests.
Before trying the exercises, know these frequent errors:
Debugging tip: When templates fail, run helm template --debug ./my-chart to see the exact error location and line number.
Create a template that renders replica count based on environment tier:
Write a template block that sets spec.replicas based on the tier. Hint: Use a variable assignment and conditional.
Solution:
Output (for tier: production):
Given environment variable values, transform and render them:
Write a template that:
Solution:
Output:
Render an Ingress ONLY if enabled, using a with block:
Write a template that renders the Ingress block conditionally.
Solution:
Output (when enabled: true and tls: true):
(Rendered nothing if enabled: false)
Transform a map of environment variables into Kubernetes env blocks:
Write a range loop that creates env blocks with quoted values.
Solution:
Output:
You have a template with an error:
The default function is missing a value. Run helm template to debug.
Command:
Error Output:
Fix:
Use helm template --debug to see the full template rendering process.
In this section, you'll use AI to explore template patterns you haven't seen before, evaluate its suggestions, refine them based on production constraints, and validate the results.
You're building a chart for a data pipeline that needs conditional authentication. Ask AI:
"I need a Helm template that includes a Secret for database credentials, but only when .Values.database.enabled is true. The Secret should also only be created when .Values.auth.type equals 'database'. Show me how to handle both conditions with a template."
Review AI's response. Ask yourself:
If AI's response doesn't handle whitespace control (the {{- syntax), tell it:
"The template produces extra blank lines that break the YAML structure. Use {{- to strip leading whitespace from template tags. Also, make sure the Secret data values are base64-encoded (Kubernetes requirement)."
Ask AI to validate its updated template:
"Now show me the rendered output when .Values.database.enabled is true and .Values.auth.type is 'database'. Also show what happens when one of those conditions is false."
Compare the rendered outputs to expected Kubernetes manifests:
If all answers are yes, you've successfully learned to combine conditionals with AI's help.
You built a helm-chart skill in Chapter 1. Test and improve it based on what you learned.
Ask yourself:
If you found gaps:
Next Chapter: Chapter 4 teaches named templates and helpers (like _helpers.tpl), which let you build reusable template code across an entire chart.