Helm (site) is an open-source Kubernetes package and operations manager (more info). Its name stems from the (likely mangled from a mispronunciation of the) Greek word κυβερνήτης which translates to “pilot” or “helmsman”. The helmsman stands of the deck and the helm steers the boat. At it is either a tiller or the steering wheel.
The Helmsman also uses charts to guide the route that the boat will take on their journey so logically Charts in Helm are the configuration files that allow the packaging of a Kubernetes release into a single file which then guide the deployment of your Kubernetes environment. All-in-all quite a clever and sensible naming strategy.
A Helm Chart at its minimum will contain a deployment and a service, but can contain any number of Kubernetes objects, for example ingress and persistent Volume Claims.
Why would we use Helm?
We have already learned that a Helm Chart is used to deploy an application or even as a part of a larger application deployment strategy. There are many official Helm Charts, which can be downloaded from their respective repositories. Because they utilize an open-source licensing model you are free to use as-is or modify to suit your purpose. For example modify a Helm Chart to install a PostgreSQL container rather than a MySQL one.
The power of a Helm Chart is clear. It simplifies software deployment (installation, configuration, integration). Helm is a layer of abstraction that can simplify deployment whilst providing a method of repeatability, which in turn brings stability – and stability is one of the core pillars of operational desires.
Installing Helm
There are a number of platforms that you can install Helm to including Windows, Linux (Intel, AMD,ARM, PPC, and even s390 if you have a spare mainframe server hanging about doing nothing) and finally macOS. This shows the cross-platform of Helm, powered by the cross-platform nature of containers.
Pre-requisites
- A stable and up-to-date version of Kubernetes
- A configured local copy of kubectl
Installation depends on the target operating system, for example on macOS you would use Homebrew to install it, on Windows you would use Chocolatey.
However, for Linux, the most common method is with a script file. There is currently no Yum, apt or yast package for Helm (although there is a Ubuntu Snap package).
curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash
After the initial installation
The first thing to do after installation is to add a Chart repository. To get yourself started it is recommended to add the official Helm repository, this contains Charts that are certified as stable and are trusted to actually do what they say on the tin:
helm repo add stable https://kubernetes-charts.storage.googleapis.com/
to confirm that the repo has been added correctly you can list out your Charts using the command:
helm search repo stable
if everything worked as expected you should see something similar to the graphic below
Customizing your Helm Environment
Currently we have only added the standard Helm repository, but you will want to create your own Charts that are customized for your environment. As your customized Charts cannot be easily be hosted on the default repository; this will mean hosting your own repository. Fortunately, this is easy as a Helm repository is effectively any HTTPS server that can service yaml, tar files and answer GET requests. As such, server location is very flexible, you can set it up in your GitHub or GitLab environment, even host it on a standard HTTP web-server like ISS or Tomcat. Learn more about Chart repositories here.
What does a Helm Chart look like?
At its most basic a Helm Chart is a yaml file. You will need to get acquainted with these if you want to deploy your own custom applications.
To generate a skeleton Chart you use the following command (chartname is your name for your Chart):
helm create chartname
this creates a values.yaml file, a template folder that contains three more yaml files; deployment, ingress and service. Amongst a number of other files as outlined below:
chartname |-- Chart.yaml |-- charts |-- templates | |-- NOTES.txt | |-- _helpers.tpl | |-- deployment.yaml | |-- ingress.yaml | `-- service.yaml `-- values.yaml
How do these files map together?
See what I did there? Like the corner pieces in a jigsaw puzzle the most important section is the templates directory. It is in here that Helm finds the YAML definitions for your Services, Deployments and other Kubernetes objects. If you have already generated definitions for your application, all you need to do is replace the generated empty YAML files for your own and voila, you have a working Chart that you can simply deploy using the helm install command.
Helm uses Go to run each of the files in the templates directory using the template rendering engine, Helm has extended the template language by adding a number of utility functions for writing Charts. Let’s have a quick look at the service.yaml file that is auto-generated by the creation command.
apiVersion: v1 kind: Service metadata: name: {{ template "fullname" . }} labels: chart: "{{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}" spec: type: {{ .Values.service.type }} ports: - port: {{ .Values.service.externalPort }} targetPort: {{ .Values.service.internalPort }} protocol: TCP name: {{ .Values.service.name }} selector: app: {{ template "fullname" . }}
This is a default service definition. When the Chart is deployed Helm well generate a definition that will look more like a valid service, we can dry-run this with the following command.
helm install --dry-run --debug ./chartname ... # Source: chartname/templates/service.yaml apiVersion: v1 kind: Service metadata: name: Amazic-test-chartname labels: chart: "chartname-0.1.0" spec: type: ClusterIP ports: - port: 80 targetPort: 80 protocol: TCP name: my-application selector: app: Amazic-test-chartname ...
The next file to take note of is the values.yaml file. This is effectively a variables file; here you can see two variables that relate to the ingress and target port for the application.
# Default values for chartname. # This is a YAML-formatted file. # Declare variables to be passed into your templates. …. Service: type: ClusterIP externalport: 80 internalPort:80
if you desire a different value from that in your values.yaml file, you can override the values.yaml file by directly setting the value on the command line
helm install my-application ./chartname --dry-run --debug --set externalport=8080
The next file to look at is the NOTES.txt file this is effectively your Chart documentation, this is a templated file that is printed out after the Chart has successfully deployed.
1. Get the application URL by running these commands:
{{- if .Values.ingress.enabled }}
{{- range $host := .Values.ingress.hosts }}
{{- range .paths }}
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ $host.host }}{{ . }}
{{- end }}
{{- end }}
{{- else if contains "NodePort" .Values.service.type }}
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "chartname.fullname" . }})
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
echo https://$NODE_IP:$NODE_PORT
{{- else if contains "LoadBalancer" .Values.service.type }}
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "chartname.fullname" . }}'
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "chartname.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
echo https://$SERVICE_IP:{{ .Values.service.port }}
{{- else if contains "ClusterIP" .Values.service.type }}
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "chartname.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
echo "Visit https://127.0.0.1:8080 to use your application"
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:80
{{- end }}
This is a copy of the default NOTES.txt file is is highly recommended that you edit the file to reflect your application. This file prints access directions to the command line when a Chart has been deployed and can consume variables.
Deploying your first Helm Chart
When your Chart is ready, you can use this command to create a .tgz package:
helm package chartname
You can upload this package to your Chart repository, or install it to your cluster. You can also install or upgrade the Chart without packaging it first.
First, install your Chart “chartname”:
helm install chartname
List the helm releases – you should see a generated deployment name with the Docker image designated by “chartname”.
helm ls
Delete the deployment.
helm delete generated-deployment-name
Package the Chart.
helm package chartname
Install the packaged Chart.
helm install chartname-0.1.0.tgz
To make changes, update the version number in chart.yaml. Package the Chart, and upgrade.
helm upgrade generated-deployment-name chartname-0.2.0.tgz
To assign a release name to a Chart, type:
helm install release-name chartname
Tip: to delete all local Helm deployments, use helm delete $(helm ls –short)
Summary
Helm Charts can help take your Kubernetes application to the next level by templatizing variables, reducing copy-paste work with the values.yaml file, and specifying Chart dependencies. In our next post we will look at using a Helm Chart to deploy a new Vault 1.4 cluster