Without a tool like Helm, you would have to manually write and rewrite dozens of configuration files every time you wanted to install, update, or remove an application in Kubernetes. That is slow, error-prone, and impossible to do consistently at scale. For the CKAD exam, you need to understand how to design and package applications using Helm charts so you can deploy complex software without repeating yourself or breaking things.
Jump to a section
A simple way to picture Designing and Using Helm Charts for Application Packaging
Your grandmother's kitchen, late Sunday afternoon. The counter is covered with bowls, measuring cups, and ingredients. Your cousin is trying to bake her famous apple pie for the first time. Instead of watching her struggle to find the right recipe card in a messy drawer, you hand her a thick, well-organised binder. Inside, every recipe is written on a standard template: one card for the pie crust, one for the apple filling, one for the crumble topping. Each card lists the exact ingredients (flour, butter, sugar, cinnamon) and the precise steps (chill the dough for 30 minutes, preheat the oven to 190 degrees Celsius).
But the real magic is how the binder works. It has "values sheets" — separate pages that let you customise any recipe without rewriting the whole card. Is your cousin allergic to nuts? She writes "substitute almond extract with vanilla" on a values sheet, slides it under the pie filling card, and the recipe automatically adjusts. Is she baking for a party of twelve instead of six? She changes the serving size on a different values sheet, and every ingredient amount scales up perfectly. Later, her brother wants to make the same pie for a gluten-free friend. He grabs the same binder, writes "replace all-purpose flour with gluten-free blend" on a new values sheet, and the recipe works without touching a single original card.
The binder itself is the Helm chart. Each recipe card is a Kubernetes resource template — a blueprint for a part of your application (a container, a network rule, a storage volume). The values sheets are your configuration files (values.yaml). Your cousin is a developer deploying an app to a test environment. Her brother is an operator deploying the same app to production, with different settings. Everyone uses the same binder. No one rewrites the recipe from scratch.
Helm is a tool that helps you package and manage Kubernetes applications. Think of Kubernetes as the operating system for running containers — and Helm as the app store and package manager combined. Just like you use a package manager on your computer (like APT on Ubuntu or Homebrew on macOS) to install and update software without hunting down files, Helm lets you install, upgrade, and remove entire Kubernetes applications with simple commands.
A Helm chart is a collection of files that describe a set of Kubernetes resources. Instead of writing a separate YAML file for a Deployment, a Service, a ConfigMap, and a PersistentVolumeClaim, you put them all into one chart. The chart is like a blueprint for your application. It includes templates — these are YAML files with placeholders, written in a special language called Go templates. The placeholders get filled in with actual values when you install the chart.
The values are stored in a file called values.yaml. This file is the central place where you define things like the number of replicas (how many copies of your app to run), the image tag (which version of the container to use), and the port your app listens on. When someone installs the chart, Helm takes the templates and merges them with the values from values.yaml to produce the final Kubernetes YAML files. Those files are then sent to the Kubernetes API, which creates the actual resources.
This design solves a huge problem: configuration drift. If you manually edit YAML files in different environments (development, staging, production), they quickly become inconsistent. With Helm, you keep one chart and one set of templates. You change only the values.yaml file for each environment. For example, your development values.yaml might set replicas to 1 and use a debug image tag. Your production values.yaml sets replicas to 5 and uses a stable image tag. The templates never change. This is called separation of concerns — the structure (the templates) is separate from the settings (the values).
Helm also manages releases. Every time you install a chart, Helm creates a release — a record of that installation. You can upgrade a release with new values, roll back to a previous version, or delete the release entirely. This is critical for application lifecycle management. In the old way, you would have to track your YAML files manually and apply them with kubectl apply. If something went wrong, rolling back meant finding the old files and hoping you remembered the correct state. With Helm, one command rolls back to the previous release.
Key terms in Helm:
Chart: A packaged collection of files that define a Kubernetes application.
Release: A running instance of a chart. You can have multiple releases of the same chart (e.g., one for testing, one for production).
Repository: A place where charts are stored and shared, like an app store.
Template: A YAML file with placeholders written in Go template syntax (e.g., {{ .Values.replicaCount }}).
values.yaml: The default configuration file for a chart.
Dependencies: Charts can depend on other charts. For example, your app chart might depend on a database chart (like PostgreSQL).
A simple example. Suppose you have a web app that needs a Deployment and a Service. Without Helm, you would write two YAML files:
deployment.yaml:
apiVersion: apps/v1 kind: Deployment metadata: name: my-web-app spec: replicas: 3 selector: matchLabels: app: my-web-app template: metadata: labels: app: my-web-app spec: containers: - name: web image: nginx:1.21 ports: - containerPort: 80
service.yaml:
apiVersion: v1 kind: Service metadata: name: my-web-app-svc spec: selector: app: my-web-app ports: - port: 80 targetPort: 80
With Helm, you create a chart structure:
mychart/ Chart.yaml values.yaml templates/ deployment.yaml service.yaml
The Chart.yaml file contains metadata about the chart (name, version, description). The values.yaml file contains:
replicaCount: 3 image: repository: nginx tag: "1.21" service: port: 80
The deployment.yaml template looks like this:
apiVersion: apps/v1 kind: Deployment metadata: name: {{ .Values.nameOverride | default "my-web-app" }} spec: replicas: {{ .Values.replicaCount }} selector: matchLabels: app: {{ .Values.nameOverride | default "my-web-app" }} template: metadata: labels: spec: containers: - name: {{ .Chart.Name }} image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" ports: - containerPort: {{ .Values.service.port }}
When you run helm install my-release ./mychart, Helm processes the templates, replaces the placeholders with the values from values.yaml, and creates the Deployment and Service in Kubernetes. If you want to change the number of replicas to 5 for production, you create a new values file (prod-values.yaml) with replicaCount: 5 and run helm upgrade my-release ./mychart -f prod-values.yaml.
This is the heart of designing and using Helm charts for application packaging. You design the templates once, and you package them as a chart that can be shared, versioned, and reused across environments.
Create the chart skeleton
Run helm create mychart from the terminal. This generates a standard directory structure with a Chart.yaml (metadata), values.yaml (default config), templates/ folder (with starter Deployment and Service YAML), and a charts/ folder (for dependencies). This scaffold saves you from writing every file from scratch and ensures your chart follows Helm conventions expected by the exam.
Define default configuration in values.yaml
Open values.yaml and add key-value pairs for every configurable aspect of your application, such as replicaCount, image.repository, image.tag, service.port, and ingress.enabled. Use meaningful default values that work in a development environment. This file becomes the single source of truth for all configurable parameters. In the exam, you may need to add a new parameter to an existing values.yaml.
Write Go template placeholders in resource YAML files
In the templates/ folder, edit the Deployment.yaml, Service.yaml, and any other resource files. Replace hard-coded values with {{ .Values.replicaCount }}, {{ .Values.image.repository }}:{{ .Values.image.tag }}, etc. Use the default function for optional values: {{ .Values.service.port | default 80 }}. This makes your templates dynamic and reusable across environments. The exam tests your ability to write correct template syntax, especially handling missing values.
Install the chart to test it
Run helm install test-release ./mychart to deploy the chart to your Kubernetes cluster. This command processes all templates, merges them with values.yaml, sends the resulting Kubernetes resources to the API server, and creates a release named test-release. If there is a syntax error in your templates, Helm will report it here. Use helm template ./mychart to render templates locally first without installing, which is faster for debugging.
Override default values for different environments
Create a separate values file for production, e.g., prod-values.yaml, that overrides specific keys like replicaCount: 5 and image.tag: "v1.0.0". Then run helm upgrade test-release ./mychart -f prod-values.yaml. This demonstrates the separation of configuration from template logic. In the exam, you may be asked to deploy a chart with a specific values file or --set flag.
Add a dependency to another chart
Edit Chart.yaml to add a dependencies section listing a chart name, version, and repository. Then run helm dependency update ./mychart to download the dependency into the charts/ subdirectory. You can then reference the dependency's resources when you install your chart. This is crucial for composing applications from reusable components, and the exam may require you to add a dependency and then install the parent chart.
Roll back a failed upgrade
If an upgrade introduces a bug, run helm rollback test-release 1 to revert to the first revision. Helm keeps a history of releases (revisions), so you can always go back to a known good state. This lifecycle management feature is a core exam concept — you must know how to undo a change without manual kubectl commands.
An IT professional working for a mid-sized e-commerce company is responsible for deploying a microservices-based application. The application consists of ten services: a web frontend, an authentication service, a product catalogue service, a shopping cart service, an order service, a payment service, a notification service, and three data stores (PostgreSQL, Redis, and Elasticsearch). Each service has its own Kubernetes resources: Deployments, Services, ConfigMaps, and sometimes PersistentVolumeClaims and NetworkPolicies.
Without Helm, the engineer would have to manage approximately forty separate YAML files. Every time a new version of a service is released, they would need to edit the corresponding Deployment file (changing the container image tag), and then run kubectl apply on each file. If one service requires a configuration change (like a new database connection string), they must update the ConfigMap YAML file and possibly restart the pods. This manual process is prone to typographical errors, leading to outages. For example, a missing indentation in a YAML file could cause the Deployment to fail silently.
The engineer decides to convert each microservice into a Helm chart. They create a structure like this:
backend/ charts/ auth/ catalogue/ cart/ orders/ payments/ notifications/ Chart.yaml values.yaml
Each sub-chart has its own templates and default values. The engineer creates one global values.yaml file that sets common defaults (like the Kubernetes namespace, the container registry URL, and the logging level). For environment-specific customisation, they create separate values files:
development.yaml: replicaCount: 1 imageTag: "latest" resources: limits: memory: "256Mi" cpu: "250m"
staging.yaml: replicaCount: 2 imageTag: "staging-20231001" resources: limits: memory: "512Mi" cpu: "500m"
production.yaml: replicaCount: 5 imageTag: "v1.2.3" resources: limits: memory: "1Gi" cpu: "1" requests: memory: "512Mi" cpu: "500m"
To deploy to staging, the engineer runs:
helm upgrade --install ecommerce-staging ./backend -f staging.yaml --namespace staging
This single command installs all ten services with the correct configurations. If the staging deployment breaks, the engineer can roll back quickly:
helm rollback ecommerce-staging 1
This reverts to the previous working release. In production, the engineer uses a CI/CD pipeline that automatically runs helm upgrade with the production values file whenever a new Git tag is pushed. The pipeline also runs helm lint before deployment to check for chart errors.
Helm charts are also stored in a chart repository (like an HTTTP server or a cloud storage bucket). The company uses a private Helm repository so that all teams can discover and reuse charts. For example, the platform team publishes a standard PostgreSQL chart that all microservice teams can depend on. This reduces duplication and ensures consistency (e.g., all databases use the same backup configuration).
The engineer also uses Helm hooks — special annotations in templates that run jobs before or after a release. For example, a pre-upgrade hook runs a database migration Job before the new version of the app deploys. A post-delete hook runs a cleanup Job to remove orphaned resources.
In summary, the real-world benefit is speed and reliability. What used to take thirty minutes of manual file editing and kubectl commands now takes a single Helm command that takes seconds. The risk of human error drops dramatically. The team can focus on developing features rather than fighting with configuration files.
The CKAD exam tests your ability to design, package, and use Helm charts in a hands-on environment. You will be given a terminal with a Kubernetes cluster and expected to complete tasks within a time limit. The exam objectives for section 3.1 — Design and package applications using Helm — cover the following specific skills:
Creating a Helm chart from scratch using helm create.
Understanding the chart directory structure (Chart.yaml, values.yaml, templates/, charts/, README.md).
Writing and editing template files using Go template syntax (e.g., {{ .Values.replicaCount }}, {{ .Release.Name }}, {{ .Chart.Name }}).
Using built-in Helm objects like .Values, .Release, .Chart, .Files, and .Capabilities.
Supplying configuration values at install and upgrade time using --set and -f (values files).
Installing, upgrading, rolling back, and uninstalling a release.
Understanding chart dependencies and how to manage them (dependencies in Chart.yaml, helm dependency update).
Using helm lint to check chart validity and helm template to render templates locally without installing.
Working with common template functions like default, quote, and indent.
Exam traps and what they test:
Values hierarchy and precedence: Exam questions often test that you know how values are merged. The precedence from lowest to highest is: built-in defaults in templates, values.yaml in the chart, parent chart values (for subcharts), user-supplied values file (-f), and finally --set flags. A typical question gives a values.yaml with a key and a --set flag that overrides it. You must know that --set wins. A trap is to assume the values file overrides everything.
Go template syntax errors: The exam environment will not give you syntax hints. If you write {{ .Values.nonexistent }} and the value is missing, the template rendering fails unless you use the default function: {{ .Values.nonexistent | default "fallback" }}. They test your ability to handle missing values gracefully.
Chart name and release name constraints: Chart names and release names must follow DNS-1123 conventions (lowercase, alphanumeric, hyphens only). A question may ask you to create a chart with an invalid name to see if you catch the error.
Dependencies: You might be asked to add a dependency on an existing chart (like a database from a repository). The trap is forgetting to run helm dependency update after editing the Chart.yaml dependencies block. Without it, the dependent chart is not downloaded.
Subcharts and global values: A parent chart can pass values to subcharts using the same key hierarchy. Exam questions test your understanding of how global values (under .Values.global) are inherited by all subcharts. A common trap is thinking subcharts can access any parent value directly — they can only access values under their own key or under global.
Helm hooks: Questions about hooks (pre-install, post-install, pre-upgrade, post-upgrade, pre-delete, post-delete) appear occasionally. A trap is placing a hook in a Deployment Pod template where it gets ignored — hooks must be defined in a separate YAML file (like a Job) with the helm.sh/hook annotation.
helm upgrade --install: This combination command is a favourite because it handles both fresh installs and upgrades with one command. A trap is thinking you need to run install before upgrade.
Key definitions to memorise:
helm create: Generates a scaffold chart directory with starter files.
helm lint: Validates chart syntax and structure.
helm template: Renders templates locally (useful for debugging).
helm install: Creates a new release.
helm upgrade: Upgrades an existing release.
helm rollback: Reverts to a previous revision.
helm list: Lists releases.
helm uninstall: Deletes a release.
helm dependency update: Downloads chart dependencies into the charts/ directory.
--set: Inline key-value assignment.
-f or --values: Path to a YAML values file.
--namespace: Target Kubernetes namespace.
Examiners also love to test the difference between a template and a static file. Any file in the templates/ directory is processed as a Go template. Any file outside templates/ (like values.yaml or Chart.yaml) is not processed. A trap is putting a file with placeholders outside templates/ and expecting it to be rendered.
Finally, you must know how to find a chart's default values quickly. The command helm show values <chart-name> prints the default values from the chart's values.yaml. This is useful when you need to know what keys are available for customisation.
A Helm chart is a packaged collection of YAML template files that defines a complete Kubernetes application, separating the structure (templates) from the configuration (values).
Helm creates releases — named, versioned records of each installation that enable upgrades, rollbacks, and deletions with a single command.
The values.yaml file holds default configuration values, which can be overridden at install or upgrade time using --set flags or custom values files.
Go template syntax (like {{ .Values.replicaCount }}) is used to insert dynamic values into resource definitions, with built-in objects for accessing chart metadata and release context.
Helm charts can depend on other charts, enabling reusable components (like a database) to be composed into a larger application.
The helm upgrade --install command handles both fresh installations and upgrades, making it the standard way to deploy in CI/CD pipelines.
Helm does not replace kubectl — you use kubectl for debugging and inspection, while Helm handles deployment lifecycle management.
Chart dependencies are defined in Chart.yaml and downloaded using helm dependency update, not automatically resolved.
Values precedence is: built-in defaults < values.yaml < parent chart values < user values files (< -f) < --set flags, with later sources overriding earlier ones.
Helm hooks allow you to run Jobs at specific points in the release lifecycle (pre-install, post-upgrade, etc.) for tasks like database migrations.
These come up on the exam all the time. Here's how to tell them apart.
Helm Chart
Packages multiple resource definitions into one reusable unit
Uses templates with placeholders for dynamic values
Includes metadata (version, dependencies) and supports lifecycle management
Kubernetes YAML file
A single static file defining one Kubernetes resource
All values are hard-coded and must be edited manually
No built-in versioning or release management; managed individually
helm install
Creates a named release with a history of revisions
Processes templates and merges values before applying
Supports rollback to any previous revision
kubectl apply
Applies resources without creating a release record
Applies the exact YAML you provide with no template processing
No built-in rollback — you must track versions manually
values.yaml (chart default)
Ships inside the chart as the default configuration
Used when no other values are provided
Overridden by any user-supplied values
Custom values file (-f flag)
Created by the user for a specific environment (dev, prod)
Overrides default values from values.yaml
Not stored inside the chart — provided at install/upgrade time
Helm hooks
Run at specific lifecycle points (pre-install, post-install)
Defined as separate Kubernetes resources (Jobs) with annotations
Can run before or after the main application is deployed
Init containers in a Pod
Run at Pod startup, before the main container starts
Defined within the Pod spec of a single resource
Only run at Pod initialisation, not tied to release lifecycle
Mistake
Helm charts store the actual running state of containers.
Correct
Helm charts only store templates and configuration values. The actual running state (which containers are running, their IP addresses, etc.) is managed by Kubernetes itself. Helm interacts with the Kubernetes API to create or update resources, but it does not monitor or store runtime state.
People confuse a package manager (which installs software) with a process manager (which monitors running processes). Helm is like an installer — it puts the files in place, but the operating system (Kubernetes) runs them.
Mistake
Once a chart is installed, you cannot change the values without uninstalling and reinstalling.
Correct
You can upgrade an existing release with new values using helm upgrade. The command updates only the resources that changed. You do not need to delete and recreate everything. Helm uses a three-way strategic merge patch to apply changes intelligently.
This misconception comes from manual workflows where people delete and recreate resources. Helm's release management system explicitly supports incremental upgrades, which is one of its main advantages.
Mistake
Helm charts work only with YAML. You cannot use JSON or other formats.
Correct
Helm templates are processed as Go templates, and the output can be any text format. While YAML is the standard for Kubernetes resources, you could theoretically generate JSON or even plain text. Helm also supports including arbitrary files via the .Files object.
Most documentation and examples show YAML, so learners assume it is the only option. The underlying technology (Go templates) is format-agnostic.
Mistake
Helm is a replacement for kubectl. You never need kubectl if you use Helm.
Correct
Helm is a complementary tool. It automates the deployment of multiple Kubernetes resources, but you still need kubectl for debugging, inspecting resources, port-forwarding, logs, and occasional manual operations. Helm does not replace kubectl's diagnostic capabilities.
Beginners see that Helm can install a whole app with one command and think it makes kubectl obsolete. In practice, professionals use both tools every day.
Mistake
Helm charts are only useful for large, complex applications. Simple apps do not need Helm.
Correct
Helm is useful even for a single Kubernetes resource. It provides versioning, easy rollback, and separation of configuration from structure. A one-resource app benefits from these features just as much as a multi-service app.
People think Helm is 'overkill' for small things because they underestimate how often configuration changes. A small app with a single Deployment that needs a different image tag per environment is a perfect use case for Helm.
Mistake
Helm commands modify your local filesystem. They only affect the cluster.
Correct
Some Helm commands do modify local files. For example, helm create creates a directory of files on your local machine. helm dependency update downloads chart archives into the charts/ subdirectory. helm package creates a .tgz archive on your local disk. Only helm install, upgrade, and delete modify the cluster.
Users focus on the cluster interaction and forget that Helm is a local CLI tool that manages local files as artefacts.
Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.
helm install creates a brand new release. helm upgrade modifies an existing release. You use helm install the first time, and helm upgrade for all subsequent changes. The combined command helm upgrade --install does both — it installs if the release does not exist, or upgrades if it does.
You can use multiple --set flags (like --set replicaCount=3 --set image.tag=v2), or create a YAML file with all your values and pass it with -f myvalues.yaml. You can also combine both: -f file sets base values, and --set overrides specific keys.
Yes, but you must ensure Helm manages those resources. You can adopt existing resources by creating a chart that generates the exact same YAML and running helm install. Helm will adopt the existing resources if they are identical. For critical production systems, it is safer to create a fresh install in a new namespace.
helm lint checks your chart for common errors: missing required fields in Chart.yaml, invalid YAML syntax, template rendering issues, and dependency problems. It does not test that the chart works against a cluster — it only validates the chart structure and syntax locally.
Helm does not encrypt values by default. For secrets, never store plaintext passwords in values.yaml. Use external secret management tools like SealedSecrets, Helm Secrets plugin, or Kubernetes External Secrets. In the CKAD exam, you will not be tested on encryption; you will only pass secret values as plain strings in --set flags or values files.
The charts/ folder holds subcharts — dependent charts that your parent chart relies on. When you run helm dependency update, Helm downloads the required chart archives (.tgz files) into this folder. At install time, Helm merges these subcharts into the parent release.
Yes, absolutely. Multiple charts can be installed in the same namespace, as long as resource names do not conflict. You can manage them separately with helm list, helm upgrade, and helm uninstall per release name.
You've finished Designing and Using Helm Charts for Application Packaging. Continue through the CKAD study guide to build a complete picture of the exam.
Done with this chapter?