What are the key parts of a Helm chart?

6 minintermediatehelm-chartchart-structure

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.