Installing packages with Helm is as simple as adding a repository with helm repo add <<repo_name>> << charts_url >> and then running helm install bitnami/nginx <<name>. The quickstart guide on the Helm site is a great resource to get started – https://helm.sh/docs/intro/quickstart/
In addition to installing applications to a Kubernetes platform Helm can be used to package your own application for easy deployment.
Before we get into some of the details of creating a sample helm chart, let’s look at the main concepts. With Helm, there are some important concepts,
- Charts – A chart is information required to create an instance of a Kubernetes application.
- Config – A collection of configuration files that gets packaged into the chart
- Repo – A place to store charts
- Release – A release is a running instance of a chart that would have its own release name. On a Kubernetes cluster, there can be more than one instance of the same chart each with its own release name.
Packaging an application into a Helm Chart
With the introductory concepts out of the way let’s look at creating a sample Helm Chart. At a very high level creating a helm chart involves defining variables in the Kubernetes manifest files and providing values for those variables as part of the Helm package. Helm then parses the manifest files through its templating engine substituting the defined variables.
In this example, I’m using the sample PHP GuestBook application, the manifest files can be found here PHP GuestBook. The application contains a front-end pod with a front-end service and a mongo DB pod with its service. To get started we will run,
helm create guestbook
This will create a directory structure that looks like the below output with some boilerplate manifests that we can leverage. To package the guestbook application we will place the deployment and service manifest in the template directory, we can also get rid of the boilerplate YAML files.
├── Chart.yaml
├── charts
├── templates
│ ├── NOTES.txt
│ ├── _helpers.tpl
│ ├── deployment.yaml
│ ├── hpa.yaml
│ ├── ingress.yaml
│ ├── service.yaml
│ ├── serviceaccount.yaml
│ └── tests
│ └── test-connection.yaml
└── values.yaml
We will now edit the mongo deployment manifest and add variables in the YAML file. Helm provides built-in objects such as the Release, Chart, Values objects that we can use in our manifest files, In this case, I have defined values for variables in the helm values.yaml file.
The frontend pods and the mongo DB pods can also be split into two different charts with their own values.yaml. In this way, the mongo DB pod can be updated independently from the frontend application
Below spec is the deployment and service manifest for the frontend pod. I’ve provided variables for the name of deployment/service, the number of replicas, image repository and image version. Similar variables are added to the deployment and service manifest of the mongo DB pod.
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{.Values.fe_deploy.name}}
labels:
app.kubernetes.io/name: guestbook
app.kubernetes.io/component: frontend
spec:
selector:
matchLabels:
app.kubernetes.io/name: guestbook
app.kubernetes.io/component: frontend
replicas: {{.Values.fe_deploy.replicas}}
template:
metadata:
labels:
app.kubernetes.io/name: guestbook
app.kubernetes.io/component: frontend
spec:
containers:
- name: {{.Values.fe_deploy.name}}
image: {{.Values.fe_deploy.images.repository}}:{{.Values.fe_deploy.images.version}}
# image: {{.Values.fe_deploy.images.repository}}:{{.Values.fe_deploy.images.version}}
resources:
requests:
cpu: 100m
memory: 100Mi
env:
- name: GET_HOSTS_FROM
value: dns
ports:
- containerPort: 8
---
apiVersion: v1
kind: Service
metadata:
name: {{.Values.fe_svc.name}}
labels:
app.kubernetes.io/name: guestbook
app.kubernetes.io/component: frontend
spec:
# if your cluster supports it, uncomment the following to automatically create
# an external load-balanced IP for the frontend service.
type: NodePort
ports:
- port: 80
targetPort: 80
nodePort: 30007
selector:
app.kubernetes.io/name: guestbook
app.kubernetes.io/component: frontend
---
Now that variables are defined in the Kubernetes manifest files we need to provide values for these variables. To do so we will edit the values.yaml in that directory and define values for our variables.
mongo_deploy:
name: gb-mongo
replicas: 1
images:
version: 4.2
mongo_svc:
name: mongo
fe_deploy:
name: gb-frontend
replicas: 3
images:
repository: paulczar/gb-frontend
version: v5
fe_svc:
name: gb-frontend-svc
To test that our helm package works and the variables are substituted correctly we can run helm install with the –dry-run option. The output should provide Kubernetes manifests with the defined values.
helm install guestbook –dry-run ./guestbook
To install our application we run
helm install guestbook ./guestbook
We can validate the status of our application by running kubectl get pods to verify if all the pods are running. We can run helm list to list installed charts
~/ helm list
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
guestbook default 1 2021-06-10 02:33:16.280572 +1000 AEST deployed guestbook-0.1.0 1.16.0
nginx-1623140150 default 1 2021-06-08 18:15:54.889611 +1000 AEST deployed nginx-9.1.0 1.21.0