All About Helm, The K8s Package Manager
Tags: kubernetes, beginners, opensource, devops
Published: 2022-02-08 06:16:08

[Helm](https://helm.sh) is one of the most powerful and community adopted Kubernetes Package manager used in industry. It is used to install and manage all the Kubernetes application. In laymen language, think of it as `npm` or `pip` for Kubernetes. Helm deploys all the k8s applications in a packaging format called helm charts. It is used to install, upgrade, delete even the most complex Kubernetes applications. Now let's try to understand why do we even need helm charts at the first place?

## Need of Helm Charts
Kubernetes provides a command line utility called, `kubectl` which is efficient enough to deploy, inspect, update, delete, your Kubernetes resources. All the k8s resources are defined in YAML files and can be deployed, update, etc by using `kubectl`. But then why the hell we need helm charts? Let's try to understand this with an example.

For instance you have a Kubernetes application which have different resources say, deployment, service, service account, role, role-binding, configmap, secret and ingress. Now we need to deploy all these resources in our cluster. Either we can use `kubectl apply -f Yamls` command to deploy all resources present in `Yamls` directory, or we can use helm charts. If we are using yamls, then for any new resource, we need to create a new yaml file and then deploy it. In this case, eventually we will have to write multiple yaml files, each for different resource. But this is not the case with helm charts.

Helm charts packages all the different resources of your k8s application in an organized way. It contains a directory called `templates` where all the different resources are defined which needs to be deployed. The environment variables and deployment-specific parameters are extracted out and put in a separate file called `Values.yaml` which can be configured every-time you deploy the chart. The advantage of doing so is that you can deploy it to different clusters and even in different environments say, development, staging or production environment without creating the whole chart again.

So, this one of the major advantage of using helm. If you still have doubts, don't worry. We will create a chart from scratch and deploy it on a k8s cluster.

## Getting Started
Installing and creating helm charts are quite straight-forward. You can always refer to their [installation-docs](https://helm.sh/docs/intro/install/) for installation as they provide a rich documentation to install helm in different distributions. For this example, we will be using script to install helm. Please execute the below commands -
- First we need to download the script in our machine
```bash
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
```
- Now we need to give execute permission to the shell script
```bash
chmod 700 get_helm.sh
```
- Finally need to execute it which will install helm in your system
```bash
./get_helm.sh
```
Great. We are done with installing helm in our system. To verify the installation please run - `helm version --short`
![helm-version](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cfhlsb57bfnmb023bgxz.jpg)
If you could see the version, the installation is successful.

### Create Your First Helm Chart
As we have successfully installed helm in our system, its time to create our own helm chart and deployed a Kubernetes application. We will be creating a chart for a simple go application which can be cloned from [here](https://github.com/devtron-labs/demo-go-app.git). 
**[Note: In this blog, I will not be demonstrating how to wrap the application in an image using Dockerfile. Rather I will use an image which I created before and can be accessed from [here](https://hub.docker.com/r/alex43/go-demo-app/tags)]**
Now let's begin with the hands-on part and create our first helm chart. Please follow the steps below -

**Step-1:** Helm is efficient enough to provide you with the basic template to begin with. To create the template, execute -
```bash
helm create demo-go-app
```
It will create a helm chart named `demo-go-app` which contains the basic configuration files & directories in the helm syntactical order as you can see in the below image.
![helm-create](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/22cc3tq5j09q02ary00u.jpg)
Let's understand the files & directories created by-default

|Key | Description|
|----|------------|
|Chart.yaml| The file contains the information of your chart|
|chart| Its an empty directory which may contain any dependent charts if you have|
|templates| The directory contains all the yaml files needs to be deployed|
|tests| It contains files used for testing|
|values.yaml| This file contains the values which needs to be given while installation|

**Step-2:** Now you can add/remove the files which you don't need for your application. In our case let's delete chart dir, tests dir, ingress.yaml and hpa.yaml as we don't need these for our demo.
![rm-command](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cb9gk60yy7cb3f13l5sf.jpg)

**Step-3:** Now we need to provide the image where our application has been wrapped and needs to be deployed. In our case as I already mentioned above, we already have our application wrapped in an image and pushed in [public container registry](https://hub.docker.com/r/alex43/go-demo-app/tags), so I will be using it. 
Feel free to use it if you don't have your own image. One of the benefits of helm charts as we discussed, we just need to make changes in our `values.yaml`, which contains the parameters extracted from all the resources which we want to deploy. In the files, we just have to add our own image details and we are done with the bare min config to deploy our application. In the default `value.yaml` file, there are a lot different parameters which can be tweaked as per our requirements. As you can see an extract of few parameters from values.yaml, where I have just manipulated the image details and added `fullnameOverride`, rest everything goes default.
```bash
replicaCount: 1

image:
  repository: alex43/go-demo-app
  pullPolicy: IfNotPresent
  # Overrides the image tag whose default is the chart appVersion.
  tag: "v1.0"

imagePullSecrets: []
nameOverride: ""
fullnameOverride: "go-app"
```
Now you can make these changes and save the file.

**Step-4:** Since we are ready with the necessary changes, now we can install our chart. To install the chart in default namesapce we can use the following command.
```bash
helm install go-app demo-go-app/
```
If we want to install the chart in specific namespace, we can use the following command. It will create a new namespace and will install the chart in that namespace. If the namespace already exists, we can omit the `--create-namespace` parameter
```bash
helm install go-app demo-go-app --create-namespace --namespace helm-app
```
To verify weather the helm app has been created or not, we can simply use the following command with the namespace where it was installed as you can see in the below image.
```bash
helm list -n helm-app
```
![helm-install](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/py7nfldv6wqdtkupa2bq.jpg)

Now we have successfully installed/deployed our k8s application with helm chart. Now let's play a bit around helm chart. In the `values.yaml`, let's say, if we want to add some more parameters which we want to configure while installation or upgrading the chart, we can easily do that. From `deployment.yaml`, for instance we want to make `containerPort: 80` a generic parameter by passing it in `values.yaml` file so that it can be changed or updated while installation. To pass any value, we need to grab the values by using the syntax - `{{ .Values.<AttributeNameGiven_in_Values.yaml> }}`
- Add a parameter in values.yaml file say,
```
port:
  containerPort: 80
```
- Now add the following in the `containerport` parameter in your `deployment.yaml` so that it can receive the values passed through `values.yaml`
```
ports:
 - name: http
   containerPort: {{ .Values.port.containerPort }}
   protocol: TCP
```
Now if you want to check if the Values you added is properly working or not, you can render the chart locally by using the below command. It will render all the templates with values given in `values.yaml`. This is mostly used to debug and test your custom created helm charts.
```bash
helm template --debug demo-go-app/
```
The output would look like something in the below image if there isn't any error.
![helm-template-debug](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xewd2qplux5ezi4ql4bc.jpg)

The advantage of doing so is that, we can override the values while installing or upgrading the chart just by using a parameter called `--set`. Lets upgrade the chart which we have installed. 
```bash
helm upgrade go-app demo-go-app/ --set port.containerPort=8080 -n helm-app
```
The command will update the installed chart and will also update the `REVISION` automatically as you can see in the below image.
![helm-upgrade](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lrej5c2y4tevwimb4y77.jpg)
Similarly, we can update any parameter passed in `values.yaml` file while installation or upgradation. Now if we want to access our deployed application, just copy-paste the commands given in `NOTES` section after upgrading the chart. It will port-forward the port number `8080` of your localhost to the container port you have given. In our case we set it to 8080 so the output would look something like the below image.
![port-forward](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l31l6nvsget7t8ig0wyz.jpg)

Now if you visit `127.0.0.1:8080/`, you would be able to see your application. In my case, I have given an endpoint `layout.html` so I will be able to see my application at the given endpoint as you can see in the image below.
![deployed-app](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cbygd43b8f9sgkbyvz7u.jpg)

So this was all about helm, and how you can create your own helm charts and deploy over k8s. Now if you want to delete the chart installed, simply execute the below command. It will delete all the resources it created along with it.
```bash
helm delete go-app -n helm-app
```
Since we are familiar with the helm chart concepts, let's talk a bit about its advantages and some of its challenges.

### Advantages of Helm Charts
- Can package complex applications to deploy over k8s
- Easy to get started with per-defined templates
- Can use nested helm charts as dependencies
- Values can be overridden while installation and you don't have to create helm charts for different environments
- Just one click away for deploying all the resources of a k8s application
- Helm by-default maintains the database of REVISIONs (version) providing an ease to rollback if something goes wrong
- Easy collaborations among team and scalability

### Challenges with Helm Charts
- It can easily package complex applications, but creating a helm chart for complex applications is itself quite complex
- Troubleshooting and debugging is quite difficult in helm for complex applications as it uses templates for different resources
- It doesn't provide any UI to manage applications deployed through helm. In scenarios where 100s of helm charts are deployed, it would be very difficult to manage helm apps.

## So What next, Introducing Hyperion
In the blog, we have talked about helm, its requirements, creating helm charts, its advantages and some of its challenges. To overcome its challenges and sustain the originality of helm, let me take the pleasure to introduce you to a tool called [`Hyperion`](https://docs.devtron.ai/hyperion/hyperion). It is one of its rare kind open source tool where you can easily look for all the helm charts deployed on a cluster through an intuitive dashboard. Hyperion is a lightweight in nature packed with full-fledged debugging features for your Kubernetes workloads. To know more about it, feel free to install & explore Hyperion and let me know your views through comments. I am working on a dedicated blog for Hyperion which will be releasing soon.

{% github devtron-labs/devtron no-readme %}