Learn how to automatically deploy new container images to Kubernetes using FluxCD Image Automation, Amazon ECR, GitHub Apps, and GitOps principles.
Introduction
One of the challenges platform engineers face in Kubernetes environments is keeping application deployments synchronized with newly built container images.
In many organizations, the deployment process looks something like this:
- A developer merges code.
- A CI/CD pipeline builds a Docker image.
- The image is pushed to a container registry.
- Someone manually updates the image tag in Kubernetes manifests.
- The changes are committed and deployed.
While this works, it introduces unnecessary manual effort and increases the risk of deploying the wrong image version.
FluxCD's Image Automation Toolkit solves this problem by automatically:
- Detecting newly published container images
- Selecting the correct image based on defined policies
- Updating Kubernetes manifests in Git
- Committing the changes back to the repository
- Allowing Flux to reconcile and deploy the new version
This creates a fully automated GitOps workflow where Git remains the single source of truth.
The Problem We're Solving
Imagine your CI/CD pipeline generates image tags like:
branch-dev-1715555000-a12b34c
branch-dev-1715556000-b45d67e
branch-dev-1715557000-f12a34b
Without automation, someone must:
- Identify the latest image
- Update deployment manifests
- Create a pull request
- Merge the change
- Wait for deployment
As the number of applications grows, this quickly becomes difficult to manage.
Flux Image Automation removes this operational overhead entirely.
Solution Architecture
The deployment workflow looks like this:
┌──────────────────────┐
│ Developer Pushes Code│
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ CI/CD Pipeline │
│ Builds Docker Image │
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ Amazon ECR │
│ Stores New Image │
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ Flux ImageRepository │
│ Scans Registry │
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ Flux ImagePolicy │
│ Selects Latest Tag │
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ ImageUpdateAutomation│
│ Updates Git │
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ Git Repository │
│ Receives Commit │
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ Flux Reconciliation │
│ Deploys New Version │
└──────────────────────┘
Prerequisites
Before implementing this solution, ensure you have:
- A Kubernetes cluster
- FluxCD installed
- GitOps repository containing Kubernetes manifests
- Amazon ECR repository
- GitHub repository
- GitHub App configured for write access
- AWS permissions configured for Flux
Required Flux controllers:
- source-controller
- helm-controller
- image-reflector-controller
- image-automation-controller
Verify Flux installation:
flux check
Expected output:
► checking prerequisites
✔ Kubernetes 1.29.0 >=1.28.0
✔ prerequisites checks passed
► checking controllers
✔ source-controller
✔ helm-controller
✔ image-reflector-controller
✔ image-automation-controller
Step 1: Create a Write-Capable Git Repository
Unlike a standard Flux GitRepository resource, Image Automation requires write access because Flux must commit updated image tags back to Git.
Create a dedicated repository source:
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: flux-system-write
namespace: flux-system
spec:
interval: 1m
provider: github
ref:
branch: dev
secretRef:
name: flux-system-write
url: https://github.com/<organization>/<repository>.git
What This Resource Does
This repository allows Flux to:
- Clone the repository
- Modify files
- Create commits
- Push updates
Without write access, Image Automation cannot function.
Step 2: Configure GitHub App Authentication
Flux recommends using GitHub Apps instead of Personal Access Tokens (PATs).
Create the authentication secret:
flux create secret githubapp flux-system-write \
--app-id=<app-id> \
--app-installation-owner=<organization> \
--app-private-key=<path-to-private-key.pem>
The GitHub App should have:
Repository Permissions
Contents: Read & Write
Metadata: Read
Benefits of GitHub Apps:
- More secure than PATs
- Easier rotation
- Granular permissions
- Better auditing
Step 3: Configure an Image Repository
The ImageRepository resource tells Flux where images are stored.
Example using Amazon ECR:
apiVersion: image.toolkit.fluxcd.io/v1
kind: ImageRepository
metadata:
name: testservice
namespace: flux-system
spec:
image: <account-id>.dkr.ecr.us-east-1.amazonaws.com/testservice
interval: 5m
provider: aws
What Happens Behind the Scenes?
Every five minutes Flux:
- Authenticates to AWS
- Queries the ECR repository
- Retrieves available tags
- Stores the results internally
Check the repository status:
flux get image repository
Example:
NAME LAST SCAN READY
testservice 2025-05-23T14:20:00Z True
Step 4: Create an Image Policy
An Image Policy determines which image Flux should deploy.
Example:
apiVersion: image.toolkit.fluxcd.io/v1
kind: ImagePolicy
metadata:
name: testservice
namespace: flux-system
spec:
imageRepositoryRef:
name: testservice
filterTags:
pattern: "^branch-dev-(?P<ts>[0-9]+)-[0-9a-f]+$"
extract: "$ts"
policy:
numerical:
order: asc
Understanding the Tag Strategy
Suppose ECR contains:
branch-dev-1715555000-a12b34c
branch-dev-1715556000-b45d67e
branch-dev-1715557000-f12a34b
The regex:
^branch-dev-(?P<ts>[0-9]+)-[0-9a-f]+$
breaks down as:
| Component | Meaning |
|---|---|
branch-dev |
Environment identifier |
(?P<ts>[0-9]+) |
Captures timestamp |
[0-9a-f]+ |
Commit SHA |
$ |
End of tag |
For:
branch-dev-1715557000-f12a34b
Flux extracts:
1715557000
and uses it for comparison.
Why Use Numerical Policies?
Numerical policies are ideal when image tags contain:
- Build numbers
- Unix timestamps
- Sequential releases
This allows Flux to determine the newest image without relying on semantic versioning.
Step 5: Configure Image Update Automation
Now we tell Flux how to update Git.
apiVersion: image.toolkit.fluxcd.io/v1
kind: ImageUpdateAutomation
metadata:
name: dev
namespace: flux-system
spec:
interval: 5m
sourceRef:
kind: GitRepository
name: flux-system-write
git:
checkout:
ref:
branch: dev
commit:
author:
name: FluxBot
email: flux@example.com
messageTemplate: |
Automated image update
Automation name: {{ .AutomationObject }}
Files:
{{ range $filename, $_ := .Changed.FileChanges -}}
- {{ $filename }}
{{ end -}}
push:
branch: image-update-dev
update:
path: ./apps/dev
How Image Update Automation Works
Every five minutes:
- Clone repository
- Scan manifests under
./apps/dev - Locate image policy markers
- Update image tags
- Commit changes
- Push changes to GitHub
This completely removes the need for manual image version updates.
Step 6: Configure HelmRelease for Automation
Flux requires a marker showing where image updates should occur.
Example:
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: core
spec:
values:
testservice:
image:
tag: branch-dev # {"$imagepolicy": "flux-system:testservice:tag"}
The comment is critical:
# {"$imagepolicy": "flux-system:testservice:tag"}
This tells Flux:
"Update this value whenever the ImagePolicy selects a newer tag."
What Happens During an Update?
Current manifest:
tag: branch-dev-1715555000-a12b34c
New image pushed:
branch-dev-1715557000-f12a34b
Flux updates the file automatically:
tag: branch-dev-1715557000-f12a34b
and commits the change.
Real-World Deployment Example
Let's walk through a deployment.
Step 1
Developer merges code into the development branch.
Step 2
CI/CD builds:
branch-dev-1715557000-f12a34b
Step 3
Image is pushed to ECR.
Step 4
ImageRepository detects the new tag.
Step 5
ImagePolicy determines it is the newest valid image.
Step 6
ImageUpdateAutomation updates Git.
Step 7
Flux detects the Git commit.
Step 8
HelmRelease deploys the updated image.
The application is now running the latest version without any engineer modifying a deployment manifest.
Multi-Environment Strategy
One of the biggest advantages of Flux Image Automation is environment separation.
Example:
Development
branch-dev-*
Staging
branch-staging-*
Production
release-*
You can create separate:
- ImageRepositories
- ImagePolicies
- ImageUpdateAutomations
for each environment.
This allows:
- Developers to deploy rapidly in Development
- QA teams to validate releases in Staging
- Production deployments to remain tightly controlled
Monitoring and Troubleshooting
View Image Repositories
flux get image repository
View Image Policies
flux get image policy
Example:
NAME LATEST IMAGE
testservice branch-dev-1715557000-f12a34b
View Image Automations
flux get image update
Force a Repository Scan
flux reconcile image repository testservice
Force Image Automation
flux reconcile image update core-us-dev
Check Automation Logs
kubectl logs \
-n flux-system \
deployment/image-automation-controller
Benefits of Flux Image Automation
GitOps Compliant
All deployment changes remain in Git.
Fully Auditable
Every image promotion becomes a commit.
Reduced Operational Overhead
No more manual image tag updates.
Faster Deployments
New images reach Kubernetes automatically.
Environment Control
Different environments can follow different promotion strategies.
Conclusion
FluxCD Image Automation provides a powerful GitOps-native approach to continuous deployment. By combining Amazon ECR, GitHub Apps, ImageRepository, ImagePolicy, ImageUpdateAutomation, and HelmRelease resources, teams can automatically promote container images while keeping Git as the single source of truth.
The result is a deployment workflow that is:
- Automated
- Auditable
- Scalable
- Secure
- GitOps compliant
For organizations running multiple Kubernetes environments, this pattern significantly reduces operational effort while improving deployment consistency and reliability.
Top comments (0)