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
GitHub example repo used for test deployment, google-hello-app-logging-multiarch