Most CKAD candidates learn to write a Deployment YAML by hand and stop there. But the exam’s Application Deployment domain expects more than raw manifests — it expects you to package and ship the same application into different environments without copy-pasting YAML and hand-editing image tags. That is exactly the problem Helm and Kustomize solve, and both are named tools on the current CKAD curriculum.
This guide takes a developer’s view of the two tools for the CKAD exam. We won’t rebuild your app from scratch — you already know how to write a Pod spec. Instead we’ll focus on the workflow the exam tests: take an application you own, and use Kustomize overlays or a Helm chart to deploy it to dev, staging, and prod, changing only what needs to change per environment. If you also sit the CKA, the CKA Helm & Kustomize guide is the cluster-admin companion to this page — same tools, more of an operator’s angle.
Why a Developer Needs Helm or Kustomize
Imagine your app is a Deployment plus a Service plus a ConfigMap. It runs fine in dev. Now you need it in staging with 3 replicas, a different image tag, and a staging- name prefix, and in prod with 6 replicas and a production database URL. The naive approach — three near-identical copies of the same YAML — rots immediately: a fix in one copy silently drifts from the others.
Kustomize and Helm both eliminate that duplication, using opposite philosophies:
| Tool | Core idea | You write… | You get… |
|---|---|---|---|
| Kustomize | Overlay patches on a shared base | Plain YAML + small patches | Merged plain YAML — no templating language |
| Helm | Template + values | A chart with {{ }} placeholders | Rendered YAML from a values file |
Kustomize is template-free: everything is valid Kubernetes YAML that gets layered. Helm is a package manager: a chart is parameterized and you fill in the blanks. Both are built to answer the same question — “how do I run this one application in many places?” The exam rewards knowing which levers each tool exposes and how to pull them quickly.
Kustomize Fundamentals: Base + Overlays
Kustomize is built into kubectl (kubectl apply -k, kubectl kustomize), so on the exam there is nothing to install. The unit of a Kustomize project is a directory containing a kustomization.yaml file.
A base holds the resources common to every environment:
app/
├── base/
│ ├── kustomization.yaml
│ ├── deployment.yaml
│ └── service.yaml
└── overlays/
├── staging/
│ └── kustomization.yaml
└── prod/
└── kustomization.yaml
The base kustomization.yaml simply lists its resources:
# base/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
An overlay references the base and applies environment-specific changes on top:
# overlays/prod/kustomization.yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../../base
namePrefix: prod-
namespace: production
commonLabels:
environment: prod
replicas:
- name: web
count: 6
images:
- name: myorg/web
newTag: "2.4.1"
That one overlay renames everything with a prod- prefix, drops it into the production namespace, stamps an environment: prod label on every resource, scales the web Deployment to 6, and pins the image tag — all without touching the base. The staging overlay does the same with different numbers. The base never changes.
The fields the exam actually uses
You do not need every Kustomize transformer. These are the ones worth committing to muscle memory:
| Field | Effect |
|---|---|
resources | Files or directories (including other bases) to include |
namePrefix / nameSuffix | Prepend/append to every resource name |
namespace | Force all resources into one namespace |
commonLabels | Add labels to every resource and to selectors |
commonAnnotations | Add annotations to every resource |
images | Override image name/tag without editing the Deployment |
replicas | Override replica counts by resource name |
configMapGenerator | Generate a ConfigMap (with a content hash suffix) |
patches | Strategic-merge or JSON 6902 patches for anything else |
commonLabels deserves a warning: because it also rewrites label selectors, changing it on a live Deployment can produce an immutable-selector error. Prefer commonLabels for values fixed at creation (like environment) and use labels (metadata-only) or annotations for things that change later.
Applying and Inspecting Kustomize
Two commands cover the exam:
# Render the merged YAML to stdout — inspect before you touch the cluster
kubectl kustomize overlays/prod
# Build AND apply in one step
kubectl apply -k overlays/prod
Always kubectl kustomize first when a task says “verify” or “review” — you can eyeball the prefix, replica count, and image tag before applying. To remove what an overlay created, kubectl delete -k overlays/prod.
kustomize edit set image — a real developer task
A classic exam-style instruction is “update the web Deployment to use image myorg/web:2.5.0.” If the standalone kustomize binary is present you can do this without opening an editor:
cd overlays/prod
kustomize edit set image myorg/web=myorg/web:2.5.0
kubectl apply -k .
kustomize edit set image rewrites the images: block for you. If only kubectl is available, add or edit the images: entry in kustomization.yaml by hand — the effect is identical. Either way, the point the exam is testing is that you bump an image through the overlay, not by editing the base Deployment.
configMapGenerator and the hash suffix
Kustomize can build a ConfigMap from literals or files and append a content hash to its name:
configMapGenerator:
- name: web-config
literals:
- LOG_LEVEL=info
- FEATURE_X=true
The generated name becomes something like web-config-8t2hk6c9fd, and Kustomize automatically rewrites every reference to it in your Deployment. The payoff: when the config content changes, the hash changes, the Deployment’s pod template changes, and a rollout is triggered — so config changes actually redeploy your pods instead of silently sitting unused. If you need a stable name, set generatorOptions: { disableNameSuffixHash: true }.
Helm Fundamentals: Charts, Releases & Values
Helm approaches the same problem as a package manager. Three terms carry the exam weight:
- Chart — a packaged, templated application (a directory or
.tgzof templates + avalues.yaml). - Release — a specific installation of a chart into a cluster, with a name (
helm install web ./chartcreates thewebrelease). - Repository — a place charts are hosted and pulled from.
A chart directory looks like this:
mychart/
├── Chart.yaml # name, version, appVersion
├── values.yaml # default values
└── templates/
├── deployment.yaml # uses {{ .Values.image.tag }}
└── service.yaml
Inside a template, values are interpolated with Go templating:
spec:
replicas: {{ .Values.replicaCount }}
template:
spec:
containers:
- name: web
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
For CKAD you are far more likely to consume and configure a chart than author one, so focus your practice on the lifecycle commands and value overrides.
The Helm lifecycle commands
# Install a chart as a named release
helm install web ./mychart
# See what's installed
helm list
# Change configuration / upgrade to a new chart version
helm upgrade web ./mychart --set image.tag=2.5.0
# Undo — roll back to the previous revision
helm rollback web 1
# Remove the release entirely
helm uninstall web
helm upgrade is idempotent and revision-tracked: every install/upgrade bumps a revision number, and helm rollback <release> <revision> returns to an earlier one. That revision history is Helm’s built-in answer to “undo my last change,” and it’s worth mentioning when a task asks you to revert.
Overriding Helm Values
This is where per-environment configuration lives, and it’s the Helm skill the exam most reliably probes. Two mechanisms, and you can combine them:
# Inline overrides (highest priority) — great for one or two values
helm install web ./mychart --set replicaCount=6 --set image.tag=2.5.0
# A values file — best for many environment-specific settings
helm install web ./mychart -f values-prod.yaml
Precedence runs from lowest to highest: the chart’s own values.yaml → any -f files (in order) → --set flags. So --set always wins over a values file, which always wins over the chart defaults. For nested values, --set uses dotted paths (--set image.tag=2.5.0); for lists, use brackets (--set ports[0]=8080).
Inspect before you apply
Just as kubectl kustomize renders Kustomize output, Helm can render a chart without touching the cluster:
# Render templates locally with your overrides — nothing is installed
helm template web ./mychart -f values-prod.yaml
# Simulate an install server-side and show what would change
helm install web ./mychart --dry-run --debug
Use helm template when a task asks you to verify the generated manifests, and --dry-run when you want the API server’s opinion (including validation) before committing. Reading the rendered output is the single fastest way to confirm your --set flags landed where you expected.
Helm vs Kustomize: Which for What
| Situation | Reach for |
|---|---|
| Deploying a third-party app someone already packaged | Helm (install the chart) |
| Small per-environment tweaks to YAML you own | Kustomize (an overlay) |
| You want zero templating language, just layered YAML | Kustomize |
You need versioned releases with rollback and repos | Helm |
| Bumping just an image tag across environments | Either — kustomize edit set image or --set image.tag |
They are not mutually exclusive: a common real-world pattern is to helm template a chart and pipe it through Kustomize for last-mile patches. On the exam, though, a task will point you at one or the other — the giveaway is whether you’re handed a kustomization.yaml/overlay directory (Kustomize) or a chart directory / repo reference (Helm).
Exam-Day Workflow & Speed Tips
- Read what you were given. A
kustomization.yamlin the question directory means Kustomize; aChart.yamlor ahelm repo addhint means Helm. Don’t hand-edit Deployments when the task clearly wants an overlay or a value override. - Inspect, then apply.
kubectl kustomize <dir>andhelm template <release> <chart>are read-only and fast. Confirm the change is present before you apply, so you’re not debugging a live cluster. - Bump images through the tool, not the base. Use
kustomize edit set imageorhelm upgrade --set image.tag=.... Editing the base Deployment defeats the point and can cost you the mark. - Know your rollback. For Helm,
helm rollback <release> <revision>afterhelm history <release>. For Kustomize, re-apply the previous overlay state. - Namespaces matter. Kustomize overlays often set
namespace:; Helm installs take-n <namespace>. Verify withkubectl get all -n <ns>after applying.
Common Pitfalls
- Editing the base instead of the overlay. Every environment inherits the base — change it and you change all of them. Environment-specific tweaks belong in the overlay.
- Forgetting
-k/kubectl kustomizevs plain-f.kubectl apply -f kustomization.yamldoes not run Kustomize; you need-k <dir>orkubectl kustomize <dir>. --settype surprises.--set replicaCount=6is fine, but quoted numbers or booleans can render as strings; usehelm templateto confirm the rendered type.commonLabelson a running Deployment. Selectors are immutable — addingcommonLabelsafter creation can fail. Decide on those labels up front.- Assuming config edits redeploy. A plain ConfigMap edit does not restart pods.
configMapGenerator’s hash suffix (Kustomize) or bumping a value that lands in the pod template (Helm) is what forces the rollout.
Practice in Realistic Exam Conditions
Helm and Kustomize are muscle-memory topics: the commands are short, but under a two-hour clock you need them to be automatic. Reading about kubectl apply -k is not the same as scaffolding a base, writing a prod overlay, bumping an image, and verifying the result against a live cluster with the timer running.
The Certified Kubernetes Application Developer (CKAD) Mock Exam Bundle gives you five full-length, performance-based mock exams in a browser terminal against a real Kubernetes cluster — the same hands-on format as exam day — with Application Deployment tasks (overlays, image bumps, release upgrades and rollbacks) among the scenarios. Pair it with the 30-day CKAD study plan to sequence deployment tooling alongside the rest of the syllabus, and skim the CKAD exam domains breakdown to see how Application Deployment is weighted against Design and Build, Observability, and the rest.
Conclusion
For the CKAD, Helm and Kustomize are about one skill: shipping the same application into different environments without duplicating YAML. Kustomize layers plain YAML — a base plus overlays that set prefixes, namespaces, replica counts, and image tags. Helm parameterizes a chart and installs it as a versioned release you can upgrade and rollback, with --set and -f for per-environment values. Learn to inspect before you apply (kubectl kustomize, helm template), bump images through the tool rather than the base, and recognize from the files you’re given which tool the task wants. Drill those flows on a live cluster and the Application Deployment questions become some of the fastest points on the exam.
For adjacent topics, review Deployments, rolling updates & rollbacks, building container images (the image your chart or overlay ships), ConfigMaps & Secrets (what configMapGenerator and chart values feed into), and blue/green & canary strategies. Keep the CKAD kubectl cheat sheet close for the apply/inspect commands.
Frequently Asked Questions
Are Helm and Kustomize really on the CKAD exam?
Yes. The Application Deployment domain of the current CKAD curriculum names both — using Kustomize to manage and dynamically update resources, and understanding Helm to deploy packaged applications. Expect tasks that hand you an overlay or a chart and ask you to configure and apply it.
Do I need to install Kustomize separately?
No. Kustomize is built into kubectl as kubectl apply -k and kubectl kustomize. The standalone kustomize binary adds conveniences like kustomize edit set image, but you can achieve the same result by editing kustomization.yaml directly.
How do I change an image tag with each tool?
With Kustomize, set it in the overlay’s images: block (or run kustomize edit set image name=name:tag) and kubectl apply -k. With Helm, helm upgrade <release> <chart> --set image.tag=<tag> (assuming the chart wires that value into the container image).
How do I undo a bad Helm change?
helm history <release> shows the revisions, then helm rollback <release> <revision> returns to an earlier one. Helm tracks every install and upgrade as a numbered revision, so rollback is a first-class operation.
Should I render output before applying?
Yes — it’s the fastest way to catch mistakes. kubectl kustomize <dir> and helm template <release> <chart> render the final YAML locally without touching the cluster, so you can confirm your prefixes, replica counts, and value overrides landed correctly before you apply.
Helm or Kustomize — which should I learn first for CKAD?
Learn Kustomize first: it’s built into kubectl, has no templating language, and its base/overlay model maps directly to the “deploy across environments” tasks the exam favors. Then add Helm’s install/upgrade/rollback and value-override flow.