What are the key parts of a Helm chart?
Quick Answer
`Chart.yaml` holds the chart's own metadata (name, version, description, dependencies). `values.yaml` defines the default configuration values the templates reference. The `templates/` directory holds the actual Kubernetes manifest templates, written in Go template syntax, referencing values from `values.yaml` (and built-in objects like `.Release` and `.Chart`). Optional additions include `charts/` (bundled subchart dependencies), `_helpers.tpl` (reusable template snippets/functions), and a `NOTES.txt` (shown to the user after install/upgrade).
Detailed Answer
The standard chart layout
mychart/
├── Chart.yaml # chart metadata
├── values.yaml # default configuration values
├── charts/ # bundled dependency charts (subcharts)
├── templates/
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── configmap.yaml
│ ├── _helpers.tpl # reusable template snippets (not rendered as its own manifest)
│ └── NOTES.txt # shown to the user after helm install/upgrade
└── .helmignore # files to exclude when packaging the chart
Chart.yaml — the chart's own identity
apiVersion: v2
name: mychart
description: A Helm chart for my application
version: 1.2.0 # the CHART's own version
appVersion: "2.4.0" # the version of the application it deploys (informational)
dependencies:
- name: postgresql
version: "12.x.x"
repository: "https://charts.bitnami.com/bitnami"
Note the important distinction between version (the chart's own packaging version, incremented whenever the chart's templates/structure change) and appVersion (the version of the actual application inside, purely informational, not used by Helm's own versioning logic) — conflating these two is a common early mistake.
values.yaml — default configuration
replicaCount: 2
image:
repository: myapp
tag: "1.0.0"
resources:
requests:
cpu: "100m"
memory: "128Mi"
Every value referenced in the templates ({{ .Values.replicaCount }}) has a default here — overridden per-install via --set replicaCount=5 or a separate --values production.yaml file, without ever touching the templates themselves.
templates/ — the actual manifest templates
Written in Go's templating language, with access to several built-in objects beyond just .Values:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-web # .Release: info about this specific install
labels:
chart: {{ .Chart.Name }}-{{ .Chart.Version }} # .Chart: this chart's own metadata
spec:
replicas: {{ .Values.replicaCount }} # .Values: user-supplied or default config
_helpers.tpl — reusable snippets, not a standalone manifest
{{- define "mychart.fullname" -}}
{{ .Release.Name }}-{{ .Chart.Name }}
{{- end -}}
Files starting with an underscore aren't rendered as Kubernetes manifests themselves — they define reusable named template snippets (like a function) that other templates can invoke ({{ include "mychart.fullname" . }}), avoiding repetition of common logic (like generating consistent resource names or labels) across many template files.
charts/ — bundled subchart dependencies
If Chart.yaml declares dependencies, running helm dependency update downloads and places them here as .tgz packages, letting a parent chart compose several other charts together (e.g., an application chart depending on a redis subchart for its caching layer) as one cohesive, installable unit.
NOTES.txt — post-install guidance
Rendered with the same templating engine and printed to the user's terminal immediately after a successful helm install/helm upgrade — commonly used to show next steps, like the command to retrieve a generated admin password, or the URL the application will be reachable at.