Chart Anatomy
Chart Anatomy
mychart/
├── Chart.yaml # apiVersion: v2, name, version (chart semver), appVersion
├── values.yaml # default configuration
├── templates/ # rendered into manifests
│ ├── deployment.yaml
│ ├── _helpers.tpl # named templates, not rendered alone
│ └── NOTES.txt # printed after helm install
├── charts/ # packaged subchart dependencies
└── .helmignore
Helm renders every file under templates/ through Go's template engine, concatenates the output, and submits it as YAML. Files starting with _ define named templates only. Chart.yaml version tracks the chart itself; appVersion tracks the packaged application — bump them independently.
Template Syntax That Works
Template Syntax That Works
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "mychart.fullname" . }}
labels:
{{- toYaml .Chart.Labels | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- if eq .Values.mode "ha" }}
strategy: { type: Recreate }
{{- end }}
Context is everything: . is the root data inside {{ }}; with rebinds . to the block's value (so {{ . }} inside is the list itself). Helpers in _helpers.tpl avoid duplication: {{ include "mychart.fullname" . }}, built-ins .Release.Name, .Release.Namespace, .Capabilities.APIVersions.Has, plus required "replicaCount is mandatory" .Values.x.
Pitfalls and Interview Angles
Pitfalls and Interview Angles
Indentation bugs are the number-one failure: toYaml output must go through | nindent 4 (or hand-built indentation). Off-by-two spaces yields "error converting YAML" at apply time — catch it earlier with helm template | kubeconform.
Lost context in helpers. A helper invoked without . cannot see values; always pass the context: include "x" ..
Overlong names. Deployment and Service names must match selectors and stay ≤63 chars — the standard fullname helper truncates.
Unquoted numbers. Ports like 8080 rendered as 8080 are fine, but version-like values (1.10) become floats — wrap with quote.
Interview angle: describe your validation pipeline (helm lint → helm template → schema validation → diff) and explain how with changes ..
Quiz
1. What happens to files in templates/ beginning with an underscore?
2. Why pipe toYaml through nindent in most templates?
3. Inside a with .Values.nodeSelector block, what does {{ . }} refer to?
Flashcards
Question
_helpers.tpl
Click to reveal answer
Answer
Chart-local named templates (define) used via include; underscore-prefixed files render no output themselves.
Question
nindent vs indent
Click to reveal answer
Answer
nindent N = newline + N spaces before content; use with toYaml for nested blocks.
Question
required function
Click to reveal answer
Answer
required "msg" .Values.x aborts rendering with a message when the value is empty.
Question
Chart version vs appVersion
Click to reveal answer
Answer
version = chart packaging semver; appVersion = the application version packaged inside.
Revision Notes
Key Takeaways
- 1. A chart renders through Go templates into plain manifests — YAML errors are template errors
- 2. Master context (the dot), with/if/range, and include with helpers
- 3. Gate merges with helm lint + helm template + schema validation before anything reaches a cluster
Interview Tips
- • Explain what the dot means and how with changes it — the most common template interview question
- • Walk your CI checks for a chart and name the failure each one catches
Cheat Sheet
Chart.yaml (version/appVersion), values.yaml, templates/ (+ _helpers.tpl, NOTES.txt). Dot = context; with rebinds it; toYaml | nindent for blocks; required for mandatory values. lint + template in CI.