Introduction
This article is part of an ongoing series designed to help you prepare for the Certified Kubernetes Application Developer (CKAD) exam through small, focused labs.
In this article, we’ll cover the requirements within the “Application Deployment” domain:
Use the Helm package manager to deploy existing packages
We’ll explore what Helm is, how to install it, and how to use it to deploy applications in a Kubernetes cluster.
You can start from the beginning of the series here: CKAD Preparation — What is Kubernetes.
Prerequisites
A running Kubernetes cluster (like, Minikube, Docker Desktop, or use one of the KillerCoda Kubernetes Playgrounds) and basic familiarity with Pods and YAML manifests.
Getting the Resources
Clone the lab repository and navigate to this article’s folder:
git clone https://github.com/SupaaHiro/schwifty-lab.git
cd schwifty-lab/blog-posts/20260102-ckad
Hands-on Exercise: Let’s Use Helm to Deploy an Application
Before we dive into this hands-on exercise, it’s important to understand what Helm is and why it’s useful. In essence, Helm does for Kubernetes what apt, yum, or Homebrew do for operating systems: it simplifies the installation, upgrading, and management of complex applications.
When we deploy an application on Kubernetes, we often need to create and manage many different resources (Pods, Services, ConfigMaps, Secrets, etc.). Kubernetes knows how to handle these resources, but it doesn’t have visibility into how they work together to form a complete application. This is where Helm comes in. Helm uses “charts,” which are pre-configured packages of Kubernetes resources. These charts can be easily installed, upgraded, or removed with simple Helm commands, significantly simplifying application management on Kubernetes.
There are several public Helm chart repositories, such as Artifact Hub, which hosts thousands of charts for various applications.
Let’s start by installing Helm, following the official instructions in the official documentation.
On a Debian/Ubuntu-based system, you can install Helm with the following commands:
$ curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-4
$ chmod 700 get_helm.sh
$ ./get_helm.sh
Verify that Helm was installed correctly by checking the version:
helm version
You should see output similar to this:
version.BuildInfo{Version:"v4.0.4", GitCommit:"8650e1dad9e6ae38b41f60b712af9218a0d8cc11", GitTreeState:"clean", GoVersion:"go1.25.5", KubeClientVersion:"v1.34"}
To understand how Helm works, we’ll create a simple Helm chart to deploy a small Nginx-based web application. A quick way to create a sample chart is to use the helm create command, which generates a basic directory structure for a Helm chart.
helm create my-nginx-app
This command should create a directory called my-nginx-app with the following structure:
my-nginx-app/
Chart.yaml
values.yaml
templates/
deployment.yaml
service.yaml
_helpers.tpl
.. other files ..
Since the generated example might be more complex than necessary for this exercise, let’s simplify the chart by removing unnecessary files and modifying the manifests to fit our simple Nginx application.
You can directly use the example in the charts/my-nginx-app folder as a reference for the modified files, or follow the instructions below to make the necessary changes.
If you’ve chosen to modify the files manually, proceed as follows:
-
Remove all files in the
templates/directory, keeping onlydeployment.yaml,service.yaml,_helpers.tpl, andNOTES.txt. -
Replace the content of
templates/deployment.yamlwith the following:
apiVersion: apps/v1
kind: Deployment
metadata:
name: { { include "my-nginx-app.fullname" . } }
spec:
replicas: { { .Values.replicaCount } }
selector:
matchLabels:
app: { { include "my-nginx-app.name" . } }
template:
metadata:
labels:
app: { { include "my-nginx-app.name" . } }
spec:
containers:
- name: nginx
image: ":"
imagePullPolicy: { { .Values.image.pullPolicy } }
ports:
- containerPort: 80
resources:
limits:
memory: 256Mi
cpu: 200m
requests:
memory: 64Mi
cpu: 50m
Note: The files in the
templates/folder are not just static YAML manifests. Helm uses Go Templating, a templating system that allows you to insert dynamic expressions within the YAML files.
- Replace the content of
templates/service.yamlwith the following:
apiVersion: v1
kind: Service
metadata:
name: { { include "my-nginx-app.fullname" . } }
spec:
type: ClusterIP
selector:
app: { { include "my-nginx-app.name" . } }
ports:
- port: 80
targetPort: 80
- Replace the content of
NOTES.txtwith the following:
Nginx has been successfully installed 🎉
Release:
Namespace:
Replica Count:
Image: :
To check the status of the pods:
kubectl get pods -l app= -n
To view the logs of the first pod:
kubectl logs -l app= -n --tail=100
To remove the release:
helm uninstall -n
------------------------------------------------------------
Accessing nginx
If you are running inside the cluster:
curl http://..svc.cluster.local
If the Service type is ClusterIP (default), you can use port-forward:
kubectl port-forward svc/ -n 8080:80
curl http://localhost:8080
If the Service type is NodePort:
kubectl get svc -n
# Then access using:
http://<NodeIP>:<NodePort>
If the Service is exposed via Ingress:
kubectl get ingress -n
# Then access using the configured host name.
- Finally, replace the content of
values.yamlwith the following:
replicaCount: 1
image:
repository: nginx
tag: "1.27"
pullPolicy: IfNotPresent
Let’s finish by running a check to verify everything is in order:
helm lint my-nginx-app
You should see a message indicating that the chart is valid:
==> Linting my-nginx-app
[INFO] Chart.yaml: icon is recommended
1 chart(s) linted, 0 chart(s) failed
For third-party charts, it can be useful to examine the default configuration values and chart documentation before proceeding with installation.
You can do this using the helm show values, helm show readme, and helm show crds commands:
helm show values my-nginx-app
helm show readme my-nginx-app
helm show crds my-nginx-app
Obviously, our chart is very simple and doesn’t include CRDs, but in real-world scenarios these commands are very useful for understanding how to properly configure a chart before installation.
Before installing the chart, we can also generate the Kubernetes manifests that Helm will create for us using the helm template command. This allows us to see exactly which resources will be created in the cluster:
helm template my-nginx-app > ../manifests/nginx-manifests.yaml
If you want to modify any parameters, you can do so directly in the values.yaml file or pass custom values via the command line using the --set option.
helm template my-nginx-app --set replicaCount=2 > ../manifests/nginx-manifests.yaml
Now we’re ready to install our Helm chart in the Kubernetes cluster. Let’s use the helm install command to deploy the application:
helm install my-nginx-release my-nginx-app -n nginx --create-namespace
The above command will install the my-nginx-app chart with the release name my-nginx-release in the nginx namespace, creating the namespace if it doesn’t already exist.
You can verify that the deployment and service were created successfully with the following command:
k get deploy,svc,po -n nginx
With the helm list or helm ls command, you can see all Helm releases installed in the cluster:
helm list -n nginx
With the helm status command, you can get detailed information about the release status:
helm status my-nginx-release -n nginx
The helm upgrade command allows you to update an existing release with new configurations or chart versions. For example, to upgrade the Nginx container image to version 1.29:
helm upgrade my-nginx-release my-nginx-app --set image.tag="1.29" -n nginx
Helm maintains a version history for each release:
helm history my-nginx-release -n nginx
Here’s an example output:
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
1 Tue Dec 30 18:32:22 2025 superseded my-nginx-app-0.1.0 1.16.0 Install complete
2 Tue Dec 30 18:36:43 2025 deployed my-nginx-app-0.1.0 1.16.0 Upgrade complete
This history is stored in secrets managed by Helm within the namespace where the release was installed:
k get secrets -n nginx
The helm rollback command allows you to revert to a previous version of the release if something goes wrong during an upgrade. For example, to roll back to revision 1:
helm rollback my-nginx-release 1 -n nginx
Keep in mind that the rollback itself generates a new release, so the history will show all versions, including rollbacks:
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
1 Tue Dec 30 18:32:22 2025 superseded my-nginx-app-0.1.0 1.16.0 Install complete
2 Tue Dec 30 18:36:43 2025 superseded my-nginx-app-0.1.0 1.16.0 Upgrade complete
3 Tue Dec 30 18:41:15 2025 deployed my-nginx-app-0.1.0 1.16.0 Rollback to 1
Finally, when you no longer need the application, you can remove it with the helm uninstall command:
helm uninstall my-nginx-release -n nginx
To complete our overview of Helm, let’s see how to add an external Helm chart repository. For example, we can search for a WordPress application on Artifact Hub and add the official repository from Bitnami, which hosts a chart for WordPress.
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
Now we can search for the WordPress chart in the Bitnami repository:
helm search repo bitnami/wordpress --versions
The --versions option shows all available versions of the chart.
We can install WordPress using the Bitnami chart with the following command:
helm install my-wordpress bitnami/wordpress -n wordpress --create-namespace --version 28.0.4 --set wordpressUsername=admin,wordpressPassword=pass123
With this command, Helm will download the WordPress chart from the Bitnami repository and install it in the wordpress namespace, creating the namespace if it doesn’t already exist. We’ve also specified some custom configurations, such as the WordPress username and password.
If we want to upgrade the WordPress version in the future, we can use the helm upgrade command:
helm upgrade my-wordpress bitnami/wordpress -n wordpress --version 28.1.0
If we look at the release history for WordPress, we’ll see the different versions that have been installed:
helm history my-wordpress -n wordpress
Here’s an example output:
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
1 Wed Dec 31 09:56:53 2025 superseded wordpress-28.0.4 6.9.0 Install complete
2 Wed Dec 31 09:59:28 2025 deployed wordpress-28.1.0 6.9.0 Upgrade complete
Recap: What We’ve Covered
In this exercise, we explored Helm, the Kubernetes package manager, and how it can significantly simplify application management.
We learned how to:
- Install Helm on our system following the official documentation.
- Create a basic Helm chart using the
helm createcommand. - Customize Kubernetes templates within a chart to fit our needs.
- Validate a chart with
helm lintto ensure it’s properly configured. - View configuration values, documentation, and CRDs of a chart with
helm showcommands. - Generate Kubernetes manifests without installing them using
helm template. - Install a chart in the cluster with
helm installand verify its status. - Manage releases with
helm list,helm upgrade,helm rollback, andhelm history. - Completely remove an application with
helm uninstall. - Add external chart repositories and install applications from them.
Helm is a fundamental tool in the Kubernetes ecosystem and represents an essential skill for the CKAD exam. The ability to use existing Helm charts, understand them, and customize them will allow you to deploy complex applications quickly and efficiently, while maintaining reproducibility and manageability over time.
In daily practice, Helm will save you valuable time and reduce configuration errors, allowing you to focus on the most important aspects of your application development.
Final Cleanup
To wrap up, let’s remove the namespaces created for this exercise:
k delete ns nginx