An intro to Helm and how you can use it for packaging cloud native applications
Table of contents
In the evolving landscape of the cloud native world managing and deploying applications to kubernetes environments has become a critical skill.
Helm is a tool which aids in simplifying the complex process and provides a streamlined process.
Why Helm
Reproducible and Consistency: Helm allows us to package complete applications and configurations into a single unit.
Versioning and Rollback: Helm allows us to version our charts and perform rollbacks when required.
Multi Environment Deployment: The template engine of helm allows us to seamlessly deploy resources in multiple namespaces and environments.
CI/CD integration: Helm integrates easily with CI/CD pipelines which allows organizations to automate deployment processes.
Building a sample Helm Chart
To build a helm chart from scratch firstly install helm in your system.
Once run in your directory run the following command
helm create webserver
A directory called webserver is created
templates: these are the files helm packages and manages , these are the kubernetes manifests that helm will deploy.
Chart.yaml: metadata about the helm chart , contains details about chart name , version , description.
values.yaml: default configuration about the helm chart.
helperts.tpl: reusable Go template functions.
For this exercise we will only work with the deployment.yaml and service.yaml so the rest of the files in templates can be removed.
rm hpa.yaml ingress.yaml serviceaccount.yaml
These are the parts which are picked from values files
"{{ .Values.image.repository }}
We are going to add another container to this deployment so under the values.yaml add a block like this.
In the values.yaml file we add this
webcontainer:
name: httpd
repository: httpd
pullPolicy: Always
tag: latest
In the deployment.yaml template we add the following block
- name: {{ .Values.webcontainer.name }}
image: {{ .Values.webcontainer.repository }}:{{ .Values.webcontainer.tag }}
imagePullPolicy: {{ .Values.webcontainer.pullPolicy }}
So the containers block looks like this
containers:
- name: {{ .Values.webcontainer.name }}
image: {{ .Values.webcontainer.repository }}:{{ .Values.webcontainer.tag }}
imagePullPolicy: {{ .Values.webcontainer.pullPolicy }}
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 80
protocol: TCP
To test the helm templates we can run the following commands
helm template web ./webserver
web is the releaseName given to the chart.
The output displayed is this
apiVersion: apps/v1
kind: Deployment
metadata:
name: dryrun-webserver
labels:
helm.sh/chart: webserver-0.1.0
app.kubernetes.io/name: webserver
app.kubernetes.io/instance: dryrun
app.kubernetes.io/version: "1.16.0"
app.kubernetes.io/managed-by: Helm
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: webserver
app.kubernetes.io/instance: dryrun
template:
metadata:
labels:
app.kubernetes.io/name: webserver
app.kubernetes.io/instance: dryrun
spec:
serviceAccountName: dryrun-webserver
securityContext:
{}
containers:
- name: httpd
image: httpd:latest
imagePullPolicy: Always
- name: webserver
securityContext:
{}
image: "nginx:1.16.0"
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http
resources:
{}
helm install --debug --dry-run dryrun ./webserver
This displays the installation process and demonstrates the template values , this will not install the chart but show what is about to be installed.
To package the chart into a tar file run the following command
helm package webserver
Output: Successfully packaged chart and saved it to: webserver-0.1.0.tgz
Installation of Helm Chart
Let us install the chart
helm install web ./webserver
OUTPUT
NAME: web
LAST DEPLOYED: Wed Feb 7 20:02:07 2024
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=webserver,app.kubernetes.io/instance=web" -o jsonpath="{.items[0].metadata.name}")
export CONTAINER_PORT=$(kubectl get pod --namespace default $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
echo "Visit http://127.0.0.1:8080 to use your application"
kubectl --namespace default port-forward $POD_NAME 8080:$CONTAINER_PORT
Run the following commands to view your deployed pods and deployment
kubectl get deploy
kubectl get pods
To upgrade a chart i:e to make modifications to the chart edit the templates and run the following command
helm upgrade web ./webserver
Release "web" has been upgraded. Happy Helming!
NAME: web
LAST DEPLOYED: Wed Feb 7 20:05:37 2024
NAMESPACE: default
STATUS: deployed
REVISION: 2
Notice the revision is marked as 2.
To view the revisions by helm run the following command
helm history web (web is release name)
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
1 Wed Feb 7 20:02:07 2024 superseded webserver-0.1.0 1.16.0 Install complete
2 Wed Feb 7 20:05:37 2024 deployed webserver-0.1.0 1.16.0 Upgrade complete
To rollback to a particular release run the following command
helm rollback web 1
Rollback was a success! Happy Helming!
View helm history once again
helm history web
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
1 Wed Feb 7 20:02:07 2024 superseded webserver-0.1.0 1.16.0 Install complete
2 Wed Feb 7 20:05:37 2024 superseded webserver-0.1.0 1.16.0 Upgrade complete
3 Wed Feb 7 20:09:22 2024 deployed webserver-0.1.0 1.16.0 Rollback to 1
This is a basic intro on developing your own custom charts using helm.
A sample Helm Project can be found here -> Click here for a Helm project
Happy Helming.