Helm 101

What is Helm? How do we deploy our applications?
Helm is a package administrator developed for Kubernetes. You can think of this as apt or yum in the Linux environment. Helm provides us to manage our applications’ sources which are run in a Kubernetes environment (deployment, stateful set, service, ingress, etc.) and avoid complications.
So, how does Helm do all of them? Helm allows us to manage all sources that belong to our applications from one point using the structure named “Chart”. For example, let’s assume we have a web application with dependencies like ElasticSearch and MySQL. After we prepare our environment, I will talk about all processes by deploying the sample application with Helm. It will be harder to control when too many projects and dependencies increase simultaneously.
1. What is Helm Chart?
The chart is a package style that is Helm uses. We can package and version our applications at the Kubernetes environment with Chart. When we create a new Helm Chart, some folders and files come as a default. If we need to examine these files;
demo/ Chart.yaml # A yaml file containing information about the chart. LICENSE # File containing chart license (optional) README.md # Readme file for chart usage or different information. (optional) values.yaml # The file that holds the variables we created to access our Kubernetes resources directly. values.schema.json # JSON schema to impose a structure on value.yaml (optional) charts/ # Directory created to use different charts or dependencies in the chart. (use optional) crds/ # Kubernetes Custom Resource Definitions templates/ # The directory where our Kubernetes resources are located. templates/NOTES.txt # After our Kubernetes resources are deployed, they can be used to show different information about usage or additional information via the terminal (optional)
Now that we know the basic terms, we can do a sample demo and move on. First of all, we need to prepare our environment. After we prepared our environment, I will try to tell all processes with deploy the sample application with Helm.
2. Helm Setup
You can implement the below steps at your terminal environment to set up Helm to Linux environment. If you want to set up to different operation system, you can follow the steps from the Helm documentation.
Reminder: You need to have a Kubernetes cluster to use Helm. If you don’t have any Kubernetes cluster and want to set it up quickly, you can read my K3D and K3S Kubernetes Cluster Setup blog post.
$ curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 $ chmod 700 get_helm.sh $ ./get_helm.sh
After you did the steps, you can run the helm version –client command to verify the setup.
3. Creating Chart
If you did the Helm setup to your system successfully and your cluster is ready too, now we can deep dive into Helm by making demos. Firstly, let’s start with creating a Helm Chart. As we can create Helm Chart from zero, we can use prepared Helm Charts too. Now we will learn to create a Helm Chart from zero.
$ helm create demo
If you control with ls after you run the command, you will see a created file named demo.
demo ├── charts ├── Chart.yaml ├── templates │ ├── deployment.yaml │ ├── _helpers.tpl │ ├── hpa.yaml │ ├── ingress.yaml │ ├── NOTES.txt │ ├── serviceaccount.yaml │ ├── service.yaml │ └── tests │ └── test-connection.yaml └── values.yaml
This chart created by Helm helps most of our needs. Basic Kubernetes sources are located in this Chart in the templates folder. Now, let’s examine the content of our Chart.yaml file.
apiVersion: v2 name: demo description: A Helm chart for Kubernetes type: application version: 0.1.0 appVersion: "1.16.0"
We can change our application’s name, description, version, etc. in Chart.yaml file. I will mention the versions used here when we examine templates/deployment.yaml file.
4. Deploying the Application
There is more than one way to deploy our application at the Kubernetes cluster. The commands below show us how we deploy the created application in the Kubernetes environment;
$ cd demo/ $ helm install demo .
Firstly, we need to go to the index where the chart is, and after that, we need to deploy the application with the helm install command. We can run our demo application in the Kubernetes environment with the command above.
NOTE: If you want to deploy for a different namespace, you can use –namespace parameter.
After the setup, we can see the situation of kubectl get pods and pods.
$ kubectl get pods NAME READY STATUS RESTARTS AGE demo-5c5559755c-vg9xx 1/1 Running 0 2m45s
4.1 Helm Packaging
We can package our Helm Charts with the package command. We can send the chart we packaged to registration or deploy it this way. We can package our demo application with the command below;
$ cd demo/ $ helm package .
After the packaging, when we control the index with ls, there should occur an archive file that ends with *.tgz.
$ ls charts Chart.yaml demo-0.1.0.tgz templates values.yaml
Now, let’s deploy the demo application with demo-2 again. For that, we use the helm install command we used above. But this time, we will give our *.tgz file instead of “.” that we specify the index.
$ helm install demo-2 demo-0.1.0.tgz
After, we can see our active charts with the helm ls command.
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION demo default 1 2022-01-16 20:20:18.996794236 +0300 +03 deployed demo-0.1.0 1.16.0 demo-2 default 1 2022-01-16 20:23:54.947237373 +0300 +03 deployed demo-0.1.0 1.16.0
4.2 Removing the Chart
We can use helm uninstall to remove deployed charts. This command removes all sources of application (deployment, service, ingress, etc.) from our Kubernetes cluster. To remove the demo-2 chart that we ran above, we need to use the following command;
$ helm uninstall demo-2
5. Updating the Application
When we create a helm chart, a prepared chart template is created for us and it comes by default to boot the Nginx image. We want to change this image, for that we need to update the values.yaml file. After the open values.yaml file with any editor, you can see a lot of variables inside that file. All changes that you made at values.yaml update Kubernetes sources which are under the templates/. Shortly, there is more than one Kubernetes source under the templates/. We can say that the values.yaml is for managing these sources from one point.
Now, we can run Helm by changing the image at values.yaml file. First of all, we need to open values.yaml file with any editor. After opening, we can update the section that says image.repository as follows;
image: repository: dturan/echo-server tag: "latest"
So what does the above change mean? All changes that we made on image. repository actually updates the templates/deployment.yaml file. By the way, I will mention tag: part soon. Now, let’s open the templates/deployment.yaml file and examine the related part.
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
You need to see something like above in the section starting with image:. So what exactly does this mean? Let’s examine it step by step.
- {{ . Values. image. repository }} = This part actually means to get the repository value under the image in the values.yaml file.
- {{ . Values. image. tag | default . Chart. AppVersion }} = This part means to get the image.tag value in the values.yaml file, but if you noticed above, we did not assign a value. So what will happen when we don’t make any value assignment? The part specified by | default.Chart.AppVersion goes to the next step if the first condition is not met (it is empty enough for the condition not to be met). So if we don’t give a version for this image, it will read the part that says appVersion: in Chart.yaml.
5.1 Environment Variable Defining
There is an environment called text_message that I have prepared for the application. When we defined this environment, we can publish this with a related service. Our next goal is to define this environment in the Helm environment and access our application from outside.
First of all, let’s open our values.yaml file and add the following lines;
environments: name: text_message value: Hi from Helm Chart ^^
So, is it enough to make this definition? Actually no, we only did definition. Now, let’s examine how can we add this inside Kubernetes deployments. First, let’s open our templates/deployment.yaml file and add the following lines under containers: ;
env: - name: {{ .Values.environments.name }} value: {{ .Values.environments.value }}
We did our definitions. When running the application, our deployment.yaml file can read env.name and env.value variables from values.yaml file anymore.
So, what should we do if we define more than one environment? In such cases, you can define a different variable for each environment or do the following, which is more suitable. Let’s open our values.yaml file again and replace the environments we just added with the following.
environments: - name: text_message value: Hi from Helm Chart ^^ - name: baska_bir_env value: baska bir deger
WARNING: While making this definition, you may need to look at how it is used in the Kubernetes environment. Because in such usage, we cannot change the variables as we want.
We can also use it this way without defining different variable names. So how do we define it in the deployment.yaml file? For this, just before deployment. Let’s replace the environment part that we added to our yaml file with the following;
env: {{- toYaml .Values.environments | nindent 12 }}
With this definition, we can take all environments defined under .Values.environment and define them in our deployments.yaml file. In fact, if you run the kubectl edit deployment demo command when the chart is run, you can see that it is defined as follows;
spec: containers: - env: - name: text_message value: Hi from Helm Chart ^^ - name: baska_bir_env value: baska bir deger image: dturan/echo-server:latest
5.2 Access to the Application
Now that we have defined our variables, we can run the chart. First of all, let’s set up our application to our cluster with the following command;
$ helm install demo .
After installation, we can check if the container is ready with kubectl get pods.
If the container appears as 1/1 Running, we can access the service from our environment with the following command;
$ kubectl port-forward demo-xxxxxxxxxx-xxxxx 8080:80
Then, when we go to localhost:8080 from our browser, we should encounter a JSON like the one below;
{ "CONTAINER": "demo-5c5559755c-vg9xx", "DATE": "Mon, 17 Jan 2022 00:00:00 GMT", "IP ADDRESS": "10.42.0.18", "TEXT": "Hi from Helm Chart ^^" }
We have successfully seen the variable we defined above in the field specified with TEXT. Now our application is ready. 🙂
Happy Helming!
Author: Doğukan Turan
Date Published: Feb 1, 2022
