Flux: automating Helm chart deployments with Flux

Flux is a GitOps continuous delivery tool that provides a framework for keeping a Kubernetes cluster in-sync with source git repositories, OCI registries, and published Helm charts [1].

In this article, I will show how Flux can deploy a Helm chart, and then subsequently monitor for changes and auto-upgrade when new chart versions are published.

If you have not installed Flux at the cluster-level yet, see my previous article.

Installing the Flux CLI

Below are instructions for install the Flux CLI tool on Debian/Ubuntu.

# ensure json parser is installed
sudo apt install jq -y

# discover latest version of flux available, then fetch/extract
latest_flux_linux=$(curl -sL https://api.github.com/repos/fluxcd/flux2/releases/latest | jq -r ".assets[].browser_download_url" | grep linux_amd64.tar.gz)
wget $latest_flux_linux
tar xvfz $(basename $(echo $latest_flux_linux))
sudo mv flux /usr/local/bin/.

# validate installation
flux --version

Example Helm chart

I have written a previous article describing a GitHub repository that builds a small GoLang web server into a Docker/OCI image and uses a GitHub Action to automatically publish a Helm chart using GitHub Pages.

Changes to the project are published to GitHub Pages, and the Helm repo index.yaml can be found at:

https://fabianlee.github.io/google-hello-app-logging-multiarch

If we wanted to check this published Helm chart from a Helm CLI client, we would use the commands below.

# to validate example Helm chart from CLI
# this is not necessary since the in-cluster Flux will be the client
helm repo add github-hello https://fabianlee.github.io/google-hello-app-logging-multiarch

# show versions of chart available
$ helm search repo -l github-hello
NAME                                           	CHART VERSION	APP VERSION	DESCRIPTION                
github-hello/google-hello-app-logging-multiarch	0.0.4        	1.0.34     	A Helm chart for Kubernetes
github-hello/google-hello-app-logging-multiarch	0.0.3        	1.0.34     	A Helm chart for Kubernetes
github-hello/google-hello-app-logging-multiarch	0.0.1        	0.1.0      	A Helm chart for Kubernetes

In the next section, we will have Flux use this Helm index for installs and watch for subsequent upgrades.

Test Flux Helm chart deployment from published chart

If we want the cluster-level Flux integration to deploy the Helm Chart above, we need to instantiate two Flux custom resource definitions into a new “github-hello-helm” namespace:

  • HelmRepository.source.toolkit.fluxcd.io – defines the URL of the published Helm chart index.yaml
  • HelmRelease.helm.toolkit.fluxcd.io – based on events from the HelmRepository above, runs install or upgrade of helm chart based on regex of allowed versions (e.g. “0.0.*”)
# create target k8s namespace
target_ns=github-hello-helm
kubectl get ns $target_ns || kubectl create ns $target_ns

# get my project that has yaml definitions for flux helm objects
git clone https://github.com/fabianlee/google-hello-app-logging-multiarch.git
cd google-hello-app-logging-multiarch/flux-helm-objects

# create HelmRepository object that watches helm index.yaml for versions available
kubectl apply -f helmrepository.yaml -n $target_ns

# create HelmRelease object that specifies which chart and version to install
# in this case we are pinning to version 0.0.3 of the chart (instead of newest 0.0.4)
kubectl apply -f helmrelease-0.0.3.yaml -n $target_ns

# view status of Flux helm objects
$ kubectl get HelmRepository,HelmRelease -n $target_ns
NAME                                                             URL                                                              AGE   READY   STATUS
helmrepository.source.toolkit.fluxcd.io/github-hello-helm-repo   https://fabianlee.github.io/google-hello-app-logging-multiarch   29m   True    stored artifact: revision 'sha256:958f7e894f89beb7f3d5ec9a9a775f8b33d56e04046e476af99d86d8a4a7d3aa'

NAME                                                   AGE   READY   STATUS
helmrelease.helm.toolkit.fluxcd.io/github-hello-helm   20m   True    Helm test succeeded for release github-hello-helm/github-hello-helm.v1 with chart google-hello-app-logging-multiarch@0.0.3: 1 test hook completed successfully

# wait for reconciliation of release, Ready=true
kubectl wait --for=condition=ready HelmRelease/github-hello-helm -n $target_ns --timeout=60s

# view status of workload deployed by Flux helm objects
$ kubectl get deployment,service -n $target_ns
NAME                                                                   READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/google-hello-app-logging-multiarch   2/2     2            2           3m14s

NAME                                                           TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
service/google-hello-app-logging-multiarch   ClusterIP   10.152.183.73           8080/TCP   3m14s

# validate version of release, which was embedded as environment variable
$ kubectl get deployment google-hello-app-logging-multiarch -n $target_ns -o=jsonpath="{.spec.template.spec.containers[0].env}"
[{"name":"whoami","value":"patch version 3"}]

Test Flux Helm chart auto-upgrades

In the last section, we pinned the Helm chart version to ‘0.0.3’, but if we modify this with a wildcard, we can have Flux watch for newer chart versions and auto-upgrade.

$ grep "version:" helmrelease.yaml 
version: '0.0.*' # any 0.0.x version, helm upgrade executed if newer patch released

# apply new HelmRelease definition that allows charts '0.0.*', which should upgrade chart release to 0.0.4
$ kubectl apply -f helmrelease.yaml -n $target_ns

# wait for reconciliation of release, Ready=true
kubectl wait --for=condition=ready HelmRelease/github-hello-helm -n $target_ns --timeout=60s

# check status
$ kubectl get HelmRelease -n $target_ns
NAME                AGE     READY   STATUS
github-hello-helm   3h38m   True    Helm test succeeded for release github-hello-helm/google-hello-app-logging-multiarch.v27 with chart google-hello-app-logging-multiarch@0.0.4: 1 test hook completed successfully

# environment variable should now reflect newer message
# this is because Flux upgraded the Helm chart
$ kubectl get deployment google-hello-app-logging-multiarch -n $target_ns -o=jsonpath="{.spec.template.spec.containers[0].env}"
[{"name":"whoami","value":"patch version 0.0.*"}]

Test Flux Helm chart deployment from chart source

There is an alternative to reading a Helm chart from a publicly published index.yaml and chart package (tgz).  You can also point Flux at a git repository and path that contains a chart.   Flux can install the chart directly from source, as well as upgrade when changes to the chart are made.

# create target k8s namespace
target_ns=github-hello-helm-src
kubectl get ns $target_ns || kubectl create ns $target_ns

# create GitRepository object that watches 'charts/' directory for changes
kubectl apply -f gitrepository.yaml -n $target_ns

# create HelmRelease object that specifies path of chart files
kubectl apply -f helmrelease-from-gitrepo.yaml -n $target_ns

# view status of Flux helm objects
$ kubectl get GitRepository,HelmRelease -n $target_ns
NAME                                                           URL                                                               AGE   READY   STATUS
gitrepository.source.toolkit.fluxcd.io/github-hello-git-repo   https://github.com/fabianlee/google-hello-app-logging-multiarch   32m   True    stored artifact for revision 'main@sha1:eb4098665daebb25f664f75c8ab5ee87c2306e58'

NAME                                                   AGE   READY   STATUS
helmrelease.helm.toolkit.fluxcd.io/github-hello-helm   27m   True    Helm test succeeded for release github-hello-helm-src/google-hello-app-logging-multiarch.v2 with chart google-hello-app-logging-multiarch@0.0.5: 1 test hook completed successfully

# wait for reconciliation of release, Ready=true
kubectl wait --for=condition=ready HelmRelease/github-hello-helm -n $target_ns --timeout=60s

# view status of workload deployed by Flux helm objects
$ kubectl get deployment,service -n $target_ns
NAME                                                 READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/google-hello-app-logging-multiarch   2/2     2            2           24m

NAME                                         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/google-hello-app-logging-multiarch   ClusterIP   10.152.183.170           8080/TCP   24m

# validate version of release, which was embedded as environment variable
$ kubectl get deployment google-hello-app-logging-multiarch -n $target_ns -o=jsonpath="{.spec.template.spec.containers[0].env}"
[{"name":"whoami","value":"using src with patch version 0.0.*"}]

 

 

REFERENCES

Flux site

Flux, Helm Controller concept

Flux, HelmReleases

Flux, managing Helm releases

GitHub example repo used for test deployment, google-hello-app-logging-multiarch