AI Hints
Home›Kubernetes Tutorial›Helm and Kustomize
Kubernetes · Lesson 47 of 86

Writing Charts

Templates and values.

⏱ 2 min read▶ Video at 1:55:27🎓 Free
Watch this lesson in the Kubernetes courseWatch on YouTube ↗Full Kubernetes course

Using other people's charts is useful. But sooner or later, you will package your own app. A chart is simply your Y A M L files, with the changing parts replaced by variables. In this lesson, you will see the folder layout, the templates, and the values that fill them in.

Writing Charts
From the video: Writing Charts
  • A chart is a folder
  • Templates hold placeholders
  • Values fill them in

The anatomy of a chart

A chart has a simple layout. Chart dot yaml is the identity card, with the name and the version. Values dot yaml holds the default settings. The templates folder holds your Kubernetes files, with placeholders. And optional folders hold sub charts, the dependencies. When you install, Helm combines the templates with the values, and sends the finished Y A M L to the cluster.

  1. Chart.yamlname and version
  2. values.yamldefault settings
  3. templates/Kubernetes files with placeholders
  4. charts/dependencies

A template

Here is a template. It looks like a normal deployment, but some values are written in double curly braces. The release name, becomes part of the object's name, so two releases never clash. The replica count is read from the values. And the image comes from two values, the repository, and the tag. So the same template can produce a small test setup, or a large production one, depending on the values.

templates/deployment.yamlyaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-web
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ .Release.Name }}
  template:
    metadata:
      labels:
        app: {{ .Release.Name }}
    spec:
      containers:
      - name: web
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"

The values file

And here are the default values. A replica count of two, and the image, engine X, tag one point twenty seven. When you install, you can override any of them. Dash dash set changes one value, and dash f points to your own values file, for example, one file per environment. Keep the chart generic, and put the differences in the values.

values.yamlyaml
replicaCount: 2

image:
  repository: nginx
  tag: "1.27"

Create, lint, template, install

Helm can scaffold a chart for you. The create command makes a folder, with all the standard files. We look at its default values. Lint checks the chart for mistakes. Template renders the finished Y A M L on your screen, without touching the cluster, a great way to debug. And install sends it to the cluster. The release is listed, and its pods are running.

helm
helm create mychart
Creating mychart
ls mychart
Chart.yaml
charts
templates
values.yaml
grep -v '^ *#' mychart/values.yaml | grep -v '^$' | head -8
replicaCount: 1
image:
  repository: nginx
  pullPolicy: IfNotPresent
  tag: ""
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
helm lint mychart
==> Linting mychart
[INFO] Chart.yaml: icon is recommended

1 chart(s) linted, 0 chart(s) failed
helm template demo mychart | head -12
---
# Source: mychart/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: demo-mychart
  labels:
    helm.sh/chart: mychart-0.1.0
    app.kubernetes.io/name: mychart
helm install demo ./mychart --set replicaCount=2 --wait
NAME: demo
LAST DEPLOYED: Fri Oct 30 23:42:00 2026
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
  export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=mychart,app.kubernetes.io/instance=demo" -o jsonpath="{.items[0].metadata.name}")
  export CONTAINER_PORT=$(kubectl get pod --namespace default $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
helm list
NAME    NAMESPACE       REVISION        UPDATED                                 STATUS          CHART           APP VERSION
demo    default         1               2026-10-30 23:42:00.213695 +0300 +03    deployed        mychart-0.1.0   1.16.0
kubectl get pods -l app.kubernetes.io/instance=demo
NAME                           READY   STATUS    RESTARTS   AGE
demo-mychart-98bffbb88-bxgwv   1/1     Running   0          7s
demo-mychart-98bffbb88-x2mp9   1/1     Running   0          7s

Summary

Wonderful. A chart is a folder, templates hold placeholders, and values fill them in. You can lint, template, and install your own charts. Next, a different approach to the same problem, without templates, Kustomize.

Key takeaways
  • Chart.yaml, values.yaml, templates/
  • {{ .Values.x }} placeholders
  • helm template previews safely
Next up: Kustomize — customising without templates