If you have ever deployed applications to Kubernetes or other platforms, you are probably used to the following approach:
- developers check in code which triggers CI (continuous integration) and eventually results in deployable artifacts
- a release process deploys the artifacts to one or more environments such as a development and a production environment
In the case of Kubernetes, the artifact is usually a combination of a container image and a Helm chart. The release process then authenticates to the Kubernetes cluster and deploys the artifacts. Although this approach works, I have always found this deployment process overly complicated with many release pipelines configured to trigger on specific conditions.
What if you could store your entire cluster configuration in a git repository as the single source of truth and use simple git operations (is there such a thing? 😁) to change your configuration? Obviously, you would need some extra tooling that synchronizes the configuration with the cluster, which is exactly what Weaveworks Flux is designed to do. Also check the Flux git repo.
In this post, we will run through a simple example to illustrate the functionality. We will do the following over two posts:
- Create a git repo for our configuration
- Install Flux and use the git repo as our configuration source
- Install an Ingress Controller with a Helm chart
- Install an application using standard YAML (including ingress definition)
- Update the application automatically when a new version of the application image is available
Let’s get started!
Create a git repository
To keep things simple, make sure you have an account on GitHub and create a new repository. You can also clone my demo repository. To clone it, use the following command:
git clone https://github.com/gbaeke/gitops-sample.git
Note: if you clone my repo and use it in later steps, the resources I defined will get created automatically; if you want to follow the steps, use your own empty repo
Flux needs to be installed on Kubernetes, so make sure you have a cluster at your disposal. In this post, I use Azure Kubernetes Services (AKS). Make sure kubectl points to that cluster. If you have kubectl installed, obtain the credentials to the cluster with the Azure CLI and then run kubectl get nodes or kubectl cluster-info to make sure you are connected to the right cluster.
az aks get-credentials -n CLUSTER_NAME -g RESOURCE_GROUP
It is easy to install Flux with Helm and in this post, I will use Helm v3 which is currently in beta. You will need to install Helm v3 on your system. I installed it in Windows 10’s Ubuntu shell. Use the following command to download and unpack it:
curl -sSL "https://get.helm.sh/helm-v3.0.0-beta.3-linux-amd64.tar.gz" | tar xvz
This results in a folder linux-amd64 which contains the helm executable. Make the file executable with chmod +x and copy it to your path as helmv3. Next, run helmv3. You should see the help text:
The Kubernetes package manager Common actions for Helm: - helm search: search for charts - helm fetch: download a chart to your local directory to view - helm install: upload the chart to Kubernetes - helm list: list releases of charts ...
Now you are ready to install Flux. First, add the FLux Helm repository to allow helmv3 to find the chart:
helmv3 repo add fluxcd https://charts.fluxcd.io
Create a namespace for Flux:
kubectl create ns flux
Install Flux in the namespace with Helm v3:
helmv3 upgrade -i flux fluxcd/flux --wait \ --namespace flux \ --set registry.pollInterval=1m \ --set git.pollInterval=1m \ --set firstname.lastname@example.org:GITHUBUSERNAME/gitops-sample
The above command upgrades Flux but installs it if it is missing (-i). The chart to install is fluxcd/flux. With –wait, we wait until the installation is finished. We will not go into the first two –set options for now. The last option defines the git repository Flux should use to sync the configuration to the cluster. Currently, Flux supports one repository. Because we use a public repository, Flux can easily read its contents. At times, Flux needs to update the git repository. To support that, you can add a deploy key to the repository. First, install the fluxctl tool:
curl -sL https://fluxcd.io/install | sh export PATH=$PATH:$HOME/.fluxcd/bin
Now run the following commands to obtain the public key to use as deploy key:
export FLUX_FORWARD_NAMESPACE=flux fluxctl identity
The output of the command is something like:
Copy and paste this key as a deploy key for your github repo:
Phew… Flux should now be installed on your cluster. Time to install some applications to the cluster from the git repo.
Note: Flux also supports private repos; it just so happens I used a public one here
Install an Ingress Controller
Let’s try to install Traefik via its Helm chart. Since I am not using traditional CD with pipelines that run helm commands, we will need something else. Luckily, there’s a Flux Helm Operator that allows us to declaratively install Helm charts. The Helm Operator installs a Helm chart when it detects a custom resource definition (CRD) of type helm.fluxcd.io/v1. Let’s first create the CRD for Helm v3:
kubectl apply -f https://raw.githubusercontent.com/fluxcd/helm-operator/master/deploy/flux-helm-release-crd.yaml
Next, install the operator:
helmv3 upgrade -i helm-operator flux/helm-operator --wait \ --namespace fluxcd \ --set git.ssh.secretName=flux-git-deploy \ --set git.pollInterval=1m \ --set chartsSyncInterval=1m \ --set configureRepositories.enable=true \ --set configureRepositories.repositories.name=stable \ --set configureRepositories.repositories.url=https://kubernetes-charts.storage.googleapis.com \ --set extraEnvs.name=HELM_VERSION \ --set extraEnvs.value=v3 \ --set image.repository=docker.io/fluxcd/helm-operator-prerelease \ --set image.tag=helm-v3-71bc9d62
You didn’t think I found the above myself did you? 😁 It’s from an excellent tutorial here.
When the operator is installed, you should be able to install Traefik with the following YAML:
apiVersion: helm.fluxcd.io/v1 kind: HelmRelease metadata: name: traefik namespace: default annotations: fluxcd.io/ignore: "false" spec: releaseName: traefik chart: repository: https://kubernetes-charts.storage.googleapis.com/ name: traefik version: 1.78.0 values: serviceType: LoadBalancer rbac: enabled: true dashboard: enabled: true
Just add the above YAML to the GitHub repository. I added it to the ingress folder:
If you wait a while, or run fluxctl sync, the repo gets synced and the resources created. When the helm.fluxcd.io/v1 object is created, the Helm Operator will install the chart in the default namespace. Traefik will be exposed via an Azure Load Balancer. You can check the release with the following command:
kubectl get helmreleases.helm.fluxcd.io NAME RELEASE STATUS MESSAGE AGE traefik traefik deployed helm install succeeded 15m
Also check that the Traefik pod is created in the default namespace (only 1 replica; the default):
kubectl get po NAME READY STATUS RESTARTS AGE traefik-86f4c5f9c9-gcxdb 1/1 Running 0 21m
Also check the public IP of Traefik:
kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP traefik LoadBalancer 10.0.8.59 22.214.171.124
We will later use that IP when we define the ingress for our web application.
In this post, you learned a tiny bit about GitOps with WeaveWorks Flux. The concept is simple enough: store your cluster config in a git repo as the single source of truth and use git operations to initiate (or rollback) cluster operations. To start, we simply installed Traefik via the Flux Helm Operator. In a later post, we will add an application and look at image management. There’s much more you can do so stay tuned!