Using Helm with GitOps
Tags: gitops, helm, argocd, kubernetes
Published: 2021-09-30 15:15:45

<span style="font-weight: 400;">This is the first of many posts highlighting GitOps topics that we’ll be exploring. Within this post, we will explore Helm, a tool used for Kubernetes package management, that also provides templating. Helm provides utilities that assist Kubernetes application deployment.</span>

<span style="font-weight: 400;">In order to better understand how Helm charts are mapped to Kubernetes manifests, we’ll explain more details below and how to use Helm with and without GitOps.</span>
<h2>What is Kubernetes?</h2>
<a href="https://kubernetes.io/"><span style="font-weight: 400;">Kubernetes</span></a><span style="font-weight: 400;"> is an orchestrator for containers that allows you to automate scheduling, deployments, networking, scaling, and health monitoring for the containers.</span>

<span style="font-weight: 400;">Kubernetes was needed because we increased the usage of the following:</span>
<ul>
 	<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Microservices</span></li>
 	<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Containers</span></li>
</ul>
<span style="font-weight: 400;">This was difficult to manage with scripts and self-made tools and caused the need for orchestration technology like Kubernetes. It provides features like scalability, disaster recovery, and less downtime.</span>
<h2>What is Helm?</h2>
<a href="https://helm.sh/"><span style="font-weight: 400;">Helm</span></a><span style="font-weight: 400;"> is a package manager for Kubernetes. It’s a convenient way for packaging collections of YAML files with a Helm chart for the Kubernetes application and allowing distribution with a Helm repository. </span>

<span style="font-weight: 400;">Maintaining Kubernetes manifests is time-consuming and tedious and this is why Helm is helpful!</span>
<h4>Helm Charts</h4>
<span style="font-weight: 400;">Helm Charts are deployable units for Kubernetes applications. These charts are a collection of files inside a directory. This directory is the name of the Helm chart and consists of a self-descriptor file, YAML file, and one or more Kubernetes manifests. Helm charts are typically written in the </span><a href="https://pkg.go.dev/text/template"><span style="font-weight: 400;">Go template language</span></a><span style="font-weight: 400;">. Charts are created as such files, describing a related set of Kubernetes resources. Here’s an example of a Helm chart directory and it’s layout:</span>

<a href="https://codefresh.io/wp-content/uploads/2021/09/helm-chart-example.png"><img class="alignnone wp-image-20292 size-full" src="https://codefresh.io/wp-content/uploads/2021/09/helm-chart-example.png" alt="" width="280" height="257" /></a>

<span style="font-weight: 400;">This particular directory contains a </span><span style="font-weight: 400;">Chart.yaml</span><span style="font-weight: 400;"> file and this is where the global variables, versions, and descriptions are stored. Then, the templates directory is what contains the YAML files for Kubernetes, otherwise known as the Kubernetes manifests.</span>

<span style="font-weight: 400;">Files such as the </span><span style="font-weight: 400;">deployment</span><span style="font-weight: 400;">, </span><span style="font-weight: 400;">service</span><span style="font-weight: 400;">, and </span><span style="font-weight: 400;">ingress</span><span style="font-weight: 400;"> files contain variables from the </span><span style="font-weight: 400;">values.yaml</span><span style="font-weight: 400;"> file when the chart is deployed. The </span><span style="font-weight: 400;">_helpers.tpl</span><span style="font-weight: 400;"> incorporates helpful functions for variable calculations.</span>

<span style="font-weight: 400;">You can then share the Helm chart to increase easy reusability for others to use. Sharing is done by storing the chart to a Helm repository. This repository can then be shared with others to deploy the application with the chart.</span>
<h4>Helm Repositories</h4>
<span style="font-weight: 400;">Helm supports a chart repository service that can be used to store the Helm charts. You can use any web server host or source code host for the Helm repository.</span>

<span style="font-weight: 400;">The repository has an </span><span style="font-weight: 400;">index.yaml</span><span style="font-weight: 400;"> file that contains metadata about the package, including the </span><span style="font-weight: 400;">Chart.yaml</span><span style="font-weight: 400;"> file. The index will contain information about each Helm chart in the chart repository. Then the server can serve your index and charts or the packages can be stored in the repository for shareable access.</span>
<h4>Helm Release</h4>
<span style="font-weight: 400;">Each install or upgrade will create a Helm release. A Helm release is a running instance of your Helm chart running within a Kubernetes cluster or a namespace. It’s essentially an instance of a versioned, templated chart. </span><span style="font-weight: 400;">It’s also possible to have multiple releases of the same chart in a single cluster or namespace since the chart is self-contained. You can also roll back a Helm release to a previous version in case there are any failures.</span>

<a href="https://codefresh.io/wp-content/uploads/2021/09/Helm-WF.png"><img class="alignnone wp-image-20293 size-large" src="https://codefresh.io/wp-content/uploads/2021/09/Helm-WF-1024x632.png" alt="" width="1024" height="632" /></a>

<span style="font-weight: 400;">Assuming you’re a developer with an existing cluster, perhaps you’d like to share your Helm application with an external vendor. Let's recap the Helm workflow and release process:</span>
<ol>
 	<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">To share an application with others, you need to create a Helm chart. The chart is a package that contains templates for a set of resources necessary for the application. The template uses variables applied to the </span><span style="font-weight: 400;">Values.yaml</span><span style="font-weight: 400;"> file when the manifest is created and describes how to configure the resources.</span></li>
 	<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">The Helm charts are then hosted within a repository that can then be downloaded or accessed from a server. This chart will contain all the necessary resource definitions needed for the developer to run an application.</span></li>
 	<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Now that you have access to the cluster, you can add new features or bug fixes to the application and update the Helm chart. Helm offers useful tools to manage your releases. You can upgrade the chart and create a new deployment. In Helm a deployed instance of your application is referred to as the release. </span></li>
 	<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">You can now deploy your packaged application to the cluster.</span></li>
</ol>
<span style="font-weight: 400;">Within this workflow we identified how Helm packages files and deploys them to a cluster. So, how do you apply GitOps to the workflow above? Let’s explore this below...</span>
<h2>What is GitOps?</h2>
<a href="https://codefresh.io/gitops/"><span style="font-weight: 400;">GitOps</span></a><span style="font-weight: 400;"> is a paradigm that incorporates best practices applied to the application development workflow all the way to the operating infrastructure of a system.</span>

<span style="font-weight: 400;">Some benefits of GitOps are:</span>
<ul>
 	<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Deploying faster and more often</span></li>
 	<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Easier and quicker error handling and recovery</span></li>
 	<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Self documenting deployments</span></li>
 	<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Increased developer productivity and an enhanced experience for teams</span></li>
 	<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Greater visibility on the lifecycle of developed features</span></li>
</ul>
<span style="font-weight: 400;">These benefits make it easier to handle the applications and allow teams to deliver quality software faster.</span>

<span style="font-weight: 400;">GitOps relies on Git as the single source of truth for declarative configuration and active reconciliation. By adopting the GitOps methodology it provides transparency between the application configuration deployed in a cluster and the one residing in Git. </span>

<span style="font-weight: 400;">A GitOps tool that follows this approach of a Git-based workflow is Argo CD. It’s a continuous delivery tool for Kubernetes that is essentially a GitOps controller that does two-way synchronization. Argo continuously monitors running applications and compares the live state against the desired state in Git and applies it to the cluster. In addition, it also monitors the container registry for new images and updates the workload definitions based on the deployment policies.</span>

<span style="font-weight: 400;">We will mention Argo CD again in this post and can assume that it’s already been installed and implemented within our workflow!</span>
<h2>GitOps works with all of your existing tools</h2>
<span style="font-weight: 400;">Now that you have a good understanding of what Helm is and it’s capabilities, perhaps you’ve considered applying GitOps to your existing or future applications.</span>

<span style="font-weight: 400;">Let’s explore the various approaches of how to use GitOps with or without Helm:</span>
<ol>
 	<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Using only Helm (without GitOps)</span></li>
 	<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Using GitOps (without Helm)</span></li>
 	<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Using Helm with GitOps</span></li>
</ol>
<span style="font-weight: 400;">If you’d like to explore these different approaches from a code-base perspective, here is an </span><a href="https://github.com/codefresh-contrib/helm-gitops-example/blob/main/README.md"><span style="font-weight: 400;">example project</span></a><span style="font-weight: 400;"> that you should check out on GitHub that digs deeper into how you can:</span>
<ul>
 	<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Install an application with Helm and deploy locally</span></li>
 	<li style="font-weight: 400;" aria-level="1"><span style="font-weight: 400;">Install an application with Argo CD and deploy locally both within the UI and command line</span></li>
</ul>
<span style="font-weight: 400;">If not, then we’ll be sure to highlight these approaches below!</span>
<h4>Approach #1: Using only Helm without GitOps</h4>
<span style="font-weight: 400;">If you want to use Helm but your organization isn’t quite ready to implement the GitOps workflow, that’s perfectly fine. Helm was created before the GitOps methodology came to fruition, but can still work with GitOps (as we will see in the latter point).</span>

<span style="font-weight: 400;">The workflow allows you to search through Helm repositories for charts and install them to clusters, creating releases. This process enables execution of application deployments on a cluster. The maintenance of YAML manifests for Kubernetes objects is still the same as before. Helm releases are what keeps track of the version history of each chart installation and change and still allows rolling back to the previous cluster version. When installing a chart it creates a release of the new package and it’s the Helm release that deploys the Helm application.</span>

<span style="font-weight: 400;">When using Helm there are some powerful commands you will find useful, please see below.</span>

To install a new package:

```helm install <release_name> <name_of_chart_you_want_to_install>```

To view currently deployed releases:
```helm list```
or
```helm ls```

To view revision numbers for a particular release:
```helm history <release_name>```

<span style="font-weight: 400;">To learn more details about these commands and how to use them, reference the </span><a href="https://github.com/codefresh-contrib/helm-gitops-example/blob/main/README.md"><span style="font-weight: 400;">example project</span></a><span style="font-weight: 400;"> in GitHub.</span>
<h4>Approach #2: Using GitOps without Helm</h4>
<span style="font-weight: 400;">If you’re sold on the idea of GitOps, there are alternative tools that can be used if you’re unable to use Helm or choose not to. </span>

<span style="font-weight: 400;">You can use ArgoCD on its own. It is pretty flexible and can work with other templating solutions or even plain manifests. </span><span style="font-weight: 400;">Another templating tool that can be used instead of Helm is </span><a href="https://kustomize.io/"><span style="font-weight: 400;">Kustomize</span></a><span style="font-weight: 400;">. This tool is built into </span><span style="font-weight: 400;"><code>kubectl</code></span><span style="font-weight: 400;"> and is native to Kubernetes. It allows you to customize Kubernetes configurations using only the Kubernetes API resource files.</span>

<span style="font-weight: 400;">Now, let’s explore our third approach about how to implement GitOps using Helm and Argo CD...</span>
<h4>Approach #3: Using Helm with GitOps</h4>
<span style="font-weight: 400;">Now that you’ve seen how GitOps can be applied without Helm, let’s explore how you can use it with Helm. </span>

<span style="font-weight: 400;">First, the Helm chart and any application changes must be committed in Git prior to being applied to the cluster. Meaning all of your workload definitions in a YAML format, the Helm charts, and any other Kubernetes custom resources that define the cluster’s desired state must be committed to the repo. This way rollbacks and logs are accessible and the state of production can be restored easily.</span>

<span style="font-weight: 400;">Within Argo CD you can connect the Git repository using HTTPS and add the URL directly. This then allows you to enable auto-synchronization to automatically synchronize the cluster to the desired state in the Git repository. Once synced successfully, the application status is recognized as Healthy. Otherwise, if the application is OutOfSync, you can rollback or view the release history to resolve the issue.</span>

<span style="font-weight: 400;">Here’s an example of a Healthy application in the Argo CD UI.</span>

<a href="https://codefresh.io/wp-content/uploads/2021/09/HelmGitOpsArgoUI.png"><img class="alignnone wp-image-20301 size-large" src="https://codefresh.io/wp-content/uploads/2021/09/HelmGitOpsArgoUI-1024x455.png" alt="" width="1024" height="455" /></a>

<span style="font-weight: 400;">When the application is running you can view its resource components, logs, events, and the health status.</span>

<span style="font-weight: 400;">For good measure, here’s a visual of the Argo CD UI exemplifying an OutOfSync application when the live state deviates from the target state.</span>

<a href="https://codefresh.io/wp-content/uploads/2021/09/OutOfSyncArgoUI.png"><img class="alignnone wp-image-20303 size-full" src="https://codefresh.io/wp-content/uploads/2021/09/OutOfSyncArgoUI.png" alt="" width="1764" height="742" /></a>

<span style="font-weight: 400;">If your application had an error or was OutOfSync like the example above, you could execute the argo history command that allows you to view the application deployment history:</span>
```argocd app history <argocd_app_name>```

Then, if you need to rollback the deployment you can do so by executing this command:
```argocd app rollback <argocd_app_name> <history_id>```

Essentially, these commands leverage a faster and more secure deployment, by enabling the tracking from the Git repository. It also allows you to track the active Kubernetes resources and events.

<span style="font-weight: 400;">Therefore, using source control like this is what classifies this application deployment as GitOps!</span>

<span style="font-weight: 400;">Something important to note is that Argo CD provides native support for Helm, meaning you can directly connect a packaged Helm chart and Argo CD will monitor it for new versions. When this takes place the Helm chart will no longer function as a Helm chart and instead, is rendered with the Helm template when Argo is installed, using the Argo CD application manifest.</span>

<span style="font-weight: 400;">Argo CD then deploys and monitors the application components until both states are identical. The application is no longer a Helm application and is now recognized as an Argo app and can only operate by Argo CD. Hence if you execute the </span><span style="font-weight: 400;">helm list</span><span style="font-weight: 400;"> command, you should no longer be able to view your </span><span style="font-weight: 400;">helm release</span><span style="font-weight: 400;"> because the Helm metadata no longer exists.</span>

<span style="font-weight: 400;">Here’s an example of the command output. As you can see, the Argo CD application is NOT detected as a Helm application.</span>

<a href="https://codefresh.io/wp-content/uploads/2021/09/Empty-Helm-List.png"><img class="alignnone wp-image-20309 size-full" src="https://codefresh.io/wp-content/uploads/2021/09/Empty-Helm-List.png" alt="" width="727" height="65" /></a>
<h2>Summary</h2>
<span style="font-weight: 400;">Helm is a powerful tool that is used often with Kubernetes deployments and provides tracking for each release. This helps ensure reliable and quick deployments for development teams. </span>

<span style="font-weight: 400;">So, if you’re completely new to Helm, I suggest referring to our documentation to learn more about it, here: </span>
<ul>
 	<li style="font-weight: 400;" aria-level="1"><a href="https://codefresh.io/helm-tutorial/helm-deployment-environments/"><i><span style="font-weight: 400;">Helm Deployment Environments</span></i></a></li>
 	<li style="font-weight: 400;" aria-level="1"><a href="https://codefresh.io/docs/docs/new-helm/helm-best-practices/"><i><span style="font-weight: 400;">Helm Best Practices</span></i></a></li>
 	<li style="font-weight: 400;" aria-level="1"><a href="https://codefresh.io/helm-tutorial/simplify-kubernetes-helm-deployments/"><i><span style="font-weight: 400;">How to Simplify your Kubernetes Helm Deployments</span></i></a></li>
</ul>
<span style="font-weight: 400;">We'll discuss additional tools in our next post that can help you and your team continue implementing a GitOps process to your development and infrastructure systems.</span>