Why Templating?
Templating lets one chart produce many different deployments by substituting values, avoiding copy-pasted YAML.
replicas: {{ .Values.replicaCount }}Plain Kubernetes manifests are static. If you want to deploy the same app to three environments, you would copy the YAML three times and hand-edit the image tag, replica count, and hostnames. Those copies drift apart over time.
Templates + values
Helm charts contain templates — YAML files with placeholders — plus a values.yaml file that supplies the actual data. At install time Helm renders the templates with the values to produce the final manifests.
- One chart, many environments — just swap the values.
- Configuration lives in one obvious place instead of scattered across files.
- Change a value, run
helm upgrade, and every affected resource updates.
A template placeholder looks like {{ .Values.replicaCount }}. That reads the replicaCount key from your values.
Example
# templates/deployment.yaml (a fragment)
spec:
replicas: {{ .Values.replicaCount }}
template:
spec:
containers:
- name: app
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"When to use it
- A team maintains a single chart for their API service and deploys it to dev, staging, and production simply by passing different values files, avoiding three copies of near-identical YAML.
- A chart author sets replicaCount: 1 as the default so newcomers get a lightweight deployment, while production operators override it to 10 without touching the template.
- An infrastructure engineer parameterises the container image tag in a template so the CD system can inject the exact build SHA at deploy time without modifying any YAML by hand.
More examples
Basic value substitution
Shows how Go template expressions pull replicaCount and image details from values.yaml at render time.
# templates/deployment.yaml
spec:
replicas: {{ .Values.replicaCount }}
template:
spec:
containers:
- name: app
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}Default values file
Defines the default configuration consumed by the templates above; operators override only what they need.
# values.yaml
replicaCount: 1
image:
repository: my-app
tag: latest
service:
type: ClusterIP
port: 80Environment-specific override
Layering a production values file on top of defaults so shared settings stay in values.yaml and environment differences live in values-prod.yaml.
# Deploy to production with a separate values file
helm upgrade --install my-app ./my-chart \
-f values.yaml \
-f values-prod.yaml
Discussion