Topic 7.1
Chart Fundamentals: Charts, Values, and Templates
In one line
A Helm chart is a directory of templated YAML manifests plus a set of default values — the same underlying resources you've been writing by hand, now reusable and parameterized instead of copy-pasted.
Think of it like this
A form letter with blanks to fill in, versus writing the entire letter from scratch every single time — a CHART is the form letter (the structure, written once), and VALUES are what fills in the blanks differently for each specific use (dev vs staging vs production), producing a complete, correct letter every time without retyping the whole thing.
Key ideas
- 01
A CHART is a directory with a defined structure:
Chart.yaml(metadata — name, version, description),values.yaml(default configuration values), and atemplates/folder containing your actual Kubernetes manifests, written using Go template syntax to reference values instead of hardcoding them. - 02
values.yamlholds the DEFAULT values a chart uses —replicaCount: 3,image.tag: "1.5.0"— and any of these can be OVERRIDDEN at install/upgrade time (--set replicaCount=5or a separate values file per environment), without ever touching the chart's own template files themselves. - 03
A TEMPLATE file looks like an ordinary Kubernetes manifest with
{{ .Values.xxx }}placeholders substituted in —replicas: {{ .Values.replicaCount }}in a template, combined withreplicaCount: 3invalues.yaml, renders toreplicas: 3in the final manifest Helm actually applies to the cluster. - 04
helm template <chart>renders a chart's templates into final, plain YAML WITHOUT actually installing anything — genuinely useful for previewing exactly what Helm would apply, or for debugging a template that isn't rendering the way you expect, before committing to a real install. - 05
helm install <release-name> <chart>is the actual deployment step — it renders the templates with the given (or default) values and applies the resulting manifests to the cluster, tracking the whole set as one named RELEASE (Topic 7.3 covers releases, upgrades, and rollbacks as their own dedicated topic).
Code & diagrams
Values fill in the blanks in the templates — the same idea as Phase 2.1's ConfigMap, applied to whole manifests.
A chart's actual directory structure, and the two commands that matter most while learning it.
my-app-chart/
├── Chart.yaml # name, version, description
├── values.yaml # default configuration
└── templates/
├── deployment.yaml
├── service.yaml
└── configmap.yaml
# Preview the rendered output WITHOUT installing anything
helm template my-release ./my-app-chart
# Preview with a SPECIFIC value overridden
helm template my-release ./my-app-chart --set replicaCount=5
# Actually install it — tracked as a named "release"
helm install my-release ./my-app-chart
# Confirm what Helm actually applied
kubectl get deployment my-release-my-app-chartExplain it without notes
What's the practical difference between a chart's values.yaml and its templates/ folder, in terms of what each one is responsible for?
Why is helm template genuinely useful to run before helm install, especially the first time you're using an unfamiliar chart?
Practice
Create a minimal chart (Chart.yaml, values.yaml, and one templated Deployment) and run helm template against it, confirming the values substitute correctly into the rendered output.
Run helm template on the same chart twice, once with default values and once with --set overriding one value, and compare the two rendered outputs directly.
Trade-offs
- ↔
Templating adds real indirection compared to a plain, static YAML file — reading a heavily templated file in isolation can be genuinely harder to follow than reading the final, rendered manifest directly, which is exactly why
helm template's ability to preview the rendered output is worth reaching for often, not just once at the very start of learning a chart.
Done when you can
I understand the role of Chart.yaml, values.yaml, and the templates/ folder.
I can use helm template to preview a chart's rendered output without installing anything.
I understand how overriding a value changes the final rendered manifest without touching any template.