Posted on

Managing a Kubernetes cluster with Helm and FluxCD

As seen in my previous article, after successfully setting up a Kubernetes Cluster you can install applications on it using the Helm CLI. This is convenient to get started but might not scale well with multiple people administering the cluster.

To make collaboration easier and avoid making mistakes by simply mistyping Helm commands, it is recommended to adopt a GitOps workflow. This consists of using Git to version control the state of the cluster. In this article, I will explain how to use FluxCD to achieve this.

An actual helm
Illustraton by Loik Marras

Getting started with FluxCD

First of all, make sure you have a running Kubernetes cluster and have installed kubectl and helm. Then you will need to create a Git repository at your favorite provider (GitHub, Bitbucket, etc…). Once this is done, clone it locally and create a releases folder inside of it. This folder will contain the files defining your Helm releases (a release is an instance of a chart running on a cluster).

Let’s start by creating a release for my favorite IRC client, The Lounge. To do this, create a file in releases/thelounge.yaml containing the following data:

---
apiVersion: helm.fluxcd.io/v1
kind: HelmRelease
metadata:
  name: thelounge
  namespace: default
  annotations:
    fluxcd.io/automated: "false"
    fluxcd.io/tag.chart-image: semver:~4.0
spec:
  releaseName: thelounge
  chart:
    repository: https://halkeye.github.io/helm-charts/
    name: thelounge
    version: 4.3.0
  values:
    ingress:
      enabled: true
      hosts:
        - YOUR.OWN.DOMAIN

This will be using the chart available on Artifact Hub, and the software will be running on the default namespace, and we ask for an ingress to be created. Don’t forget to commit and push the release!

After creating this repository, you should install FluxCD on your cluster. To do this simply run the following commands:

helm repo add fluxcd https://charts.fluxcd.io

kubectl apply -f https://raw.githubusercontent.com/fluxcd/helm-operator/master/deploy/crds.yaml

kubectl create ns flux

helm upgrade -i flux fluxcd/flux \
   --set git.url=git@github.com:[USERNAME]/[REPO] \
   --set git.branch=[BRANCH] \
   --namespace flux

helm upgrade -i helm-operator fluxcd/helm-operator \
  --set git.ssh.secretName=flux-git-deploy \
  --set helm.versions=v3 \
  --namespace flux

You should now see 3 pods running in the flux namespace:

flux-memcached-869757cb88-77br8 1/1 Running 0 100s
flux-59cb4447b9-thpr9 1/1 Running 0 101s
helm-operator-686dc669cd-g8kn7 1/1 Running 0 89s

Finally, you will need to give read and write access to your git repository to FluxCD. To do this, install fluxctl and run:

fluxctl identity --k8s-fwd-ns flux

This will print an RSA key that needs to be added as a deploy key to your repository. For GitHub users, go to https://github.com/YOURUSERNAME/YOURUSER/settings/keys/new to add the key (tick the give write access checkbox).

Your release should start getting installed on your cluster soon. You can check the state of your helm releases by running

kubectl get hr

If needed, you can check the FluxCD logs with

kubectl -n flux logs deployment/flux -f

If you want to manually trigger FluxCD to re-read your git repository, use the command:

fluxctl sync --k8s-fwd-ns flux
A compass
Illustraton by AbsolutVision

Adding your charts

Of course, you might not be able to do exactly what you want using the charts publicly available. FluxCD allows you to add your charts directly through Git.

First, create a charts directory. Inside this directory, run the following command to create a chart named mychart:

helm create mychart

This will generate a sample chart defining everything that’s required to launch an Nginx server in production. To run this chart, you will have to define a release for it in your releases folder:

---
apiVersion: helm.fluxcd.io/v1
kind: HelmRelease
metadata:
  name: myrelease
  namespace: default
  annotations:
    fluxcd.io/automated: "false"
    fluxcd.io/tag.chart-image: glob:3.1.1-debian-9-*
spec:
  releaseName: myrelease
  chart:
    git: ssh://git@github.com/[USER]/[REPO]
    ref: [BRANCH]
    path: charts/mychart
  values:
    ingress:
      enabled: true
      hosts:
        - host: YOUR.OTHER.DOMAIN
          paths: ["/"]

Like in the previous example, don’t forget to git commit and git push. FluxCD will automatically create the new release and you will see a magnificent Nginx welcome page appear at the specified domain.

To be able to display something else than the Nginx welcome page, we will give it a configuration file. For this purpose, you can define a configmap in charts/mychart/templates/configmap.yaml. The following config will redirect every request to a URL of our choice:

apiVersion: v1
kind: ConfigMap
metadata:
  name: nginx-conf
data:
  nginx.conf: |
    events {
      worker_connections  1024;
    }
    http {
      server {
          listen 80 default_server;
          return 301 {{ .Values.redirect }};
      }
    }

You will then need to declare the volume by adding this value to spec.template.spec in charts/mychart/templates/deployment.yaml:

      volumes:
      - name: nginx-conf
        configMap:
          name: nginx-conf

To mount the configuration file into the Nginx container, you need to add the following lines to spec.template.spec.containers[0] in the same file:

          volumeMounts:
          - mountPath: /etc/nginx/
            readOnly: true
            name: nginx-conf

Finally, bump the version in charts/mychart/Chart.yaml, and set the redirect URL in releases/myrelease.yaml by editing the values section like this:

  values:
    ingress:
      enabled: true
      hosts:
        - host: YOUR.OTHER.DOMAIN
          paths: ["/"]
    redirect: "https://www.youtube.com/watch?v=cFVF26XPcAU"

Dive deeper

As this article only really scratches the surface of what Helm and FluxCD can do, I recommend you to also check out the official FluxCD docs and their example repository, as well as the Helm Chart Template Developer’s Guide.

The source code for the examples shown in this article is available on GitHub.