Skip to main content

GitOps with Helm

In the Deploy new application Tutorial we learned how to create an Argo CD application in order to listen for kubernetes manifest changes within a git repository. Argo CD also supports other inputs then direct kubernetes manifest yaml files. For example Kustomize, Jsonnet or the well known templating tool Helm.

What is Helm

Helm is a package manager specifically designed for Kubernetes applications. It simplifies the deployment, management, and sharing of complex applications within a Kubernetes cluster.

note

We recommend using helm as a templating tool and ignore its packaging capabilities and rollout features. Instead we want to use GitOps principles again and use Argo CD to deploy an application templated as a Helm Chart.

Here's how Helm helps:

  • Packaging: Helm Charts package all the resources needed for an application (configuration files, deployments, secrets, etc.) into a single unit. This makes deployments consistent and repeatable.
  • Configuration: Helm Charts can be customized with values, allowing you to tailor deployments to specific environments without modifying the core application code.
  • Sharing and Reuse: Helm Charts are easily shared and reused, promoting consistency and collaboration within teams. Public Helm repositories provide readily available charts for popular applications.

Templating kubernetes manifests

In essence, Helm streamlines the process of working with Kubernetes applications by providing a standardized way to package, configure, and deploy them. The most powerful feature for us is the fact that a values.yaml file can be used to replace values in helm templates to generate dynamically configured kubernetes manifests.

Example template for a deployment

Helm uses a strict folder structure for creating Charts/templates. In most cases it is recommended to have the chart either in the same repository as the application and create an Argo CD application that will sync the chart from the application repository with the Rocket Pad Platform cluster. At the same time the Argo CD application can be used to configure the deployment trough the variables defined with the Helm template. This allows for multiple rollouts of the same chart with different configurations, which is important when we want to have multiple instances of an application on different domain names or connected to different databases for example.

1. Create Helm Chart template

Helm needs to have a strict folder structure with specific files named a specific name. This can be achieved by using the Helm cli tool and create a new chart for templating with helm create my-chart. We recommend doing so but it will create a bunch of complex configuration and templating for you, which can be overwhelming when starting to learn Helm. Therefore we will create the bare minimum example in this tutorial to get the basics down and deploy our first application with a Helm Chart.

The folder structure we need to create is as follows. We recommend putting this folder structure under a folder named /chart within your application repository:

chart/
Chart.yaml
values.yaml
charts/
templates/
...

Create the simple folder structure within the /chart folder and fill it with the example code below. We will further explain what each part does in the later steps.

/chart/Chart.yaml
```yaml title="/chart/Chart.yaml"
apiVersion: v2 # Defines the Helm api chart version to use
name: "example-chart" # The name of the chart, not important for templating but required
description: "This is our example chart for templated deployments to {constants.productName}" # A description of the chart
version: 0.1.0 # A version for the chart/template itself. Can also be ignored for templating. We have Git for versioning the chart

The Chart.yaml file configures the chart itself and is mostly used for Charts that will be pushed to a dedicated Helm Chart registry and used with the helm cli rollout functionality and versioned within this Helm Chart registry. For templating alone adn versioning of the chart trough git like we recommend the bare minimum of required configuration in this file is sufficient.

/chart/values.yaml
name: "example"

replicaCount: 1

image: "nginx:latest"

The values.yaml file is the most important file of the Chart. It will allow us to define variables that can be used in the /chart/templates folder to inject values dynamically into our kubernetes manifests we want to configure. Define everything that might be dynamically configured later in this file and set a default value within

/chart/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .values.name }}-deployment
spec:
replicas: {{ .values.replicaCount }}
selector:
matchLabels:
app: {{ .values.name }}
template:
metadata:
labels:
app: {{ .values.name }}
spec:
containers:
- name: {{ .values.name }}
image: {{ .values.image }}

In the /chart/templates folder the kubernetes manifests to rollout into the Rocket Pad Platform cluster can be defined. If you have an application with kubernetes manifest that you want to make configurable through a Helm Chart this is the place where you can copy all the kubernetes manifest you want to apply. It will work out of the box without changing anything. Helm will read the valid kubernetes manifests and just return them un-templated. To make it dynamically configurable replace everything you want to have configurable with a variable and move the value as default into the values.yaml file like it is done in the example above.

Now with the variables defined with defaults in the /chart/values.yaml and used in the manifests inside the /chart/templates your chart is valid again and can again be used as is to generate the exact same outcome as your statically defined manifests before. But now the values can be changed dynamically when using the Helm Chart and replace for example the application name or the image deployed.

2. Using the Chart in an Argo CD application

Now with the chart in place and all configurable values defined as variables the chart can be used to rollout the kubernetes manifest trough an Argo CD application to again have the manifest applied inside the Rocket Pad Platform cluster always in sync with the git repository that defines them.

Exactly as in the deploy new application tutorial an Argo CD application manifest is needed. But this time we will not just link a repository folder with manifest in them but use the Helm Chart option of Argo CD and overwrite the values with new values directly in the Argo CD application:

application.yaml

  apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: <your-application-name>
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
project: default
sources:
- repoURL: <your-git-repository-https-url> # The url of the applications git repository where the chart is saved in.
targetRevision: HEAD # With this the git branch can be set that will be used to listen to
path: chart # Here the path to the chart within the git repository can be set
helm:
valuesObject: # Overwrite Helm Chart values
name: "app" # Use new name for the deployment
image: alpine:latest # Use alpine image for the deployment
replicaCount: 2 # Deploy 2 replicas of the container

destination:
server: 'https://kubernetes.default.svc'
namespace: <your-applications-namespace> # This namespace will be created and all manifests in the path will be applied into this namespace (Overwriting metadata defined namespace names within the manifests themselves)
syncPolicy:
syncOptions:
- CreateNamespace=true
automated:
prune: true
selfHeal: true

Now the application.yaml file can again be placed in your GitOps repository or whatever repository is used by your app of apps pattern to apply new Argo CD applications. If you are not using the app of apps pattern th application.yaml manifest can also be applied using kubectl directly with kubectl apply -f application.yaml.

The now deployed Argo CD application will pull form the defined git repository url and apply the kubernetes manifest defined in the /chart/templates folder within that application git repository. But before they get applied Argo CD will use helm to create new manifest to apply with the defined values replacing all variables defined in your chart and overwritten by the helm.valuesObject map defined in the Argo CD application manifest.

This approach can be used to build and deploy complex systems build out of multiple applications with multiple kubernetes resources and still be dynamically configured by simple values. And the most important benefit is that you can now create a second application.yaml file with another name and other values for the chart in order to rollout the same deployment but with different configuration in another namespace with another name and pulling a different image version for example. And if there is a bugfix within the chart or application code for example it will automatically propagate after a simple git push to all instances deployed with this chart.