Introduction to Helm

Archie To

This article assumes readers have a basic knowledge about Kubernetes, as Helm and Kubernetes are closely related. Reading Introduction to Kubernetes is highly recommended prior to reading this article.

What is Helm?

Helm is a package manager for Kubernetes. Think of Helm as a way to install and upgrade applications built on Kubernetes. Helm allows you to install applications with multiple Kubernetes components with a single command.

Why Helm?

To explain the benefits that Helm brings about, suppose you are deploying an app onto k8s (an abbreviation for Kubernetes). The app consists of a Deployment to run the containers, a Service for networking, a Configmap for basic configurations, a Secret to store passwords, a Persistent Volume and a Claim to store files and some IngressRoutes for advanced routing.

Without Helm, you might have a resource description file for each of these, such as deployment.yaml, service.yaml, etc., each of which define parameters specific to this particular deployment of the application.

With Helm, these are generalized as templates where the parameters are placeholders and can be filled out independently in a definition for the entire application.

We’ll see how this looks later; for now let’s look at what this means for managing our deployment.

Package k8s app components

Without Helm, in order to deploy these resources, you will have to run kubectl apply -f <resource_file_name>.yaml for each resource.

With Helm, a single command will do the trick. This becomes even less work for applications that require a large number of resources.

Reusability

Suppose you want to deploy a second app with similar resources but with a different name.

Without Helm, you would have to modify each resource yaml file and apply each file individually.

With Helm, a single change in values.yaml with a single helm install command will provide the exact same result.

Versioning

You successfully deployed your app. You then upgraded some resources and now the app doesn’t work anymore. You want to revert the app back to its previous version.

Without Helm, you would have to recall the changes you’ve made to each deployment, remove them and reapply the yaml files.

With Helm, a single helm rollback command would suffice.

Main components of Helm

Suppose we are deploying a very simple web application with 2 main components: A Deployment and a Service resource. A typical Helm chart would contain the following:

Chart.yaml

A file that contains metadata about the chart:

apiVersion: v2
name: my-web-app
description: A Helm chart for deploying a simple web application
version: 1.0.0
appVersion: 1.0.0

values.yaml

This file contains default values for the chart’s configuration. These values will be plugged into the corresponding variable names defined in Helm templates. For our web application, it might include settings like the number of replicas and the image to use:

replicaCount: 2

image:
  repository: my-web-app
  tag: "1.0.0"
  pullPolicy: IfNotPresent

service:
  type: ClusterIP
  port: 80

resources:
  limits:
    cpu: 100m
    memory: 128Mi
  requests:
    cpu: 100m
    memory: 128Mi

templates

This directory contains all Kubernetes manifest templates needed for our application (This is why we said Helm package k8s app components). Each template can use variable names to plug in the values provided in values.yaml. Here’s an example of a deployment template (deployment.yaml):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-{{ .Chart.Name }}
  labels:
    app: {{ .Chart.Name }}
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ .Chart.Name }}
  template:
    metadata:
      labels:
        app: {{ .Chart.Name }}
    spec:
      containers:
        - name: {{ .Chart.Name }}
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        ports:
          - containerPort: 80
        resources:
          limits:
            cpu: {{ .Values.resources.limits.cpu }}
            memory: {{ .Values.resources.limits.memory }}
          requests:
            cpu: {{ .Values.resources.requests.cpu }}
            memory: {{ .Values.resources.requests.memory }}

And an example of a service template (service.yaml):

apiVersion: v1
kind: Service
metadata:
  name: {{ .Release.Name }}-{{ .Chart.Name }}
spec:
  type: {{ .Values.service.type }}
  ports:
    - port: {{ .Values.service.port }}
  selector:
    app: {{ .Chart.Name }}

Others

There are other components that are also worth looking into:

  • helpers.tpl: A file for defining reusable template snippets and helper functions in Helm.
  • NOTES.txt: A file for providing post-installation information and instructions.
  • tests: A directory for defining tests to verify the functionality of the deployed chart.

How to use Helm

Using the my-web-app example above. Your directory might look like the following:

my-web-app/
├── Chart.yaml
├── values.yaml
├── charts/
├── templates/
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── _helpers.tpl
│   ├── NOTES.txt
│   └── tests/
│       └── test-connection.yaml

Let’s look at some of basic Helm commands for this chart:

helm install

To deploy my-web-app Helm chart to your Kubernetes cluster with a release name set to my-release:

helm install my-release ./my-web-app

This will create a Deployment and a Service resource for my-web-app in k8s cluster with the following Kubernetes manifest files:

deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-release-my-web-app
  labels:
    app: my-web-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-web-app
  template:
    metadata:
      labels:
        app: my-web-app
    spec:
      containers:
        - name: my-web-app
        image: "my-web-app:1.0.0"
        ports:
          - containerPort: 80
        resources:
          limits:
            cpu: 100m
            memory: 128Mi
          requests:
            cpu: 100m
            memory: 128Mi

service.yaml:

apiVersion: v1
kind: Service
metadata:
  name: my-release-my-web-app
spec:
  type: ClusterIP
  ports:
    - port: 80
  selector:
    app: my-web-app

Notice how the variable names have been replaced with the correspoding values in values.yaml.

helm upgrade

To upgrade the existing my-release to a new version of the my-web-app chart, start by modifying values.yaml. For example, change the image tag:

image:
  repository: my-web-app
  tag: "2.0.0"
  pullPolicy: IfNotPresent

Then run:

helm upgrade my-release ./my-web-app

The Deployment resource should be updated with the new image tag.

helm roll back

If for some reasons, the new image tag 2.0.0 doesn’t work and you want to change it back to 1.0.0. You can roll my-release back to the previous version:

helm rollback my-release 1

The Deployment resource should get back to using 1.0.0 tag for its image.

helm uninstall

To take the app down, you can uninstall my-release from the Kubernetes cluster:

helm uninstall my-release

All resources associated with app should be deleted.

Conclusion

In this article, we’ve explored the basics of Helm, a powerful package manager for Kubernetes that simplifies the deployment and management of applications. Helm bundles up mutliple Kubernetes resources, implements dynamic resource definitions and provides simple commands for version control. Thanks to Helm, app deployments onto k8s become extremely maintainable, reusable and managable.