Helm is a package manager for Kubernetes workloads. Creating a Helm chart for your application simplifies reproducible deployments into a Kubernetes cluster. Users can install the whole chart with one command, instead of manually applying individual component manifests with Kubectl.
In this article, we’ll show you how to get started with Helm by writing a chart for a simple application. A “chart” is conceptually similar to a “package” of Kubernetes manifests which Helm lets you manage as a single entity.
What’s a Helm Chart?
Helm charts apply the familiar model of package management encountered in operating systems and programming languages to applications running in a Kubernetes cluster. A Helm chart can have dependencies and children; all these components are automatically started in your cluster when you install a top-level chart.
Charts are fully versioned using a semantic release strategy. Similarly to an npm module or OS package, you can pin charts to specific versions and track their changes over time. This simplifies rolling back application deployments to a known good release should you run into issues in your cluster.
Helm charts also incorporate templating capabilities for supplying dynamic values at installation time. You can configure new applications without directly editing their manifest files, using variables that are provided by the chart developer.
Installing Helm
Helm’s distributed as a plain binary via the project’s GitHub Releases page. Download the correct distribution for your system, make it executable, and move it into a location within your PATH
.
Helm’s also present in the package repositories of most popular Linux distributions. You can find it in Homebrew for macOS and Chocolatey and Scoop for Windows too.
Once installation’s complete, run helm version
to check everything’s working:
$ helm version --template="Version: {{.Version}}" Version: v3.8.1
Helm commands target your active Kubernetes cluster connection as used by Kubectl. Your selected Kubeconfig file and context will be used for all Helm commands. You can reference a different config file with the standard KUBECONFIG
environment variable or --kubeconfig
flag mechanisms.
Creating a Helm Chart
Now you can begin creating a Helm chart for your application. Use the helm create
command to scaffold a new chart in your working directory:
$ helm create my-app-chart
The chart’s content will be deposited inside the my-app-chart
directory. Let’s inspect what it contains:
$ ls my-app-chart Chart.yaml charts templates values.yaml
There are two top-level files and two supplementary sub-directories. Here’s what each resource is used for:
Chart.yaml
– Your Helm chart’s manifest defining metadata properties including its name and version.values.yaml
– This file stores default values for variables that you can reference in your chart. It’s possible to override values that are set here using CLI flags when you install the chart.templates
– The templates directory contains your chart’s Kubernetes object manifests. Installing the chart will apply all these manifests to your cluster. Any valid Kubernetes YAML manifest can be placed here; you can also use extra functionality, such as references to variables defined in yourvalues.yaml
file. We’ll look at this capability below.charts
– Thecharts
directory holds other Helm charts which this one depends on. It’s used to configure complex parent-child chart relationships. We won’t be covering this feature in this article so you can delete the directory if you don’t need it.
Helm’s default chart comes pre-configured to deploy an instance of the NGINX web server. The Kubernetes manifests in the templates
directory create the various constituent components, such as a Deployment, Service, and Ingress. The application is configured by variables defined in values.yaml
; here you’ll find settings for the image tag, service port, and Ingress host, among others:
$ cat values.yaml # Default values for my-app-chart. # This is a YAML-formatted file. # Declare variables to be passed into your templates. replicaCount: 1 image: repository: nginx pullPolicy: IfNotPresent # Overrides the image tag whose default is the chart appVersion. tag: "" ...
Installing the Chart
To add the application to your cluster, use the helm install
command:
$ helm install my-app . NAME: foo LAST DEPLOYED: Tue Mar 29 14:47:48 2022 NAMESPACE: default STATUS: deployed REVISION: 1 NOTES: ...
The first argument to the command defines the name of your release. The second argument references the directory path to load the Helm chart from. You can use .
when your working directory is already set to the root of your chart.
You’ll receive some terminal output that describes the installed release. The NOTES
section consists of information provided by the chart.
To override values.yaml
variables, provide one or more instances of the --set
flag:
$ helm install my-app . --set replicaCount=3 --set image.tag=1.20
This example would deploy three replicas of a container running the nginx:1.20
image. You can check this by listing the Pods in your cluster using Kubectl:
$ kubectl get pods NAME READY STATUS RESTARTS AGE my-app-my-app-chart-6d6577749c-2qbhb 1/1 Running 0 61s my-app-my-app-chart-6d6577749c-wdmgv 1/1 Running 0 44s my-app-my-app-chart-6d6577749c-x5wp7 1/1 Running 0 40s
Upgrading, Retrieving, and Deleting Chart Releases
Next make some changes to the chart or alter a variable’s value:
$ helm install my-app . --set replicaCount=5 Error: INSTALLATION FAILED: cannot re-use a name that is still in use
Repeating the install
command doesn’t work. To apply changes to a chart that’s already deployed, use the upgrade
command instead. This creates a new “release” inside the cluster.
$ helm upgrade my-app . --set replicaCount=5 Release "my-app" has been upgraded. Happy Helming!
You can list all the deployed chart releases in your cluster with helm list
:
$ helm list NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION my-app default 2 2022-03-30 15:09:34.370758719 +0100 BST deployed my-app-chart-0.1.0 1.16.0
Each release’s details includes its name, the number of times it’s been deployed, its last update time, and the version numbers of the chart and the application it provides.
To remove a release and destroy its Kubernetes objects, pass its name to the uninstall
command:
$ helm uninstall my-app release "my-app" uninstalled
Writing Your Own Chart From Scratch
Now let’s see how to write a basic chart from scratch. Create a new directory for your chart; we’re calling ours cloudsavvy-chart
. Add a Chart.yaml
file inside with the following content:
apiVersion: v2 name: cloudsavvy-chart description: An example Helm chart. type: application version: 0.1.0 appVersion: 1.1.0
The type
field should usually be set to application
. The other supported type is library
. Library charts package functionality that can be included as a dependency of other charts. They don’t contain any Kubernetes templates
themselves.
The version
field refers to the version of your chart. You should increment this each time you modify the chart’s templates. appVersion
indicates the version of the primary software component your chart provides. It signals to chart users what will be running in their cluster after they install the chart. As an example, if you’re creating a chart that distributes WordPress, it would be appropriate to set appVersion
to the WordPress version number you’re providing.
Next create a values.yaml
file with a few simple variables:
deploymentName: cloudsavvy image: nginx:latest replicas: 1
These variables will be referenced in your chart template. Add this template now as templates/deployment.yaml
. Our basic chart will deploy a single Pod so it’ll only have one template file. In a real-world situation, it’s good practice to create individual manifest files for each of your application’s components.
apiVersion: apps/v1 kind: Deployment metadata: name: {{ .Values.deploymentName }}-deployment spec: selector: matchLabels: app: {{ .Values.deploymentName }} replicas: {{ .Values.replicas }} template: metadata: labels: app: {{ .Values.deploymentName }} spec: containers: - name: {{ .Values.deploymentName }} image: {{ .Values.image }}
The Deployment uses values from values.yaml
to configure the image reference and replica count. The deploymentName
variable is used throughout so that any future changes can be made in one place. Fields in values.yaml
are referenced using the {{ .Values.FIELD_NAME }}
syntax.
Now use Helm to install the chart:
$ helm install cloudsavvy-app . --set replicas=3 NAME: cloudsavvy-app LAST DEPLOYED: Tue Mar 29 15:43:21 2022 NAMESPACE: default STATUS: deployed REVISION: 1 TEST SUITE: None
The --set
flag overrides the default value of replicas
that’s set in values.yaml
. After the overrides have been applied, Helm injects the resolved values into the correct places in your YAML templates. The final Kubernetes manifests are then applied to your cluster. You can now verify that three containers are running by using Kubectl to list your cluster’s Pods.
$ kubectl get pods NAME READY STATUS RESTARTS AGE cloudsavvy-deployment-7b975bd985-5r7dc 0/1 ContainerCreating 0 15s cloudsavvy-deployment-7b975bd985-bpbkm 0/1 ContainerCreating 0 15s cloudsavvy-deployment-7b975bd985-jzb5q 0/1 ContainerCreating 0 15s
Summary
Helm charts let you package collections of Kubernetes manifests as complete applications that are ready to deploy. You can create templated configurations that end users can easily change before installing a release into a cluster.
In this guide, we’ve explained the basics of Helm’s functionality and shown how you can create your own simple charts for your applications. We’ve barely covered the surface of what Helm can achieve though – once you’ve written a chart, you can push it to a repository for others to use, add other charts as dependencies, and build more advanced charts using functions, pipelines, and control flow expressions. Taking the time to learn Helm makes your Kubernetes deployments more flexible, powerful, and reusable.