Automating Container Image Updates¶
While the core of a GitOps workflow is to synchronize your cluster's state with a Git repository, the GitOps toolkit (FluxCD) also provides a powerful automation feature to bridge the gap with your container registry. Flux can be configured to monitor a registry, detect when a new image version has been pushed, and automatically commit the updated image tag back to your Git repository. This closes the loop, creating a fully automated pipeline from image push to deployment.
This guide will walk you through the four-step process of configuring this automation. It involves creating three Flux resources and adding a special marker to your deployment manifest.
ImageRepository: Tells Flux which container image to scan.ImagePolicy: Tells Flux how to select the latest version (e.g., using semantic versioning).ImageUpdateAutomation: Tells Flux how to commit the change back to Git.- Marker: A comment in your deployment YAML that tells Flux where to write the new tag.
Step 1: Tell Flux Which Image to Scan (ImageRepository)¶
First, you need to create an ImageRepository resource. This tells Flux the
location of the container image you want it to monitor for new tags.
# image-repository.yaml
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImageRepository
metadata:
name: my-app-image-repo
namespace: my-app-namespace
spec:
# The full path to the container image you want to scan
image: registry.netic.dk/dockerhub/nginxinc/nginx-unprivileged
# How often Flux should scan the registry for new tags
interval: 5m
# If the repository is private, reference the secret containing your credentials
# secretRef:
# name: my-registry-credentials
Step 2: Define the Update Strategy (ImagePolicy)¶
Next, create an ImagePolicy. This resource references the ImageRepository
from Step 1 and defines the rules for selecting the "latest" version from the
list of tags that Flux finds.
The most common and recommended policy is to use semantic versioning (semver).
The example below tells Flux to select the newest tag that matches the 1.x
semantic version range (e.g., it will select 1.21 or 1.22 but not 2.0).
# image-policy.yaml
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImagePolicy
metadata:
name: my-app-image-policy
namespace: my-app-namespace
spec:
# Reference the ImageRepository from Step 1
imageRepositoryRef:
name: my-app-image-repo
# Define the policy for selecting the latest version
policy:
semver:
# Select the newest tag within the 1.x range
range: 1.x
Step 3: Configure the Git Update (ImageUpdateAutomation)¶
Now, create the ImageUpdateAutomation resource. This connects the dots,
telling Flux to use the policy to find new images and then how to commit the
changes back to your Git repository.
# image-update-automation.yaml
apiVersion: image.toolkit.fluxcd.io/v1beta1
kind: ImageUpdateAutomation
metadata:
name: my-app-update-automation
namespace: my-app-namespace
spec:
# How often Flux should check for updates and commit them
interval: 5m
# Reference the GitRepository resource that Flux is already using to sync your cluster
sourceRef:
kind: GitRepository
name: my-gitops-repo # This should match the name of your existing GitRepository source
# Define the Git commit and push details
git:
checkout:
ref:
branch: main
commit:
author:
email: fluxcdbot@users.noreply.github.com
name: fluxcdbot
messageTemplate: "Automated image update: {{range .Updated.Images}}{{.}}{{end}}"
push:
branch: main
Step 4: Mark Your Deployment Manifest¶
The final and most important step is to tell Flux exactly where to write the
new image tag. You do this by adding a specially formatted comment to the
image line in your Deployment, StatefulSet, or other workload manifest.
The format is # {"$imagepolicy": "<namespace>:<policy-name>"}.
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-application
spec:
# ...
template:
spec:
containers:
- name: my-app
# The current image tag, followed by the magic comment
image: registry.netic.dk/dockerhub/nginxinc/nginx-unprivileged:1.20 # {"$imagepolicy": "my-app-namespace:my-app-image-policy"}
ports:
- containerPort: 8080
When all four of these components are deployed, the following will happen:
- Flux will scan the
nginx-unprivilegedrepository every 5 minutes. - If it finds a new tag that matches the
1.xrange (e.g.,1.21), theImagePolicywill be updated to reflect this new version. - The
ImageUpdateAutomationwill see the policy change, check out themainbranch of your Git repository, find the file with the marker comment, and change1.20to1.21. - It will then commit and push this change back to your repository.
- Your existing GitOps workflow will detect the change in the Git repository and deploy the new version of the application to the cluster.