DEV Community

Folashade Oluwaseun Oroge
Folashade Oluwaseun Oroge

Posted on

Automating Kubernetes Image Updates with FluxCD, Amazon ECR, and GitHub

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:

  1. A developer merges code.
  2. A CI/CD pipeline builds a Docker image.
  3. The image is pushed to a container registry.
  4. Someone manually updates the image tag in Kubernetes manifests.
  5. 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
Enter fullscreen mode Exit fullscreen mode

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  │
└──────────────────────┘
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

The GitHub App should have:

Repository Permissions

Contents: Read & Write
Metadata: Read
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

What Happens Behind the Scenes?

Every five minutes Flux:

  1. Authenticates to AWS
  2. Queries the ECR repository
  3. Retrieves available tags
  4. Stores the results internally

Check the repository status:

flux get image repository
Enter fullscreen mode Exit fullscreen mode

Example:

NAME          LAST SCAN              READY
testservice   2025-05-23T14:20:00Z  True
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Understanding the Tag Strategy

Suppose ECR contains:

branch-dev-1715555000-a12b34c
branch-dev-1715556000-b45d67e
branch-dev-1715557000-f12a34b
Enter fullscreen mode Exit fullscreen mode

The regex:

^branch-dev-(?P<ts>[0-9]+)-[0-9a-f]+$
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Flux extracts:

1715557000
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

How Image Update Automation Works

Every five minutes:

  1. Clone repository
  2. Scan manifests under ./apps/dev
  3. Locate image policy markers
  4. Update image tags
  5. Commit changes
  6. 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"}
Enter fullscreen mode Exit fullscreen mode

The comment is critical:

# {"$imagepolicy": "flux-system:testservice:tag"}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

New image pushed:

branch-dev-1715557000-f12a34b
Enter fullscreen mode Exit fullscreen mode

Flux updates the file automatically:

tag: branch-dev-1715557000-f12a34b
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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-*
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

View Image Policies

flux get image policy
Enter fullscreen mode Exit fullscreen mode

Example:

NAME          LATEST IMAGE
testservice   branch-dev-1715557000-f12a34b
Enter fullscreen mode Exit fullscreen mode

View Image Automations

flux get image update
Enter fullscreen mode Exit fullscreen mode

Force a Repository Scan

flux reconcile image repository testservice
Enter fullscreen mode Exit fullscreen mode

Force Image Automation

flux reconcile image update core-us-dev
Enter fullscreen mode Exit fullscreen mode

Check Automation Logs

kubectl logs \
-n flux-system \
deployment/image-automation-controller
Enter fullscreen mode Exit fullscreen mode

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)