YAML with Go templates layered on top
Helm is Kubernetes' package manager. A chart is a directory of YAML templates. helm install renders the templates against a values.yaml file and applies the result. Same K8s manifests at the bottom; a templating layer in the middle lets one chart deploy to dev/staging/prod with different values.
Chart layout
Chart.yaml— chart metadata.values.yaml— default values (the chart's API).templates/— YAML templates with{{ .Values.x }}substitution.charts/— sub-charts.
The string-quoting trap
Helm templates output text. The result is then parsed as YAML. So a template that emits a bare value gets re-typed by YAML — {{ .Values.port }} with port: 8000 becomes the integer 8000, even where K8s expects a string. Quote the rendered output explicitly: {{ .Values.port | quote }} or wrap in quotes.
The 'rendered YAML is sometimes invalid YAML' problem: Helm templates can produce broken YAML (missing newlines, double-pipes, mistabbed blocks). Always run
helm template ./chart and pipe through kubeconform or yq . in CI — render-time validation, not just deploy-time.