HomeOperationsAutomated OperationsUsing Helm to package and deploy container applications

Using Helm to package and deploy container applications

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.

Helm Hearts Kubernetes

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

Helm Repo Search

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)

SummarySummary

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

 

NEWSLETTER

Receive our top stories directly in your inbox!

Sign up for our Newsletters

spot_img
spot_img

LET'S CONNECT