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