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 take you through the process of creating your own chart, hosting it, and then installing it. Along the way I'll document the internals and structure of a Helm chart, and highlight how a helm chart is really just a collection of templates plus a couple of extra metadata and default config value files which collectively represent an application to be deployed.

Charts can and do range in terms of complexity. Some charts are simply designed to deploy nothing more than a single application or service, whereas others can be much more complex, designed to deploy a full application stack consisting of multiple microservices, web servers, databases, and so on. Ultimately, deploying a chart will result in one or several Kubernetes resources such as pods, deployments, services etcetera being created.

Now, when it comes to building your own chart, you need to understand the required folder and file structure. The helm command line client helpfully provides the "helm create" command which when invoked scaffolds out this directory structure for you. Let's take a closer look at that now. A chart, as mentioned earlier is nothing more than a specific directory structure containing a set of specific files.

Consider the following default chart directory structure, which gets generated for you when you invoke the "helm create" command. In the parent directory you have the Chart.yaml and values.yaml files, together with the charts and templates directories. Let's now begin to review each of these individually. The Chart.yaml file contains top-level metadata which really explains the purpose of the chart. Every chart must have a name which is expressed in the mandatory name field. The optionally required description field indicates the purpose of the chart. The optionally required type field can be set to either 'application' or 'library'.

When set to application, the chart becomes deployable meaning resources will be created within the cluster. A 'library' typed chart indicates that the chart contains reusable functions that can be imported and used with application typed charts. The mandatory version field indicates the version of the Chart itself and follows the semantic versioning scheme. The optionally required appVersion on the other hand tracks the version of the application being deployed, and also uses the semantic versioning scheme.

There are several other optional fields that can be specified for various other purposes. Consult the online home documentation to understand their purposes.

The charts folder is used to host other dependent charts for which the current chart depends on. During deployment, charts contained within the charts directory are deployed into the cluster. The values.yaml file contains a structured list of default values, which at template rendering time get injected into the various chart templates which reference them.

Values are declared in yaml format allowing you to specify them in an organized structure. What goes into this file and how it is organized is entirely up to the chart designer. The following values.yaml file specifies a number of default values that will be referenced upon by other templates within the same chart. Templates that wish to reference a default value declared within the values.yaml file can do so by referencing the term ".Values" with a capital V, followed by a dotted notation path to the required value. For example, the service.yaml template is defined like so. Here you can see that the service type references the value stored in the values file at the position of service.type.

It's important to keep in mind that the values stored in the values.yaml file are defaults. All of these values can be overridden when invoking the "helm install" or "helm upgrade" commands, by specifying the --set argument. For example, you could update an existing release with the following command, which would override the default service port value specified in the values.yaml file, instead replacing it with the value 9090. The templates folder is used to store all template files together.

Typically, a chart is composed of multiple template files, where each template file contains the definition of a single cluster resource. For example, the deployment.yaml template will contain the definition for a deployment resource, whereas the service.yaml template will contain the definition for creating a service resource. Template files are developed according to the Golang template file syntax.

All files that are placed in the templates folder, regardless of filename and extension are subject to the template rendering process. Picking out the service.yaml template as an example we can see the basic templating format and structure. The template syntax again is based on Go templates. Double curly brackets are used to delimit the areas that are evaluated and replaced at template rendering time. A NOTES.txt file can be placed alongside the templates in the templates folder. This file contains end-user instructions as to how the deployed application should be accessed etcetera, once deployed and running within the cluster. The instructions are printed out at the end of invoking the "helm install" or "helm upgrade" commands.

Keep in mind, that the NOTES.text file, as is every other file in the templates directory, still a template file and therefore undergoes the template rendering process. This, allows you to dynamically generate portions of the instructions that are eventually printed out to the console. When you're building out your own templates, you'll often come across template partials that are repeated either within the same template and/or across different templates.

These template partials can be refactored out and placed within a file whose name begins with an underscore to indicate that this file does not directly result in a Kubernetes manifest file during the rendering process. For example, the underscore helpers.tpl file which gets generated by the "helm create" command contains a number of reusable template partials that are included within the other template files. The following template snippet extracted from the underscore helpers.tpl file is used to dynamically generate the service account name.

Looking at the serviceaccount.yaml template we can see how the previous template partial is then included. The tests folder is used to host one or several tests that you write to exercise and validate the chart once deployed. Tests are implemented typically using a Kubernetes Job or Pod resource. The resource once created within the cluster should be designed to return a zero exit code. This is interpreted by Helm as a successful test with a non-zero exit code representing a test failure.

It's important to understand that tests within Helm are determined by the Job or Pod resource being annotated with the hook annotation and it being set to the value test. Tests can be placed anywhere within the templates folder but for convenience are often grouped together and placed in the tests sub-folder. Tests are launched by running the command "helm test" with the name of a release which is to be tested.

The following example uses a Pod resource to launch a wget command to send an HTTP GET request to the service name. If the service in question replies with an HTTP 200 response code then the Helm test as a whole will succeed. Helm tests can be designed to test many different things. For example, they can be designed to test traffic paths, network connections, credentials and/or other application specific tasks.

Having finished the development of your chart the next thing to do is package it. The packaging process is simple and straightforward. Simply, run the "helm package" command. This command simply takes in the path to the chart directory and then archives the chart directory producing a file named according to the chart metadata stored within the Chart.yaml file located in the parent chart directory. For example, if a Chart.yaml contained the following metadata, and the Chart.yaml file was located in a directory named "ca-app", then executing the command "helm package ca-app" would produce a new archive file named cloudacademyapp-0.1.3.tgz. Anyone with access to the previously created Helm chart archive file, could simply install it by running the following command.

Now, if there were settable values, they could also be passed in by using the set parameter. These install time provided values would override any equivalent values stored in the chart's values.yaml file. If needed you can perform a dry-run of a chart installation. This will perform a template render over the enclosed chart templates, outputting actual Kubernetes manifests so that you can view exactly what will be installed in the cluster.

To host the newly created chart within a chart repository, you would simply need to create an index chart file, using the following command. And then store both the generated index.yaml file together with the chart archive in a directory that was then served up via a standard web server. The "helm repo index" command will actually perform a recursive directory scan within the provided directory to search for and find all Chart archive files. Any discovered chart archive file will then be written into the resulting index.yaml file which is used at repository search time.

If your chart is hosted and being served, then you could run the following commands to install the chart. If again there are settable values, they can be passed in by using the set parameter, overriding any equivalent values stored in the chart's values.yaml file. Okay, that completes this lesson. In this lesson, I reviewed the process involved in building your own custom Helm Charts. I reviewed the internal chart directory structure and highlighted what each directory and file was responsible for.

Finally, I documented how to package, host, and install a custom chart. Understanding how to create package, and host your own charts will not only aid you with rolling out your own applications into a Kubernetes cluster but will also allow you to share them within your own organization or the wider online community. Okay, close this lesson, and 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).