Flux Image Controller, when you’re pushing new container image tags, can automatically update your Kubernetes manifests to point to the latest version.
Imagine you’ve just built a new Docker image for your my-app service and pushed it to your registry as my-registry.com/my-app:v1.2.3. You want your Kubernetes deployment to use this new image. Manually editing the image: field in your deployment.yaml and committing/pushing that change is tedious and error-prone. This is where Flux’s Image Controller shines. It watches your image registry, detects new tags, and then automatically updates your Kubernetes manifests in Git.
Let’s see it in action.
Here’s a simplified kustomization.yaml that Flux might be managing:
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: my-app
namespace: flux-system
spec:
interval: 5m
path: ./apps/my-app
sourceRef:
kind: GitRepository
name: flux-system
prune: true
patches:
- patch: |-
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app-deployment
namespace: default
spec:
template:
spec:
containers:
- name: my-app
image: my-registry.com/my-app:v1.2.2 # This is what we want to update
And here’s the corresponding image-automation.yaml that tells Flux Image Controller what to look for and how to update:
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImageUpdateAutomation
metadata:
name: my-app-automation
namespace: flux-system
spec:
interval: 10m
sourceRef:
kind: GitRepository
name: flux-system
git:
checkout:
ref:
branch: main
commit:
author:
email: fluxcd@example.com
name: Flux Image Automation
messageTemplate: "Update my-app image to {{range .Results}}{{.Result}}{{end}}"
push:
branch: main
update:
strategy: Setters
Now, let’s say we have a kustomization resource in our Git repo that points to the kustomization.yaml above. The ImageUpdateAutomation resource is configured to watch my-registry.com/my-app for new tags. When a new tag, say v1.2.3, is pushed, the Image Controller:
- Scans the registry: It periodically checks
my-registry.com/my-appfor new tags. - Detects new tag: It sees
v1.2.3is newer thanv1.2.2. - Updates Git: It checks out the branch specified in
git.checkout.ref.branch(e.g.,main), updates theimage:field in the specified manifest (using theSettersstrategy means it looks for a specifically formattedimage: my-registry.com/my-app:v1.2.2and updates that tag), and commits the change with themessageTemplate. - Pushes to Git: It pushes the commit back to the
mainbranch. - Flux Kustomize Controller picks up: The
Kustomizationresource, which is already watching themainbranch of theGitRepository, detects the new commit and applies the updateddeployment.yamlto your cluster.
The "Setters" strategy is particularly neat. It relies on a convention where your image field looks like image: <registry>/<image>:<tag>. The Image Controller will look for a kustomization or HelmRelease that uses this image and update the tag part. If you were using Kustomize, you’d typically have a kustomization.yaml like this within your ./apps/my-app directory:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
images:
- name: my-registry.com/my-app
newName: my-registry.com/my-app
newTag: v1.2.2 # This is the tag the Image Controller will update
The ImageUpdateAutomation resource, in this setup, would then target this kustomization.yaml file, specifically updating the newTag field under images.
The ImageUpdateAutomation resource has a strategy field. The Setters strategy is the most common and works by finding the name and newName fields in Kustomize image definitions or values.yaml for Helm, and updating the newTag or the Helm value. Other strategies exist, like Digests, which updates the image to use its SHA256 digest, ensuring immutability.
A less obvious, but powerful, aspect is how you can control which branches are updated and how commits are formatted. The git.commit.messageTemplate is a Go template that can use information from the detected image tags and results. For example, {{range .Results}}{{.Result}}{{end}} will insert the new tag (e.g., v1.2.3) directly into the commit message. You can also specify a git.push.branch to ensure commits are always made to a specific branch, even if your sourceRef is tracking a different one.
When you configure your ImageUpdateAutomation to use the Setters strategy, the Image Controller will look for a specific pattern in your Kubernetes manifests. It searches for containers where the image field matches a pattern like my-registry.com/my-app:<version>, and then it updates that <version> part. If you’re using Kustomize, it will often look for the images section in your kustomization.yaml where name and newName match your image, and it will update the newTag. This mechanism ensures that only the intended image reference is modified, preventing accidental updates to other parts of your deployment.
The next thing you’ll likely want to explore is how to handle multiple images or different update strategies, such as using image digests for guaranteed immutability.