DEMO: Creating a Custom Helm Chart (Load Balanced 2x Nginx Web Server Setup)
Start course
1h 15m

Helm is a package manager for Kubernetes, used to simplify and enhance the deployment experience for deploying resources into a Kubernetes cluster. 

This training course explores Helm 3, which is the latest version of Helm building upon the successes of Helm 2. During this course, you'll learn the fundamentals of working with Helm3, its features, and the key differences between Helm 3 and Helm 2.

Several hands-on demonstrations are provided within this course, which will allow you to observe how to install and set up Helm, and also how to use Helm to perform various Chart cluster management related tasks. You'll also see how to create and host your very own Helm Chart. All of the coding assets which are used and demonstrated can be found within the CloudAcademy GitHub repositories for this course — they can be found in the links under the Resources section below. You’re encouraged to clone these repositories and perform the same helm commands against your own Kubernetes cluster.

If you have any feedback about this course, please contact us at

Learning Objectives

By completing this course, you will learn:

  • What Helm is and how to install it
  • Helm charts, templates, releases, revisions, and repositories
  • How to deploy, upgrade and rollback Helm charts
  • How to create and host your own Helm charts

Intended Audience

The intended audience for this course includes:

  • Anyone interested in learning about Helm and its fundamentals
  • Software Engineers interested in learning how to configure and deploy Helm charts into a Kubernetes cluster
  • DevOps and SRE practitioners interested in understanding how to install, manage and maintain Helm-deployed infrastructure


To get the most out of this course, you should have:

  • A basic understanding of Kubernetes
  • Experience with deploying Kubernetes resources such as pods, deployments, services, etc.
  • A basic understanding of software development and the software development lifecycle

If you’re completely new to Kubernetes, please consider taking our dedicated Introduction to Kubernetes learning path.



Welcome back. In this demonstration, I'm going to quickly show you how to create your own Helm chart. In this example, I'm simply going to create an Nginx web server deployment consisting of two replicas that sit behind a service which will provide load balancing. I'll also establish a ConfigMap to store the Nginx configuration which will be injected into the Nginx web server pods when they get launched. Okay, let's begin.

For starters, I'll run the command rm -fr * to clear out the current demo-helm directory, just to keep things nice and tidy. Next, I'll run the command helm create cloudacademy-webapp to generate a basic chart directory structure for us. This takes care of all of the tedious chart folder and file structure setup.

If I now run the tree command, we can observe the generated sample chart directory structure. Again to keep things simple, I'll drop all of the files within the templates directory by running the following command rm -rf cloudacademy-webapp/templates/*. Running the tree command again, we can see that the templates directory is now empty.

Next, I'll navigate into the cloudacademy-webapp directory, and then launch Visual Studio Code from within it by running the command. Now to follow along, consider git cloning the sample code located within the Cloud Academy GitHub Helm repository.

Next within the templates directory, I'll create a new configmap.yaml template and then populate it with the following ConfigMap resource template configuration. This ConfigMap represents the Nginx configuration that will be mounted into the Nginx web server containers when they are launched within the cluster. On line four, the webserver.fullname template partial is referenced, this will be used to generate the name for this resource. This template partial, along with a few others, will be set up later on.

On lines 13, 18, and 23, we have other template directives, those within the double curly brackets. During template rendering, line 13 injects a simple string message that we'll store within the chart's values.yaml file. Let's set this up now. Clicking on the values.yaml file, I'll simply overwrite the default content with the following content.

Notice at the bottom, we have the Nginx conf message value set to Cloud Academy DevOps 2020 V one, this is the string that gets injected into the ConfigMap template at template rendering time. Before I move on, also note that on lines 18 and 23, Helm's in-built release object is referenced for both the name and revision values of the current chart release, determined and computed at install time.

Next, I'll create the deployment.yaml template and populate it with the following template code. Without going into too much detail, the deployment.yaml template simply spins up two Nginx web server pods, mounting each of them with the ConfigMap previously created. This supplies them with their Nginx configuration, used and required by the Nginx web service. The ConfigMap configuration is set up as a volume on lines 33 to 36, and then mounted within the Nginx container on line 27. The only other interesting piece of configuration is the use of the checksum config annotation on line 17. This is used to calculate a checksum over the ConfigMap file. If the deployment detects a change, as indicated by differing checksums, then the deployment will know to bounce and replace any existing Nginx pods with newer versions of themselves, which as they launch, will then pull in the newer and updated ConfigMap.

Okay, the final template we need to create is the service.yaml template. This will be used to expose and load balance cluster traffic across the two Nginx web server pods. I'll populate this template with the following template code. The only real point of interest with this template, is the fact that this service will be configured as a ClusterIP based service, as per the setting established on line eight, which references the service.type value stored in the values.yaml file, as seen here.

Finally, I'll add back in a _helpers.tpl file which contains several reusable template partials which are referenced and used within the other templates. Template partials are similar to functions or methods as found within other languages. They are reusable template blocks that can be called upon from other templates.

Okay, now that we have our chart templates configured and saved, lets now validate it for syntax correctness, et cetera. Here, I'll run the command helm lint over the current chart directory. Perfect, linting has succeeded, reporting no errors, and with one recommendation provided. We'll ignore this recommendation for now as it will not affect deployment.

Next, let's invoke the template rendering process over our templates to see what the rendered templates look like. Within the generated output, we can now see each of the manifests which are actually used to create the respective Kubernetes resources at deployment time. Note that each resource has a source comment at the top indicating which template file was responsible for its generation.

Okay, moving on. Let's now package our chart. To do so, I'll step back out of the current cloud academy dash web app directory. And then run the command helm package cloudacademy-webapp. As we can see, the chart packaging has now completed successfully. If I list out the contents of the current directory, you can see the chart archive file. In this case, it's named cloud academy dash web app dash 0.1.0.tgz. Finally, let's try installing it.

To do so, I'll first ensure that the cluster namespace that I'm operating in is the cloud academy namespace. Therefore, I'll run the following kubectl command. Okay, I'm now ready to perform the chart install. I'll do so by running the following command, which installs the chart into the current namespace, giving it the release name CA dash demo one. Perfect, our custom Helm chart has been installed successfully.

Let's take a look at the resources that were launched within the cluster and within the cloud academy namespace. I'll run the command kubectl get all. Here, we can see the cluster resources created by our Helm chart installation. Let's now perform a quick test by firing an HTTP GET request to the services internal cluster IP. To do so, I'll run the following command which will spin up a temporary pod and use the wget command within it to handcraft an HTTP GET request.

Okay, we have a successful result. As observed by the returned Cloud Academy DevOps 2020 V one message. This is a great result showing that the end-to-end Helm chart development, packaging, and installation has worked. Now, let's do one final thing here. Let's perform a Helm upgrade on our CA dash demo one chart release. When I do so, I'll explicitly set the nginx.conf.message to have a different message, this time setting it to be "Helm rocks!!"

Okay, that has worked. As we can see, a new revision, revision two has been created for the CA dash demo one chart release. Sending a new HTTP GET request to the same service, I should now get back the updated message in its response. And indeed I do. What this implies is that the Helm upgrade resulted in two Nginx pods being bounced, i.e. terminated and replaced with newer pods. We can confirm this by looking at first the pods view within the cloud academy namespace. And then also checking the rollout history for the deployment.

We can also use the helm history command together with the chart's release name to view the release history. Okay, that concludes this demonstration in which I showed you how to create, package, and deploy, and upgrade a custom Helm chart. Knowing how to perform these basic chart building tasks will help you to start creating your own Helm charts.

About the Author
Learning Paths

Jeremy is a Content Lead Architect and DevOps SME here at Cloud Academy where he specializes in developing DevOps technical training documentation.

He has a strong background in software engineering, and has been coding with various languages, frameworks, and systems for the past 25+ years. In recent times, Jeremy has been focused on DevOps, Cloud (AWS, Azure, GCP), Security, Kubernetes, and Machine Learning.

Jeremy holds professional certifications for AWS, Azure, GCP, Terraform, Kubernetes (CKA, CKAD, CKS).