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 lesson, I'm going to review Helm template syntax, at least the more common parts that are often used. A Helm chart, at its core, is composed of one or several templates.

Now, if you're interested in building your own charts, then, knowing the basics of how to author a template from scratch or converting a standard Kubernetes manifest into a template is a required skill. To help you understand the various basic template syntax features and related templating techniques, I'll use a sample project, which deploys a pair of Nginx-based web servers into a cluster. A ConfigMap is used to store the Nginx configuration. A cluster IP-based service is deployed to load balanced traffic across the two Nginx web servers.

Again, the focus of this lesson is on the Golang-based template syntax and the various related templating techniques. To help with the explanation of how the templating syntax works, I'll first show the desired output for each Kubernetes resource, then, followed by the template that when rendered, results in that output.

Okay, let's begin. For starters, let's look at the ConfigMap resource. The ConfigMap displayed here is used to store the Nginx web server configuration. This configuration is mounted into the Nginx web server at deployment time. And as you'll later see, is referenced within the deployment resource used to spin up the two Nginx web server pods.

Now, when it comes to converting this into a template, we'll refactor it, so that the Cloud Academy DevOps 2020 v1 message is extracted out and placed within the chart's values.yaml file. Additionally, both the hard-coded release name and release version values will be substituted out in favor of using Heml's built-in release object.

Let's now take a look at the resulting config template conversion in the next slide. Observing now, the updated ConfigMap template, we can see there are several templating syntax edits that have been made. Let's go through each of these now. The ConfigMap's resource name is now provided dynamically using the webserver.fullname template partial, which is stored externally in a helpers template.

Template directives begin and end with double curly braces. The template engine evaluates the template instructions inside the double curly braces. Everything else that falls outside of the double curly braces is rendered as is, without any transformation involved. The Cloud Academy DevOps 2020 v1 message has now been replaced with a template directive that references the message, which is now being stored and moved into the values.yaml file.

The .Values object used within the template directive refers to the values.yaml file. Therefore, the following dot notation in this case, .nginx.conf.message will inject the value stored at that location within the values.yaml file, into the current position within the template at rendering time. Note this value can also be supplied on the command line using the set argument, whenever the Helm install or Helm upgrade commands are invoked, and when done so, will override the default value stored in the values.yaml file.

The same template injection also happens for both the release name and release revision. However, these values are computed and supplied via the inbuilt release object, provided by Helm. It's also worth noting that Helm provides several other inbuilt objects, those being release, values, which you've just seen, chart, files, capabilities, and template. To understand what each inbuilt object is capable of, consult the online Helm documentation.

Let's now consider the deployment resource. Our deployment spins up a pair of Nginx web servers. The deployment references and mounts the previous ConfigMap, thereby providing Nginx with its runtime configuration. The deployment references a particular container image for the Nginx web server, that being the nginx.1.13.7 tagged image.

A checksum/config based annotation is used to help roll and replace the Nginx web server pods, whenever a Helm update is performed. The checksum is performed over the ConfigMap file with the idea being that if the ConfigMap changes between revisions, then, the deployment should understand this, and roll and replace the existing Nginx web server pods. So that the new Nginx web server pods are launched with the updated ConfigMap.

Okay, let's now see how this is configured into a corresponding template. The resulting deployment template is a bit more intricate when compared to the ConfigMap template, containing a number of different and new templating features.

Let's walk through each of these now. Again, various template directives are scattered throughout the template. It's important to remember to add a single whitespace after the opening double curly brace, in a single whitespace before the closing double curly brace. We can see in various places throughout the template the use of the include template keyword. The include keyword is used to reference a template partial, which has been refactored out and stored in a template partials file. In this case, the _helpers.tpl file.

This templating technique is equivalent to refactoring repeatedly used code into a function or method, which can then be called multiple times elsewhere. The single dot, which comes immediately after the named template partial, and just before the pipe symbol, represents the passed-in scope, in this case, the top level scope. The passed-in scope can be altered by navigating it using dot notation. Template double curly brace syntax can be modified with a dash special character to tell the template engine to chomp whitespace. The dash character can be used at either end, or both, depending on where you want to have whitespace removed.

Remember, that new lines are also considered whitespace. The pipe symbol takes the output of the left-hand side and passes it through the right-hand side template function. You will quite often see this used with the indent and nindent string functions, used to ensure the correct indentation is used in the template rendering. The nindent differs from the indent string function by prepending a starting newline character to the imported string.

The pipe symbol can be used multiple times within one template directive, allowing you to compose complex pipelines, if required. Template directives can make use of various control structures. For example, the if action has been used to check if auto scaling has been enabled or not, and then, render accordingly. The end template directive is used to close off the current control structure.

A checksum is computed on the ConfigMap, and the resulting checksum's stored as an annotation within the rendered deployment. This is done as previously mentioned, to allow the deployment to roll the pods if the checksum changes between revisions for the same release. For example, when we're performing a Helm upgrade, the implementation of this checksum uses the print function to compose a file system path to the ConfigMap. The include function then pulls in the content of the ConfigMap and pipes it into the sha256sum function, all of which results in a checksum value.

The dollar sign as used and seen within the checksum line is a global variable, which always points to the root context. The inbuilt template object hangs off the root context, as referenced here. The remaining template syntax within the deployment template is self-explanatory. Moving on to the final service resource, this is used to expose and load-balance internal cluster traffic across the two Nginx web server pods. There is nothing special about this resource, other than the fact that the service is configured as a cluster IP service, indicating that it's an internal load balancer to the cluster, and that the specified selector must match the labels set on the two Nginx web server pods within the previous deployment.

Let's now see how this translates into a template. Again, various template directives are scattered throughout the template. We've encountered all these types in the previous two templates, so nothing new here. One thing that I would point out is that the selector uses the same template directive as used within the deployment template, ignoring the required indentation. This emphasizes how refactoring out commonly used template areas, helps with increasing reusability, thereby, reducing template clutter. This approach also reduces unintentional errors, in this case, avoiding the potential for mismatching labels.

Now, with all three templates in place, we can both lint and test the template rendering without actually creating resources within our cluster. This is achieved by running the following commands, where webserver is the chart directory containing the templates. If you're happy with the rendering outputs, you can now perform the actual cluster installation by rerunning the previous command. Okay, that completes this lesson.

In this lesson, I reviewed many of the basic and common templating syntax features. I used a simple Nginx load-balanced deployment to provide template examples of the various templating features. Understanding how to author your own templates is an essential skill and requirement for building your own charts. Okay, close this lesson. I'll see you shortly in the next one.

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).