Authoring a Helm Chart on Kubernetes / AKS - Getting started
Solution ·As we discussed in our last article, Helm is a great technology. I recommend using it not only to manage third party packages but also your own custom-developed solutions.
But how do you author a Helm Chart?
I found that question hard to answer. The common answer is “look at existing ones”. I have two problems with that:
- You'll be hit by complexity before you understand what a chart is so won't get very far.
- That sounds a lot like the old C / C++ makefiles: copy mine and modify it to fit your needs.
Now, if there’s a way to hate a technology and not want to use it, it is to have it rime with makefile. I don’t want that to happen to you, so, allow me to introduce you gently to Helm chart authoring.
In this article, we’ll author the simplest chart ever. The chart will deploy one Kubernetes resource: a namespace. It won’t contain any parameters, any dependent charts, tests or what have you. We will tour the world of Helm chart and run a bunch of commands to get familiar.
As usual, the code is on GitHub. There is also documentation out there. I recommend:
Both from the official Helm site. It is comprehensive. This article is shorter and simpler.
Installing
First you need to install Helm.
Helm comes as two components: Helm on the client side (e.g. your computer) and tiller on the cluster.
We recommend looking at either AKS documentation or Helm documentation for guidance.
Concepts
Let’s get a few concepts out of the way.
From the official documentation, there are three big concepts we should be familiar with:
- A Chart is a Helm package. It contains all of the resource definitions necessary to run an application, tool, or service inside of a Kubernetes cluster. Think of it like the Kubernetes equivalent of a Homebrew formula, an Apt dpkg, or a Yum RPM file.
- A Repository is the place where charts can be collected and shared. It’s like Perl’s CPAN archive or the Fedora Package Database, but for Kubernetes packages.
- A Release is an instance of a chart running in a Kubernetes cluster. One chart can often be installed many times into the same cluster. And each time it is installed, a new release is created. Consider a MySQL chart. If you want two databases running in your cluster, you can install that chart twice. Each one will have its own release, which will in turn have its own release name.
In short, a Chart is a Helm Package. A Release is chart deployed, with parameters (or values), on a cluster. It’s like an instance of a chart. A Repository is the central location where charts are collected and distributed. It’s like a Docker Repository but for charts (and way simpler). Azure Container Registry can be used as a Helm Repository.
So we have the following relationships:
File Structure
A chart is an archive, a TGZ (i.e. TAR + GZIP) archive. It is composed of multiple files.
According to the official documentation, the file structure of a chart is the following:
<Chart Name>/
Chart.yaml # A YAML file containing information about the chart
LICENSE # OPTIONAL: A plain text file containing the license for the chart
README.md # OPTIONAL: A human-readable README file
requirements.yaml # OPTIONAL: A YAML file listing dependencies for the chart
values.yaml # The default configuration values for this chart
charts/ # A directory containing any charts upon which this chart depends.
templates/ # A directory of templates that, when combined with values,
# will generate valid Kubernetes manifest files.
templates/NOTES.txt # OPTIONAL: A plain text file containing short usage notes
We see there are a lot of optionals in there. This is why it’s easy to start.
Let’s look at our example at https://github.com/vplauzon/helm/tree/master/a-namespace. It has the following files:
a-namespace/
Chart.yaml
README.md # Optional but quick to write
values.yaml # Mandatory, but empty in our case
templates/
namespace.yaml # The only resource this chart deploys: a namespace
NOTES.txt # Optional but quick to write
As promised, this is pretty minimalist.
There really is content in only Chart.yaml and namespace.yaml, so let’s look at those.
Chart.yaml
Chart.yaml’s schema is defined in the official documentation. It contains a few mandatory fields and a lot of optional ones.
Our Chart.yaml is defined as follow:
apiVersion: v1
name: a-namespace
version: 0.1.0
description: A simple example of a chart:: solely deploys a namespace
keywords:
- namespace
- simple
home: https://github.com/vplauzon/helm/tree/master/a-namespace
sources:
- https://github.com/vplauzon/helm/tree/master/a-namespace
maintainers: # (optional)
- name: Vincent-Philippe Lauzon
email: NA
url: http://vincentlauzon.com/
It stands in 14 lines. Let’s look at a few of them:
Line # | Field | Comments |
---|---|---|
1 | apiVersion | Always v1: easy. |
2 | name | Name of the chart. It must match the folder name. |
3 | version | That's the package version. This will appear later when we list the Helm releases running on the Cluster. |
5 | keywords | Those are useful for feeding in the search (i.e. helm search command) within a repository |
The rest is purely informational.
Template
In our case we have only one template: namespace.yaml. In general, there are many files in the template folder.
It is recommended practice to have one Kubernetes resource per template file.
namespace.yaml has the following content:
apiVersion: v1
kind: Namespace
metadata:
name: helm-deployed
This template is straightforward as there is no values. We’ll cover values in a future article. It is a simple namespace description.
When there are many files in the template folder, or even many resources in one file, the resources are sorted by kind and then alphabetic order for deployment.
Deployment
Before we deploy our chart, let’s look at the current namespaces:
$ kubectl get namespaces
NAME STATUS AGE
default Active 4d
kube-public Active 4d
kube-system Active 4d
This is the typical configuration of a vanilla AKS cluster.
helm install
is used to install a chart, i.e. create a release. We can install from different sources:
- Local folder (unpacked chart)
- Local archive (.tgz)
- Remote archive (i.e. URL)
- From repository
Let’s do the first one. Let’s clone the repo and position ourselves just above the a-namespace folder.
Now we can install by typing:
$ helm install a-namespace
NAME: coiled-heron
LAST DEPLOYED: Wed Oct 17 13:33:26 2018
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/Namespace
NAME AGE
helm-deployed 0s
NOTES:
No values are supported. This is the most vanilla chart.
A couple of observations here:
- The name is generated as coiled-heron in our case ; this is random ; we'll see we can set the name
- The namespace is default ; this is the namespace where templates not specifying a namespace will be deployed (in our case it doesn't apply as we only deploy a namespace per se)
- It lists the resources that were deployed ; in our case helm-deployed namespace
- The NOTES section is the NOTES.txt file content
Now if we look at the cluster’s namespaces again:
$ kubectl get namespaces
NAME STATUS AGE
default Active 4d
helm-deployed Active 1m
kube-public Active 4d
kube-system Active 4d
We observe the helm-deployed namespace that was just deployed.
Let’s look at the charts installed in the cluster:
$ helm list
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
coiled-heron 1 Wed Oct 17 13:33:26 2018 DEPLOYED a-namespace-0.1.0 default
We observe the following:
- The release name is there: coiled-heron
- The revision is 1 ; this isn't the chart's version, it is the release's revision
- The chart is a-namespace-0.1.0, which is a concatenation of the chart's name and version
At a glance we can see what is deployed on our system.
The revision is an integer incrementing at every update. It is used to track upgrades and rollbacks.
Let’s delete the release and confirm the namespace is gone:
$ helm delete coiled-heron
release "coiled-heron" deleted
$ kubectl get namespaces
NAME STATUS AGE
default Active 4d
kube-public Active 4d
kube-system Active 4d
Now, let’s reinstall the chart by given the release a name this time:
$ helm install --name myrelease a-namespace
NAME: myrelease
LAST DEPLOYED: Wed Oct 17 13:39:18 2018
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/Namespace
NAME AGE
helm-deployed 0s
NOTES:
No values are supported. This is the most vanilla chart.
We can then find that release name in the list of releases as well:
$ helm list
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
myrelease 1 Wed Oct 17 13:39:18 2018 DEPLOYED a-namespace-0.1.0 default
helm list
returns the list of deployed releases. Helm tracks deleted releases for audit purposes. We can see all releases, including deleted ones with:
$ helm list --all
NAME REVISION UPDATED STATUS CHART APP VERSION NAMESPACE
coiled-heron 1 Wed Oct 17 13:33:26 2018 DELETED a-namespace-0.1.0 default
myrelease 1 Wed Oct 17 13:39:18 2018 DEPLOYED a-namespace-0.1.0 default
Finally, we could package our chart:
$ helm package a-namespace/
Successfully packaged chart and saved it to: /home/vplauzon/git/helm/a-namespace-0.1.0.tgz
The created archive could then be uploaded to a repository (e.g. Azure Container Registry).
Summary
We did a quick getting started on Kubernetes Helm.
We saw the big concepts, the file structure, a very simple example and a couple of command lines.
Helm is quite easy to use and not so complicated to author. We hope this quick start will help you start authoring Helm charts for your projects!
Update (07-11-2018): See Authoring a Helm Chart on Kubernetes / AKS – Parametrized values on how to author charts with parameters.