This episode covers image automation with FluxCD: ImageRepository to scan the registry, ImagePolicy to choose the version according to policy, and ImageUpdateAutomation which writes the updates back to Git automatically.

In episode 12 you learned multi-tenancy: how to separate several teams in one cluster with per-tenant RBAC, quotas, and lockdown mode. That structure and isolation will be useful now, because episode 13 discusses something that runs across environments: image automation.
Image automation is FluxCD's ability to monitor the container registry, detect new images, evaluate the version that matches a policy, then update the manifests in Git automatically. The whole flow stays 100% GitOps — changes always end up in Git as the single source of truth, only they don't have to be done manually by a human.
Image automation in FluxCD is built from three CustomResourceDefinitions (CRDs) that work together:
| CRD | API Group | Role |
|---|---|---|
| ImageRepository | image.toolkit.fluxcd.io | Scans the registry and records the list of image tags |
| ImagePolicy | image.toolkit.fluxcd.io | Evaluates which tag is the latest according to the policy |
| ImageUpdateAutomation | image.toolkit.fluxcd.io | Writes the version update back to Git |
ImageRepository is tasked with periodically scanning the container registry and storing the list of tags it finds. This component is run by the image-reflector-controller.
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImageRepository
metadata:
name: podinfo
namespace: flux-system
spec:
image: ghcr.io/stefanprodan/podinfo
interval: 10mFor a private registry, create a Secret containing the credentials, then reference it via secretRef:
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImageRepository
metadata:
name: private-app
namespace: flux-system
spec:
image: registry.example.com/private-app
interval: 5m
secretRef:
name: registry-credentialsThe interval field determines how often the registry is scanned. Avoid an interval that's too short, for example one minute, for a large registry because it will burden both the registry and the controller. To limit which tags are monitored, use filterTags with a regex pattern and an optional extract:
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImageRepository
metadata:
name: app
namespace: flux-system
spec:
image: ghcr.io/acme/app
interval: 10m
filterTags:
pattern: "^v?[0-9]+\\.[0-9]+\\.[0-9]+$"
extract: "$1"ImagePolicy determines the version selection policy from the tags found by the ImageRepository.
The most common policy, using semantic versioning:
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImagePolicy
metadata:
name: podinfo
namespace: flux-system
spec:
imageRepositoryRef:
name: podinfo
policy:
semver:
range: ">=1.0.0 <2.0.0"With that range, the ImagePolicy selects the highest version tag that satisfies the range. The supported operators include >=, >, <, <=, =, plus the x and * wildcards.
Compares tags lexicographically. Useful for tags that aren't semver versions:
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImagePolicy
metadata:
name: app
namespace: flux-system
spec:
imageRepositoryRef:
name: app
policy:
alphabetical:
order: ascCompares tags as numbers, so the numerical order is respected:
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImagePolicy
metadata:
name: app
namespace: flux-system
spec:
imageRepositoryRef:
name: app
policy:
numerical:
order: asc| Policy | How It Evaluates | Example Ordering |
|---|---|---|
| semver | Semantic versioning order | 1.4.2 is newer than 1.3.9 |
| alphabetical | Letter order | v9 is considered newer than v10 |
| numerical | Number order | v10 is newer than v9 |
| regex | Pattern matching via filterTags | Only matching tags are considered |
Note
Regex-based filtering is actually applied at the ImageRepository level through filterTags, then the ImagePolicy selects among the remaining tags. The combination of both gives the most precise control.
ImageUpdateAutomation is the engine that writes the update back to Git. This component is run by the image-automation-controller.
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImageUpdateAutomation
metadata:
name: flux-system
namespace: flux-system
spec:
interval: 10m
sourceRef:
kind: GitRepository
name: flux-system
git:
checkout:
ref:
branch: main
commit:
author:
email: fluxcdbot@users.noreply.github.com
name: fluxcdbot
messageTemplate: |
[ci skip] update image version
push:
branch: mainThe messageTemplate field determines the content of the commit message. The template supports several built-in variables, for example the image name and the new version. The [ci skip] prefix in the example above prevents a recurring CI pipeline from triggering itself.
By default the update is written to the same branch as the checkout. For a pull request strategy, for example updating to a feature branch then a PR to main, set checkout.ref and push.branch to different branches so the change can be reviewed by a human first.
Always set a clear author, for example a bot account. This makes auditing easier: the commit history will show that the change was made by the image automation bot, not a human.
Let's put all the components together with a real flow:
For the ImageUpdateAutomation to know which image to update, the Kustomization must have an images block:
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: apps
namespace: flux-system
spec:
interval: 10m
path: ./apps
prune: true
sourceRef:
kind: GitRepository
name: flux-system
images:
- name: ghcr.io/stefanprodan/podinfo
newName: ghcr.io/stefanprodan/podinfoWhen the ImagePolicy produces a new version, the ImageUpdateAutomation writes that version into the newTag or newName on the Kustomization, then commits to Git. Verify the running components:
flux get images repository
flux get images policy
flux get images update| Environment | Strategy | Example Configuration |
|---|---|---|
| Development | Full automatic update | Wide semver range, auto-commit to main |
| Staging | Controlled automatic update | Narrow range plus notifications |
| Production | Manual approval via PR | Update to a feature branch, then a PR by a human |
Tip
For production, don't let ImageUpdateAutomation write directly to main. Point the update at a separate branch and use a pull request — a human stays the last gate before the change is applied.
Episode 13 wraps up how FluxCD automates image updates from the registry to Git.
The key takeaways:
In the next episode, episode 14, we'll discuss Notifications & Alerts — how FluxCD sends notifications to Slack, Discord, or a custom webhook on every event, and how the Alert CRD filters events so they don't flood the team. See you!