GitHub Actions FluxCD & Helm
In the upcoming blog post, we will implement continuous integration and deployment with Helm and some GitOps characteristics
Guidelines
The primary focus of this blog post is to explore and showcase three key topics:
- Utilizing GitHub Actions Workflow
- Implementing deployment through Helm, with an emphasis on basic templating techniques
- Employing FluxCD for deployment and its integration with the HelmRelease resource and Image Automation
Considering that the blog post serves as an illustrative example, it's important to note that there are additional aspects of Continuous Integration (CI) and Continuous Deployment (CD) that are not covered in detail here. For instance, in the realm of CI, aspects such as testing methodologies and strategies play a crucial role. Similarly, in the CD complex processes within the workflow are also beyond the scope of this example.
Make sure to install FluxCD CLI and other prerequisites
Repository Structure
There are several ways to structure FluxCD repository More information can be found here. For the sake of simplicity in this tutorial, we will utilize a monorepo approach, consolidating all Kubernetes manifests within a single Git repository.
This is a simple Java Maven repository that was forked from here and on top of it we`ve added
- Dockerfile with simple multistage
- Two ways of deployment
- Kubectl and Helm CLIs
- FluxCD
- Using HelmRelease
- Using Flux Image Controller / Policy
- The above are orchestrated as CI and CD via GitHub Action Workflow
Our repository is structured in a manner of a monorepo, yet it has been simplified for the purposes of this example. This streamlined approach retains the core characteristics of a monorepo while ensuring ease of understanding and accessibility for demonstration purposes.
High level structure:
├── myapp (Java, Maven and Docker)
└── deployment
├── myapp-chart (Helm Chart)
└── flux
├── apps
│ └── base
├── infrastructure
│ └── dev
└── clusters
└── dev
GitHub Workflow
We've breaken our pipline into three GitHub Action jobs): app-build, docker-build and deployment.
Refer to the workflow yaml located at .github/workflows/myapp-workflow.yaml
for detailed information about the jobs and steps.
Note: In case you want to run it on your repository make sure to create PAT in order to get repository access (same as describe below for setting GITHUB_TOKEN in order to locally run FluxCD)
- app-build: Java build using Maven. i.e.
mvn clean package
- docker-build: In this phase, we build the container using the Dockerfile, just for the example the Dockerfile includes multilayer. This job stars running only after a succesful complition of app-build phase.
- deployment: triggering three independent jobs:
- Simple docker run
- Kind cluster installation and Helm CLI (using the utility script)
- Kind cluster installation and FluxCD bootstrap (using the utility script)
At the buttom of the image you can see the logs of Helm CLI & FluxCD bootstrap steps (printing out the POD logs as explianed below).
Note: The repository also demostrate some branch protection:
- Require a pull request & approvals before merging
- Require status checks to pass before merging, it will run the
app-build
as part of the pull request
Deployment
For your convinence you can use two utlity scripts:
- setup.sh - Setup the required softwares (the same script called during the CI/CD workflow)
- deploy.sh - Automate the deployment proccess for both options: Kubectl & Help CLIs as well as using FluxCD
Using Kubectl and Helm CLI
Executing the script:
cd deployment
./deploy.sh -v 1.0.0
The script will install KIND Cluster and once the cluster is ready it will start the deployment using Helm Chart located at deployment/myapp-chart
using values-dev.yaml
templating as well as --set image.tag=${VERSION}
as was set using the -v
flag.
Using FluxCD
Make to create and set GITHUB_TOKEN
You`ll need to set the both GITHUB_TOKEN & GITHUB_USER, it will be used by the utitlity script for FluxCD bootstrap command:
export GITHUB_TOKEN=<YOUR_PAT>
export GITHUB_USER=<YOUR_GH_USER>
Executing the script:
cd deployment
./deploy.sh --flux
Verify Flux PODs
The following pods should be running on flux-system namespace
kubectl get pod -n flux-system
NAME READY STATUS RESTARTS AGE
helm-controller-69dbf9568-tp4x6 1/1 Running 0 2m5s
image-automation-controller-6bbc947558-h82k6 1/1 Running 0 2m5s
image-reflector-controller-7c49fdc68f-skrjs 1/1 Running 0 2m5s
kustomize-controller-77bf676476-cj5rr 1/1 Running 0 2m5s
notification-controller-7bb6d7684d-k9s9l 1/1 Running 0 2m5s
source-controller-5996567c74-kt5nt 1/1 Running 0 2m5s
Exploring Flux Kustomizations
Flux manage the deployment and its dependencies using a kustomization resource. To watch the kustomizations list and thier status:
flux get kustomizations
NAME REVISION SUSPENDED READY MESSAGE
flux-system master@sha1:d27dac72 False True Applied revision: master@sha1:d27dac72
myapp-dev master@sha1:d27dac72 False True Applied revision: master@sha1:d27dac72
Checking the logs
Once the deployment is done, the script will get the POD i.e. myapp-6fc4d44c75-4jpvg
logs and pring it out.
Starts new deployment...
Version: Managed By FluxCD
Deploy using FluxCD
deployment "myapp" successfully rolled out
POD Image Details:
Image: devozs/myapp:1.0.0
Image ID: docker.io/devozs/myapp@sha256:0ac0962589fa30ca8d09f073a33fe7791359a295324aa237e2c5b6980f848415
POD Logs:
Hello World! DevOzs
Deployment Done
Secrets
In this tutorial, we haven't utilized a secret manager like Azure Key Vault or any other valut. In case you need to use secrets (i.e when using Flux Image Repository with private regitry) make sure not to keep your secrets in Git.
Make sure not to put your kubernetes secrets in Git
Docker Pull Secret
In case you are workign with images from private registry, Docker pull secret is will used in two ways:
- Pull the deployment image from Github registry
- FluxCD uses it to fetch new tags from Github registry
apiVersion: v1
kind: Secret
metadata:
name: cr-secret
namespace: flux-system
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: <PUT_YOURS>
---
apiVersion: v1
kind: Secret
metadata:
name: cr-secret
namespace: dev
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: <PUT_YOURS>
The FluxCD Magic 🪄
We are using two powerful Flux capabilities:
- Listen to new images in a certian repository and given pattern
apiVersion: image.toolkit.fluxcd.io/v1beta1
kind: ImagePolicy
metadata:
name: myapp
namespace: flux-system
spec:
imageRepositoryRef:
name: myapp
policy:
semver:
range: 1.0.x
apiVersion: image.toolkit.fluxcd.io/v1beta1
kind: ImageRepository
metadata:
name: myapp
namespace: flux-system
spec:
image: devozs/myapp
interval: 1m0s
flux get image policy -A
NAMESPACE NAME LATEST IMAGE READY MESSAGE
dev myapp devozs/myapp:1.0.40 True Latest image tag for 'devozs/myapp' updated from 1.0.39 to 1.0.40
flux get image repository
NAMESPACE NAME LAST SCAN SUSPENDED READY MESSAGE
dev myapp 2023-12-18T00:43:48+02:00 False True successful scan: found 41 tags
- Update the resolved image tag in the relevant Kubernetes yaml (directly to the Deployment YAML or vie Kustomization YAML)
apiVersion: image.toolkit.fluxcd.io/v1beta1
kind: ImageUpdateAutomation
metadata:
name: image-update-automation
namespace: flux-system
spec:
interval: 1m10s
sourceRef:
kind: GitRepository
name: flux-system
git:
checkout:
ref:
branch: main
commit:
author:
email: fluxcdbot@users.noreply.github.com
name: fluxcdbot
messageTemplate: '{{range .Updated.Images}}{{println .}}{{end}}'
push:
branch: main
update:
path: ./gitops/clusters/dev
strategy: Setters