An introduction to Helm

Containers solve problems but also create problems of their own, sometimes reintroducing problems which we already solved with other more traditional systems. In this article, I want to talk about Helm. Why do you need Helm? What it is and what to expect from upcoming versions?

Why do you need Helm?

You need orchestration for managing your containers. When your containers start to get quite numerous, it becomes time consuming to manage them.

When you typically start using Kubernetes, you start with a YAML file where you define a deployment, often for launching Nginx, followed by a service and so on. After that you use kubectl apply -f, the name of the file and, then deploy. And then the cluster takes care of it.

Your next step might involve a for-loop around all your YAML files. That’s already a step forward but after a while, this starts to get cumbersome. This is where Helm comes in. Helm allows you to structure your YAML representations of Kubernetes Api Objects with the added benefits of versioning and defining release cycles.

What is Helm?

Helm is a package manager for Kubernetes. More or less, Helm has the same function as the for-loop around your YAML file but it is more than that. Helm allows you to manage complexity. It enables you to introduce some versioning into your containers or the different applications that you want to deploy. Helm can share these things but also allow you to perform rollbacks when you stumble upon a problem and you want to fix quickly.

Where does Helm come from?

Helm started as a hackathon within a company called Deis, in October 2015. By that time Kubernetes didn’t exist yet. Deis was creating Fleet, a tool to manage clusters. At some point, they made a shift from Fleet to Kubernetes and Helm 1.0 was released.

Later, Google reached out to the Helm team because they were also creating a tool for managing cluster, called Google deployment manager. Helm 2.0 is the result of this integration of these two code bases.

By the end of November, we are expecting Helm 3.0 which will be discussed later on in this article.

Helm 2.0

Helm has two components. First, you have the client application which resides on your laptop and your CI/CD tool. Secondly, Helm is going to talk to Tiller, the service inside the cluster which it initializes. Tiller can also be seen as a giant sudo server. By default, Helm has access to all the cluster components through it. With some proper configuration however, it can be secured adequatly. In essence, Helm uses a templating engine for generating your YAML files with some additional logic.

How does Helm look like?

1. Charts

Charts represent a folder containing YAML files, added files, and metadata. Here’s an example of what a chart looks like. In this case, I have a random application called keycloak. This chart file contains a template folder and a values file.

➜ keycloak git:(master) tree
├── Chart.yaml
├── templates
│├── deployment.yaml
│├── _helpers.tpl
│├── NOTES.txt
│├── service.yaml
│└── tests
│ └── test-connection.yaml
└── values.yaml
  • Inside the chart.yaml file you will find metadata, API versioning, notations and a description and a version for the chart.
  • In the values.yaml you’re going to put some defaults. For example:
    • I want a replica count 1
    • I want this chart to deploy a container called keycloak
    • I want the default tag to be latest
    • Other default parameters
  • The template folder is where you put your YAML files. This folder contains the same YAML files you would use for deploying your containers and other Kubernetes Resources. The difference is that you add templating entities which Helm will replace with actual values before pushing them to Tiller (and not directed to Kubernetes). Tiller is then going to perform the requests to Kubernetes, to apply them.

➜ keycloak git:(master) cat templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include “keycloak.fullname” . }}

labels:
{{ include “keycloak.labels” . | indent 4 }}
spec:

replicas: {{ .Values.replicaCount }}
selector:
matchLabels:

  app.kubernetes.io/name: {{ include "keycloak.name" . }}  
  app.kubernetes.io/instance: {{ .Release.Name }}  

template:
metadata:
labels:

  app.kubernetes.io/name: {{ include "keycloak.name" . }}  
  app.kubernetes.io/instance: {{ .Release.Name }}  

2. Subcharts

In helm, you have a concept called SubCharts. Within that folder structure, you can add a folder called charts and add dependencies. Why would you do that? You can have a Wordpress chart which not only allows you to deploy a wordpress container, but also manage the deployment and release cycle of a PHP and MySQL chart etc. Together in one big release entity.

➜ wordpress git:(master) tree -L 2
├── charts
│ ├── php
│ └── mysql
├── Chart.yaml
├── templates
└── values.yaml

To Repo or not to Repo?

~ helm repo list
NAME URL
stable https://kubernetescharts.storage.googleapis.com
local http://127.0.0.1:8879/charts

In this example you have a default repository, pointing at kubernetischarts.storage.googleapis.com. This is the primary place where you can ask to fetch pre-created, pre-approved, pre-curated Helm charts. You can host it yourself with for example chartmuseum.

Essentially your chart is a collection of files and folders, and with that knowledge, nothing prevents you from creating your own git repository and adding your subcharts as submodules. Basically, it is a simple structure of files.

How does the Helm workflow look like?

$ helm init –history-max 200
$ helm repo update
$ helm install stable/mysql
NAME: wintering-rodent
LAST DEPLOYED: Thu Sep 25 19:20:18 2019
NAMESPACE: default
STATUS: DEPLOYED
$ helm upgrade –set pwd=3jk$o2,z=f\30.e wintering-rodent stable/mysql
$ helm delete wintering-rodent

Once you’ve downloaded the Helm binary, verified that you are able to execute it and your credentials to connect with your cluster are set, you need to perform an initialization.

The command “helm init” is going to instruct your cluster to install Tiller. I do specify –history-max 200 because every time you make a new release or change something, it is going to save the history of that event in your cluster by default. If you don’t add a –history-max, it’s going to keep on adding. Now you keep it to a certain maximum.

Helm repo update is going to update the local Cache of the upstream repository with the container definitions.

This is an example of how you could install a chart of MySQL. The defaults get a randomly generated release name. It is deployed and then you can upgrade, followed by deletion to the release.

Testing with Helm

➜ helm template keycloak Source: keycloak/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: release-name-keycloak
helm plugin install https://github.com/instrumenta/helm-kubeval
Test config against Kube schemas
  • Syntax test: The most simple test for your Helm charts before deploying is a Syntax test: By using the template function you can check if you made any syntax errors.
  • Unit testing
    • Helm test , a test function that spawns a container. The goal of that container is to exit cleanly with an exit status of zero after testing various aspects of the application deployed in it. Then you have command hooks: if a test needs to pass, needs to fail and, you can pass on configuration parameters to trigger different states.
    • A conftest which uses the Open Policy Agent. This is not limited to testing helm charts. You can use this to test a lot of broader things.

Helmfile

Helmfile is a declarative specification for deploying helm charts. This allows you to make it an easier to version your helm releases. You can apply CI/CD to configuration changes and periodically sync to avoid skews in environments.

Helm 3.0

Helm 3.0 is a complete re-architecture based on community best practices and with a big focus on security. Helm 3.0 is nearing completion and can already be tested. One of the major improvements is the removal of Tiller.

Why are they able to remove Tiller?

Helm is going to be more native to Kubernetes. Helm 3.0 will talk directly to the Kubernetes API. That is one of the reasons why they can kick out Tiller. A new security feature is that the capabilities of Helm are limited to what your user is capable of or authorized to do within your cluster. By default, your Helm can only do as much as your user.

Syntax changes

  • helm delete → helm uninstall
  • helm inspect → helm show
  • helm fetch → helm pull
  • –purge default (override: helm uninstall –-keep history)

Chart dependency

When you deploy a release without specifying the name it is going to force you to give a name to your release unless you pass the generate name option.

Other changes

  • Pluggable authehication
  • Optional support for Lua
  • Library charts: Library charts are the same thing as shared libraries. Libraries are not translated into objects that your cluster can deploy but they’re there to make it easier to reuse code.
  • Personal repos instead of the stable upstream repo: Helm 3.0 is going to kick out the knowledge of a stable repository. They are going to push people into maintaining their own repos. When you deploy a release without specifying the name it is going to force you to give a name to your release unless you pass the generate name option.

Conclusion

In this blog post we presented a brief introduction on Helm 2 and what will be different in Helm 3.

  • Why? Helm allows you to structure your YAML representations of Kubernetes Api Objects with the added benefits of versioning and defining release cycles.
  • What? Helm is a package manager for Kubernetes.

If you are intreseted to learn more about Helm, visit their website.