Automating Deployments with FluxCD in AKS
Welcome back to our Kubernetes journey! In this final installment, we’ll automate Kubernetes deployments using FluxCD in Azure Kubernetes Service (AKS). If you missed the earlier parts, you can catch up here:
- Deploying to Azure Kubernetes Service (AKS)
- Securing Kubernetes: Ingress and SSL Configuration with Nginx and Cert-Manager in AKS
Introduction to FluxCD
FluxCD is a GitOps tool that automates the deployment and lifecycle management of Kubernetes applications. It continuously monitors a Git repository for changes in the application’s manifests and automatically applies those changes to the Kubernetes cluster.
Why Use FluxCD?
FluxCD simplifies the deployment process by eliminating the need for manual intervention. It ensures consistency between the desired state described in your Git repository and the actual state of your cluster. With FluxCD, you can easily roll out updates, rollback changes, and maintain version control of your Kubernetes configurations.
Installing FluxCD
To install FluxCD in your AKS cluster, I used the flux bootstrap approach described in the Flux installation guide. Install their CLI, then head over to Azure DevOps, click on the gear icon and generate a new Personal Access Token (PAT) with read and write permissions to your git repository hosted on AZDO:
Then, run the following command:
flux bootstrap git
--token-auth=true \
--password=<Your_PAT> \
--url=https://dev.azure.com/victorgago-work/Victor/_git/VictorGago.Mobile.Base" `
--branch=main \
--cluster=webappdemoThe flux bootstrap utility works by initializing FluxCD components in your Kubernetes cluster and configuring them to sync with your Git repository. Here’s what each parameter in the command does:
- git: Specifies the Git source for FluxCD to synchronize with.
- token-auth: Enables token-based authentication for accessing the Git repository.
- password: Sets the Personal Access Token (PAT) as the authentication password.
- url: Specifies the URL of your Git repository hosted on Azure DevOps.
- branch: Defines the Git branch that FluxCD should monitor for changes.
- path: relative to the Git root, specifies the location where Flux will create its manifests and watch for changes.
- cluster: Identifies the target Kubernetes cluster where FluxCD will manage deployments.
Verifying FluxCD Installation
Once FluxCD is installed, it will automatically start synchronizing your Git repository with the Kubernetes cluster. You can verify the installation by checking the logs:
kubectl -n flux logs deployment/fluxYou should see FluxCD syncing your manifests and applying changes to the cluster. To demonstrate, I changed my deployment resource for the UI component to a non-existing tag in my ACR repository. Soon after I pushed the changes, the deployment fails to pull the image, meaning the cluster state was being synced in response to git changes. Then, after reverting the image tag to its correct value, we see the pod returning to its healthy state:
This example not only shows Flux in action, but also demonstrates the importance of automated image tag updates in manifests. Manually updating image tags in manifests can lead to errors and disruptions in your deployment process. Fortunately, Flux provides an automated solution for managing image updates.
By leveraging Flux’s image automation features, you can ensure that your Kubernetes resources always use the latest version of container images without the need for manual intervention. Flux can automatically detect new image tags pushed to your container registry and update the corresponding manifests accordingly.
The problem with targeting the ‘latest’ tag directly is that it lacks versioning and can introduce unpredictability into your deployment process. The ‘latest’ tag always points to the most recently pushed image, which might not be compatible with your application or could introduce unexpected changes. Instead, we should specify specific image tags or use a versioning strategy to ensure consistency and stability in our deployments.
Defining Image Policies
Image policies are rules or specifications that dictate how FluxCD should handle the selection and updating of container images within Kubernetes deployments. These policies help enforce best practices and ensure consistency and stability in the deployment process. By defining image policies, you can control which images are deployed, how frequently updates occur, and what criteria are used to select new images.
To enable image policies, we need an Image Reflector controller and an Image Automation controller. Install them by appending one components-extra argument to the flux bootstrap git command:
flux bootstrap git
--token-auth=true \
--password=<Your_PAT> \
--url=https://dev.azure.com/victorgago-work/Victor/_git/VictorGago.Mobile.Base" `
--branch=main \
--cluster=webappdemo \
--components-extra=image-reflector-controller,image-automation-controllerYou should see additional CRDs being configured:
Flux also requires Repository and ImagePolicy resources for defining the git source and the image pulling strategy, respectively. Repository resources define the location of container images, typically hosted in a container registry, and ImagePolicy resources specify rules for selecting images from these repositories.
The Repository resource contains information such as the image repository URL, authentication credentials (in the form of a secret reference), and the synchronization interval, which determines how often Flux checks for updates to the images.
The ImagePolicy resource defines criteria for selecting images, such as filtering based on image tags using regular expressions. Additionally, it specifies the update policy, which determines how Flux handles updates to images that match the defined criteria. This can include strategies like selecting the latest image based on timestamp or semantic versioning, ensuring that only compatible and tested images are deployed.
apiVersion: image.toolkit.fluxcd.io/v1beta1
kind: ImageRepository
metadata:
name: webapp-demo-api
namespace: flux-system
spec:
image: vgwebappdemo.azurecr.io/victorgago/webapp-demo/api
secretRef:
name: acr-secret
interval: 1m
—
apiVersion: image.toolkit.fluxcd.io/v1beta1
kind: ImagePolicy
metadata:
name: webapp-demo-api
namespace: flux-system
spec:
imageRepositoryRef:
name: webapp-demo-api
filterTags:
pattern: '^\d{8}-\d{6}$' # Regular expression to match the yyMMdd-hhmmss format
policy:
alphabetical:
order: asc
In the provided example manifests, separate ImageRepository and ImagePolicy resources are defined for each application component, allowing for granular control and flexibility in managing image updates across different parts of the application.
To see it in action, I rebuilt my application’s container images, tagged them with a timestamp matching the format specified in my image policy resources and pushed them to ACR:
As the new tags were pushed to ACR, the Flux image automation controller detects them, triggering a cluster update to the latest image as chosen by the policy:
Note: The scan interval you define for these resources can make debugging difficult, so it’s best to leave them at a minimum for troubleshooting purposes, or execute flux reconcile kustomization flux-system — with-source after a git push.
Automating Docker tasks
For an effective workflow, it is paramount to have automation set up for building and pushing images to ACR. This comprehensive guide demonstrates how to achieve this by leveraging Azure DevOps Pipelines to automate Docker tasks. With the proper automation, new images can be built and pushed to the registry based on your custom-defined triggers, such as code commits or scheduled builds.
Azure DevOps Pipelines allow you to create CI/CD pipelines that integrate seamlessly with your source control repository. By defining pipeline configurations, you can specify the steps required to build Docker images, run tests, and push the images to ACR. These pipelines can be triggered automatically or manually, depending on your workflow requirements.
Without delving into the concepts of Pipelines and their syntax, this is how a typical build and push job would look like for my use case:
trigger:
- main
pool:
vmImage: 'ubuntu-latest'
steps:
- task: Docker@2
displayName: 'Build and push UI container image'
inputs:
command: 'buildAndPush'
containerRegistry: 'vgwebappdemoServiceConnection1'
repository: 'victorgago/webapp-demo/ui'
tags: |
victorgago/webapp-demo/ui:$(Format('{0:yyyyMMdd-HHmmss}', pipeline.startTime))
victorgago/webapp-demo/ui:latest
Dockerfile: 'UI/Dockerfile'
- task: Docker@2
displayName: 'Build and push API container image'
inputs:
command: 'buildAndPush'
containerRegistry: 'vgwebappdemoServiceConnection1'
repository: 'victorgago/webapp-demo/api'
tags: |
victorgago/webapp-demo/api:$(Format('{0:yyyyMMdd-HHmmss}', pipeline.startTime))
victorgago/webapp-demo/api:latest
Dockerfile: 'API/Dockerfile'With the Pipelines being triggered on code changes to the ‘main’ branch and new revisions getting pushed to ACR, Flux can detect the changes on schedule and update the Kubernetes manifests accordingly. By properly tagging the images to match the filter specified in the ImagePolicy, Flux can identify the latest images and ensure that the Kubernetes cluster is always running the most up-to-date versions of your application components.
Defining Image Automation
In the context of FluxCD, image automation involves components such as the Image Reflector controller, which monitors container registries for new images, and the Image Automation controller, which applies image policies and updates Kubernetes resources accordingly. By automating image updates, FluxCD helps streamline the deployment process and ensures that Kubernetes clusters are always running the latest, validated versions of application components.
The provided example demonstrates an ImageUpdateAutomationResource manifest, which defines how FluxCD should automate image updates for a specific application component. Let’s break down the components of this manifest:
apiVersion: image.toolkit.fluxcd.io/v1beta1
kind: ImageUpdateAutomation
metadata:
name: webapp-demo-api
namespace: flux-system
spec:
git:
checkout:
ref:
branch: main
commit:
author:
email: fluxcdbot@users.noreply.github.com
name: fluxcdbot
messageTemplate: 'Updated deployment tags for webapp-demo-api'
push:
branch: main
interval: 1m
sourceRef:
kind: GitRepository
name: flux-system
update:
path: ./GitOps/base/webapp-demo-api
strategy: Setters- interval: Specifies the interval at which FluxCD should check for updates to the Git repository containing the application manifests (in this case, every 10 minutes).
- sourceRef: Specifies the Git repository source from which FluxCD should pull the manifests.
- kind: Specifies the kind of resource being referenced (in this case, a GitRepository).
- name: Specifies the name of the Git repository resource. I’m using the default flux-system GitRepository.
- git: Configures how FluxCD interacts with the Git repository.
- checkout: Specifies the branch from which FluxCD should check out the manifests.
- commit: Defines the author information and commit message template to be used when FluxCD commits changes back to the Git repository.
- push: Specifies the branch to which FluxCD should push changes after updating the manifests.
- update: Specifies how FluxCD should update Kubernetes resources based on changes to the Git repository.
- path: Specifies the path within the Git repository where FluxCD should look for manifests to update (in this case, “./GitOps/base”).
- strategy: Defines the strategy FluxCD should use when updating Kubernetes resources (in this case, “Setters”).
As a result, when Flux elects a new image tag, that tag is patched in the deployment manifests in the Git repository:
In summary, image policies and automation are key features of FluxCD that enable GitOps-based deployment workflows in Kubernetes. They provide mechanisms for managing container images, enforcing deployment best practices, and automating the update process, ultimately contributing to a more efficient and reliable deployment pipeline.
The final folder structure for my manifests turned out like this:
Should I want to deploy to multiple environments in the future, I can leverage the concept of base and overlays in Kustomize to override just the necessary values.
Conclusion
With FluxCD installed, we’ve automated the deployment workflow in the AKS cluster, ensuring seamless updates and maintaining the desired state of the application. In this series, we’ve covered setting up the resources, deployments and services, ingress and SSL configuration, and now deployment automation.
References
- GitOps | GitOps is continuous deployment for cloud native applications
- Application deployments with GitOps (Flux v2) for AKS and Azure Arc-enabled Kubernetes | Microsoft Learn
- Flux installation | Flux
- CI/CD workflow using GitOps (Flux v2)
- Automate image updates to Git | Flux
- Image Policies | Flux
- Image Update Automations | Flux
- Declarative Management of Kubernetes Objects Using Kustomize | Kubernetes
- Build and push Docker images to Azure Container Registry with Docker templates — Azure Pipelines | Microsoft Learn
- Image tag best practices | Microsoft Learn
