Skip to main content

Lesson: Anatomy of a Chart

What you'll learn

  • The standard files and folders inside a Helm chart.
  • What Chart.yaml, values.yaml, and templates/ each do.
  • How Helm's templating turns templates + values into real Kubernetes YAML.
  • What _helpers.tpl and NOTES.txt are for.

By the end you'll be able to open any chart and know what each part does.


The lesson

1. The chart directory layout

Run helm create demo and you get this structure — the standard shape of every chart:

demo/
├── Chart.yaml          # metadata: name, version, appVersion, description
├── values.yaml         # default configuration values (the knobs)
├── templates/          # the templated Kubernetes manifests
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── ingress.yaml
│   ├── _helpers.tpl    # reusable template snippets (no manifest output)
│   └── NOTES.txt       # message shown after install
├── charts/             # subcharts (dependencies), if any
└── .helmignore         # files to exclude when packaging

2. Chart.yaml — the package's identity

This is the chart's metadata. The two version fields trip people up, so learn them now:

apiVersion: v2
name: demo
description: A demo web app
version: 0.1.0        # the CHART version (bump when you change the chart)
appVersion: "1.4.2"   # the version of the APP the chart deploys (informational)
  • version = the chart package version (used by repos and helm upgrade).
  • appVersion = which version of the underlying application it installs.

3. values.yaml — the knobs

values.yaml holds the default configuration. Anything you might want to change per environment lives here:

replicaCount: 1
image:
  repository: 10.100.100.6/demo
  tag: "1.4.2"
service:
  port: 80
ingress:
  enabled: false
  host: demo.example.com

At install time you override these — either with --set key=value or a custom values file (-f prod-values.yaml). Override order: chart defaults → -f files → --set (last wins).

4. templates/ — manifests with blanks to fill

The files in templates/ are normal Kubernetes manifests plus Go templating ({{ }}). Helm renders them by substituting your values. A trimmed deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "demo.fullname" . }}
spec:
  replicas: {{ .Values.replicaCount }}        # ← from values.yaml
  template:
    spec:
      containers:
        - name: demo
          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
templates/deployment.yaml   +   values.yaml
            \                      /
             \   helm renders     /
              ▼                  ▼
        a real Deployment manifest (replicas: 1, image: 10.100.100.6/demo:1.4.2)

Common template gadgets you'll see:

  • .Values.x — a value from values.yaml.
  • .Release.Name — the name you gave at install (e.g. web-prod).
  • .Chart.Name / .Chart.Version — from Chart.yaml.
  • {{ if .Values.ingress.enabled }} … {{ end }} — conditional blocks.
  • {{- ... -}} — the dashes trim surrounding whitespace (keeps output tidy).

5. _helpers.tpl and NOTES.txt

  • _helpers.tpl — files starting with _ produce no manifest; they hold reusable named snippets (like the demo.fullname used above) so you don't repeat naming/label logic in every template.
  • NOTES.txt — a templated message printed after helm install, e.g. "Your app is available at …". Friendly, optional.

6. See what it renders — without touching the cluster

The single most useful habit: render locally and read the YAML before you install.

helm template web-dev ./demo -f dev-values.yaml   # prints the final manifests, applies nothing
helm lint ./demo                                  # checks the chart for problems

helm template is your X-ray: it shows exactly the Kubernetes objects Helm will create. Use it constantly while learning.


Dig deeper

Search terms

  • helm chart structure explained
  • helm chart version vs appVersion
  • helm values.yaml override --set vs -f
  • helm template go templating tutorial
  • helm _helpers.tpl named templates

Check yourself

  1. What is the purpose of Chart.yaml vs values.yaml?
  2. What's the difference between version and appVersion?
  3. How does {{ .Values.replicaCount }} in a template get its value?
  4. What does a file like _helpers.tpl do, and why does it start with an underscore?
  5. Which command shows the final rendered manifests without installing anything?