Amazon EKS — Flux on EKS

2 minute read

Flux is a CNCF graduated GitOps toolkit. Unlike ArgoCD’s UI-first approach, Flux is API-first — entirely managed via Kubernetes custom resources. It’s lightweight, composable, and ideal for platform teams automating multi-tenant clusters.


Bootstrap Flux on EKS

# Install Flux CLI
brew install fluxcd/tap/flux

# Check prerequisites
flux check --pre

# Bootstrap (creates Flux components + Git repo structure)
flux bootstrap github \
  --owner=my-org \
  --repository=fleet-infra \
  --branch=main \
  --path=clusters/production \
  --personal

This:

  1. Creates the fleet-infra repo (if it doesn’t exist)
  2. Installs Flux components in the cluster (flux-system namespace)
  3. Configures Flux to watch clusters/production/ in the repo

Core CRDs

GitRepository — Define Source

apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
  name: my-app
  namespace: flux-system
spec:
  interval: 1m
  url: https://github.com/my-org/my-app-manifests
  ref:
    branch: main
  secretRef:
    name: github-token    # GitHub PAT or deploy key

Kustomization — Deploy from Source

apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: my-app
  namespace: flux-system
spec:
  interval: 5m
  targetNamespace: production
  sourceRef:
    kind: GitRepository
    name: my-app
  path: ./overlays/production
  prune: true               # Delete resources removed from Git
  healthChecks:
    - apiVersion: apps/v1
      kind: Deployment
      name: my-app
      namespace: production
  timeout: 3m

HelmRelease — Deploy Helm Charts

apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
  name: nginx-ingress
  namespace: flux-system
spec:
  interval: 10m
  chart:
    spec:
      chart: ingress-nginx
      version: "4.x"
      sourceRef:
        kind: HelmRepository
        name: ingress-nginx
  values:
    controller:
      replicaCount: 2
      service:
        type: LoadBalancer
---
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
  name: ingress-nginx
  namespace: flux-system
spec:
  interval: 1h
  url: https://kubernetes.github.io/ingress-nginx

Multi-Tenancy with Flux

Create separate namespaces with their own GitRepository and RBAC:

# Platform team defines tenant
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: team-a
  namespace: flux-system
spec:
  interval: 5m
  sourceRef:
    kind: GitRepository
    name: fleet-infra
  path: ./tenants/team-a
  prune: true
  serviceAccountName: team-a    # Scoped RBAC

Team-a’s directory structure:

tenants/team-a/
├── namespace.yaml
├── rbac.yaml
├── git-repository.yaml     # Team A's app repo
└── kustomization.yaml      # Deploys to team-a namespace

Image Automation

Flux can watch ECR for new image tags and update Git automatically:

apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImageRepository
metadata:
  name: my-app
  namespace: flux-system
spec:
  image: 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app
  interval: 1m
  provider: aws    # Uses IRSA for ECR auth
---
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImagePolicy
metadata:
  name: my-app
  namespace: flux-system
spec:
  imageRepositoryRef:
    name: my-app
  filterTags:
    pattern: '^v(?P<version>[0-9]+\.[0-9]+\.[0-9]+)$'
    extract: '$version'
  policy:
    semver:
      range: '>=1.0.0'
---
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImageUpdateAutomation
metadata:
  name: my-app
  namespace: flux-system
spec:
  interval: 1m
  sourceRef:
    kind: GitRepository
    name: fleet-infra
  git:
    commit:
      author:
        name: fluxcdbot
        email: flux@example.com
      messageTemplate: "Update image to {{range .Changed.Changes}}{{.NewValue}}{{end}}"
    push:
      branch: main
  update:
    path: ./clusters/production
    strategy: Setters

Tag the Deployment image with a marker comment:

spec:
  containers:
    - name: my-app
      image: 123456789012.dkr.ecr.us-east-1.amazonaws.com/my-app:v1.0.0  # {"$imagepolicy": "flux-system:my-app"}

Flux vs ArgoCD

Feature Flux ArgoCD
UI No native UI (use Weave GitOps) Built-in web UI
Architecture API-first, CRD-based UI/CLI with API
Multi-tenancy Built-in with service accounts AppProject-based
Helm support HelmRelease CRD Application with Helm source
Image automation Built-in controllers Separate Image Updater
CNCF status Graduated Graduated
Complexity Lower (composable controllers) Higher (monolithic)
Best for Platform teams, automation-first Dev teams wanting a UI

Monitoring Flux

# Check Flux health
flux check

# View all Flux resources
flux get all

# Check sync status
flux get kustomizations
flux get helmreleases

# View events
flux events

Best Practices

  1. Use bootstrap — don’t install Flux manually
  2. Separate infra and app repos — fleet-infra for platform, app repos for dev teams
  3. Enable prune — keep cluster state clean
  4. Use health checks — Flux marks sync as failed if deployments don’t become healthy
  5. Use image automation — eliminate manual image tag updates in Git
  6. Use multi-tenancy — scope team access with service accounts

Updated: