In this post we will take a closer look at Helm: a package manager for Kubernetes. We will take a look at the terminology used, install the Helm Client and Server, deploy an existing packaged application and take a look at some useful Helm commands.

Introduction

We can deploy our Docker image manually in Kubernetes and configure Kubernetes to manage our Docker image. So, why do we need a package manager for our application to deploy it to Kubernetes? A package manager will package your Docker image together with the Kubernetes configuration and let you deploy this all together. The advantage is that you are able to put your Kubernetes configuration under version control for your different environments (e.g. development, staging, production) and create a new package when something changes to it. There are several tools available which make it easier to deploy your application to Kubernetes and Helm is one of those. Helm is also maintained by the CNCF (Cloud Native Computing Foundation).

Most of the information in this post is executed with the help from the official Helm documentation.

Prequisites

We will need the following applications in this post:

  • a Kubernetes cluster, we will use Minikube for it;
  • Kubectl, the CLI tool for interacting with your Kubernetes cluster;
  • and of course Helm which consists of two parts:
    • Helm, which is the Helm Client application;
    • Tiller, which is the Helm Server application which we will install by means of the Helm client into our Kubernetes cluster.

We will ignore any security at this point since we will use a local Minikube Kubernetes cluster. For production use, however, you should definitely incorporate security.

Installation

Minikube and kubectl

For installation of Minikube and kubectl, I refer to a previous post where the installation is explained.

Helm Client and Tiller

First of all, we need to install the Helm Client. Therefore, we go to the Helm releases page. I downloaded the shell script they made available, this made it quite easy to download and install the Helm Client (be sure to give it execution rights with ‘chmod +x’). After running the script, the Helm Client is successfully installed. At the time of writing, version 2.10.0 was installed.

For installing Tiller (the Helm server), we have two choices. The first option can be used for development purposes: you can decide to install Tiller locally and therefore you will have to tell Tiller which Kubernetes cluster to point to. The other option, the one I chose to use, is to install Tiller inside your Kubernetes cluster. During installation, the context (the Kubernetes cluster to use) will be taken from your kubectl config. Execute the following command in order to install Tiller:

sudo helm init

At this moment, we have installed Helm in an insecure manner, but as already said, it doesn’t matter for now, because we are working locally and it is not for production use.

Our Helm configuration is the following (where <user> is your Linux user):

stable repo: https://kubernetes-charts.storage.googleapis.com
local repo: http://127.0.0.1:8879/charts
HELM_HOME: /home/<user>/.helm

That’s it for the installation, which went very smoothly.

Some Helm concepts

Before we proceed, we need to get acquainted with some of the terminology being used in Helm:

  • A Chart is a Helm package. It contains all of the files needed to run your application inside of a Kubernetes cluster. Think of it like your software sources in a Git repository. The official Helm charts can be found on GitHub.
  • A (Chart) Repository is a location where the packaged and versioned charts are released. These packages can be deployed to your Kubernetes cluster. Think of it like your binary repository where you keep the different versions of your software (like a Nexus or Artifactory Repository). The Repository for the official Helm charts can be found here (you will need a Google account in order to access it).
  • A Release is an instance of a chart running in a Kubernetes cluster. Every time you install a chart, it becomes a new release.

To summarize, Helm installs a Chart from a Repository as a Release in a Kubernetes cluster.

Install a Helm chart

In this section we will try to install an existing chart from the official Helm repository. First, we need to search for a chart to install. We can do so by browsing to the list of stable charts or we can do so by means of the command line:

helm search

The Helm search command will return you the list of stable charts in the official Helm repository. You can also search for a particular chart by adding a search term to it. In our example, we are going to install the Grafana Helm chart. We are not going to do anything with Grafana itself, but it can be installed easily and has an admin page which we can use to test if everything is working fine. So, we will search for Grafana:

helm search grafana

This will return us the following result:

NAME              CHART VERSION    APP VERSION    DESCRIPTION 
stable/grafana    1.14.5           5.2.3          The leading tool for querying and visualizing time series...

The next thing to do, is to take a closer look at the information of the chart. We can do so by means of the inspect command:

helm inspect stable/grafana

Now a lot of information is returned. This information is also available on GitHub. What you can see here is for example all the parameters that can be set in order to configure the installation to your needs. Also, the default values of these parameters can be viewed. When you take a look at the parameter service.type then we notice that the default value is ClusterIP. In our case, when using Minikube, I want to set this to NodePort in order to make Grafana accessible outside the Kubernetes cluster.

With this in mind, we can now install the Grafana Helm chart into our Kubernetes cluster:

sudo helm install stable/grafana --name mygrafana --set service.type=NodePort

After the install command, we add the chart we want to install, stable/grafana in this case, we give our release a name mygrafana and we set the parameter service.type to NodePort. Another way to set parameters is by adding a values.yaml file to the install command which contains the parameter values.

When running this command, I quickly ran to the following error:

an error occurred forwarding 35793 -> 44134: error forwarding port 44134 to pod <guid>, uid : unable to do port forwarding: socat not found.
Error: transport is closing

Apparently, the socat tool is required for installing a Helm chart. Install it with the following command:

sudo apt-get install socat

Now, rerun our install command and now the installation is successful:

NAME:   mygrafana
LAST DEPLOYED: Thu Sep  6 20:22:08 2018
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/Service
NAME       TYPE      CLUSTER-IP      EXTERNAL-IP  PORT(S)          AGE
mygrafana  NodePort  10.102.227.169  <none>       32000:31039/TCP  4s

==> v1beta2/Deployment
NAME       DESIRED  CURRENT  UP-TO-DATE  AVAILABLE  AGE
mygrafana  1        1        1           0          4s

==> v1/Pod(related)
NAME                        READY  STATUS             RESTARTS  AGE
mygrafana-7c6df9bb8d-hg98x  0/1    ContainerCreating  0         3s

==> v1beta1/PodSecurityPolicy
NAME       DATA   CAPS      SELINUX   RUNASUSER  FSGROUP   SUPGROUP  READONLYROOTFS  VOLUMES
mygrafana  false  RunAsAny  RunAsAny  RunAsAny   RunAsAny  false     configMap,emptyDir,projected,secret,downwardAPI,persistentVolumeClaim

==> v1/Secret
NAME       TYPE    DATA  AGE
mygrafana  Opaque  3     6s

==> v1/ConfigMap
NAME       DATA  AGE
mygrafana  1     6s

==> v1beta1/Role
NAME       AGE
mygrafana  5s

==> v1beta1/RoleBinding
NAME       AGE
mygrafana  4s

==> v1/ServiceAccount
NAME       SECRETS  AGE
mygrafana  1        6s

==> v1/ClusterRole
NAME                   AGE
mygrafana-clusterrole  5s

==> v1/ClusterRoleBinding
NAME                          AGE
mygrafana-clusterrolebinding  5s


NOTES:
1. Get your 'admin' user password by running:

   kubectl get secret --namespace default mygrafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo

2. The Grafana server can be accessed via port 32000 on the following DNS name from within your cluster:

   mygrafana.default.svc.cluster.local

   Get the Grafana URL to visit by running these commands in the same shell:
     export NODE_PORT=$(kubectl get --namespace default -o jsonpath="{.spec.ports[0].nodePort}" services mygrafana)
     export NODE_IP=$(kubectl get nodes --namespace default -o jsonpath="{.items[0].status.addresses[0].address}")
     echo http://$NODE_IP:$NODE_PORT


3. Login with the password from step 1 and the username: admin
#################################################################################
######   WARNING: Persistence is disabled!!! You will lose your data when   #####
######            the Grafana pod is terminated.                            #####
#################################################################################

At least, it seems that it is successful. When you take a closer look at the v1/Pod(related) section, you will notice that our Pod is not finished deploying yet. Depending on the chart, it can take a while before the Pod is up-and-running. You can check the status with the status command:

sudo helm status mygrafana

This will return the complete output again which was returned after issuing the install command. If you just want to check the status of the Pod, you can also retrieve the Pods with kubectl and inspect the status of the deployment:

sudo kubectl get pods

Wait until the Pod is ready and then we continue with the Note which was outputted after the installation. First step is to retrieve the admin password in order to be able to login. Do so with the following command:

sudo kubectl get secret --namespace default mygrafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo

In the next step, we want to retrieve the IP address and the port where we can access the admin login page of Grafana. Do so by executing the following commands:

export NODE_PORT=$(sudo kubectl get --namespace default -o jsonpath="{.spec.ports[0].nodePort}" services mygrafana)
export NODE_IP=$(sudo kubectl get nodes --namespace default -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT

Now copy the URL to your browser and the login page of Grafana is shown.

helm-grafana-install

Login with user name admin and the password we retrieved earlier. After pressing the Log In button, we have access to Grafana and our installation is complete.

helm-grafana-logged-in

View, upgrade and delete a Helm chart

In this section we will explore some other useful Helm commands.

List command

With the list command, it is possible to retrieve a list of installed releases. When you add the option --all, all releases are shown (deployed and deleted releases).

sudo helm list

The output in our case, is the following:

NAME         REVISION    UPDATED                    STATUS      CHART             APP VERSION    NAMESPACE
mygrafana    1           Thu Sep 6 20:34:50 2018    DEPLOYED    grafana-1.14.5    5.2.3          default

Upgrade command

With the upgrade command it is possible to upgrade the release to a new Chart version or to update parameters. In our case, we will update a parameter in order to use 2 replicas instead of 1. In order to preserve previous parameters which have been set, we also provide the --reuse-values option. The upgrade command also needs the release name (mygrafana) and the chart (stable/grafana).

sudo helm upgrade mygrafana stable/grafana --reuse-values --set replicas=2

The following output is given after successful upgrade:

Release "mygrafana" has been upgraded. Happy Helming!
...
Again, a complete output as with the install command is given, I represented it with the three dots.
We can check the outcome of our upgrade command with the ‘sudo kubectl get pods‘ command. The output is the following:
NAME                         READY     STATUS    RESTARTS   AGE
mygrafana-64bb749755-j7v4j   1/1       Running   2          3m
mygrafana-64bb749755-pfs7m   1/1       Running   2          24m
Execute the ‘sudo helm list‘ command:
NAME         REVISION    UPDATED                     STATUS      CHART             APP VERSION    NAMESPACE
mygrafana    2           Sat Sep  8 16:28:29 2018    DEPLOYED    grafana-1.14.5    5.2.3          default

We now notice that the revision has been altered to 2.

Delete command

With the delete command, it is possible to remove a release. The release will be present in the history, you can check this with the list command and the option --all.

sudo helm delete mygrafana

The output of the delete command is:

release "mygrafana" deleted

When you want to completely remove the release, use the --purge option with the delete command. Check that it has been completely removed with the list command with option --all. Now it is also removed from the history.

sudo helm delete --purge mygrafana

Summary

In this post we got acquainted with Helm. We took a look at some of the terminology, installed the Helm Client and Server, installed a Chart from the official Repository and took a look at some useful Helm commands. The official Helm documentation is well documented and is of good assistance if you want to explore more Helm features.