Flux v2

CNCF Graduated GitOps tool. Originated at Weaveworks (the GitOps coiners). v2 rewrite from monolithic v1 to modular controllers (GOTK). Multi-tenant via K8s namespaces. Used at Mercedes-Benz, BMW, RingCentral, MOIA. Kustomize-first; tighter K8s-native than Argo CD.

Overview

Flux v2 and the GitOps Toolkit

Flux v2 is the K8s-native GitOps tool from Weaveworks, which coined the term GitOps in 2017. v1 was the original implementation; v2 (released 2021) is a complete rewrite into the GitOps Toolkit (GOTK), a set of composable Kubernetes controllers. It graduated in the CNCF in November 2022, the same month as Argo CD.

Why Flux wins

  • K8s-native idioms — Every concept is a CRD (GitRepository, Kustomization, HelmRelease, Receiver, Provider, ImageUpdateAutomation); RBAC, namespaces, finalizers and status conditions apply uniformly; kubectl get/describe work on everything
  • Multi-tenancy via namespaces — A tenant's GitRepository + Kustomization + HelmRelease live in its namespace, isolated by K8s RBAC; cleaner than Argo CD's bolted-on AppProjects
  • Composable — Thin controllers: install kustomize-controller without helm-controller, or just source + image automation, or write a custom controller consuming source-controller artifacts
  • flux CLI — Bootstrapping, manifest generation, reconciling, debugging; flux bootstrap installs Flux and configures it to manage its own configuration via GitOps
  • CNCF ecosystem — Used at Mercedes-Benz, BMW, RingCentral, MOIA, MyFitnessPal; featured in CNCF case studies

Where Flux has friction

  • Thinner UI — Weave GitOps OSS exists but is less polished; most work happens via flux CLI / kubectl, so UI-driven app teams often prefer Argo CD
  • No single deployment unit — You compose GitRepository + Kustomization (or HelmRelease): more moving parts, more YAML
  • Per-controller sharding — Argo CD's application-controller scales as one; Flux's controllers scale independently: more flexibility, more configuration

When to pick which

  • K8s-native composability: teams comfortable operating controllers, wanting CRD-first patterns and custom extensions — Application teams need a polished UI for sync status, troubleshooting, drift visualization
  • Namespace multi-tenancy with RBAC isolation — A centralized control plane for many clusters: Argo CD's hub-and-spoke is more mature
  • Already on Flux v1: migrating to v2 is more incremental — Argo Rollouts integration: tighter coupling
  • Built-in image automation via ImageUpdateAutomation (Argo CD needs the separate Image Updater)

Three load-bearing concepts

  • GOTK is composable — source, kustomize, helm, notification and image-automation controllers are independent; pick what you need
  • Two-step reconciliation — source-controller fetches; kustomize-controller (or helm-controller) applies. Unlike Argo CD's monolithic application-controller
  • Namespace + RBAC multi-tenancy — Tenant CRDs in the tenant namespace; standard K8s primitives enforce isolation

Key concepts

GitRepository — source CRD
Tells source-controller where to pull manifests from. source-controller fetches at interval; produces an Artifact (in-cluster tarball with checksum). Other controllers consume the Artifact. ref options: branch (mutable; usually main), tag (immutable), semver (range), commit (specific SHA — most reproducible for production). Pin production GitRepository to specific commit or tag, not branch — avoids picking up unintended changes. ignore: gitignore-style filter to exclude paths from the artifact. Reduces artifact size; speeds up downstream rendering. Other source kinds: - HelmRepository — chart repository (https or OCI). - Bucket — S3, GCS, MinIO. - OCIRepository — OCI artifacts (manifests stored in container registry).
Kustomization — apply manifests
kustomize-controller applies Kustomize-rendered manifests to the cluster. prune: true removes resources removed from git (Argo CD equivalent: prune: true in syncPolicy). wait: true blocks reconciliation until the applied resources are Ready (Deployment Available, etc.). Useful for ordering dependent Kustomizations via dependsOn. serviceAccountName: impersonate this ServiceAccount when applying. Used for multi-tenancy: tenant Kustomization runs as tenant ServiceAccount; RBAC restricts what it can apply. postBuild.substitute: variable substitution using ${var} placeholders in the rendered output. Useful for cluster-specific values (region, environment) without per-cluster overlays. healthChecks: explicit health check beyond what wait: true does. Useful for resources with custom health logic. Multiple Kustomizations can chain via dependsOn: Reconciles only after the named Kustomizations are Ready.
HelmRelease — Helm chart deployment
helm-controller applies Helm releases. helm-controller renders the chart with values, installs/upgrades the release, tracks Helm history. Auto-rollback on failure via upgrade.remediation.strategy: rollback. Helm reverts to previous release if upgrade fails health checks. Multiple HelmReleases can chain via dependsOn (same as Kustomization). Compared to ArgoCD's Helm support: Flux's HelmRelease is closer to native Helm semantics (uses helm install/upgrade under the hood); ArgoCD's Helm renders manifests and applies via kubectl. Different reconciliation models; both work.
Multi-tenancy via namespaces
Flux's multi-tenancy story is namespace-native. Tenant CRDs in tenant namespace; K8s RBAC enforces isolation. Setup for tenant payments-team: 1. Namespace per tenant: 2. Tenant ServiceAccount with restricted permissions: 3. Tenant team owns GitRepository + Kustomization in their namespace: Behavior: kustomize-controller impersonates payments-deployer SA when applying. SA only has edit on payments-prod namespace. Tenant cannot deploy to other namespaces, cannot create ClusterRoles, cannot escape their scope. Compared to Argo CD AppProject: similar isolation, different mechanism. Flux uses K8s-native impersonation; Argo CD uses AppProject scope checks. Flux's approach is more idiomatic; Argo CD's allows centralized governance more easily.
Notification controller — Slack/Webhook events
notification-controller is bidirectional: receives webhooks, sends events. Receiver — incoming webhook to trigger reconciliation: Receiver creates a Service exposing /hook/. GitHub webhook hits it; Receiver triggers immediate reconciliation of listed resources. Reduces lag from minutes to seconds. Provider + Alert — outgoing events: Behavior: every Kustomization reconciliation produces an event; Alert filters by severity/source/regex; matching events forwarded to Slack via Provider. Provider types: slack, discord, msteams, rocket, generic, github, gitlab (commit status), webex, sentry, pagerduty, alertmanager. GitHub commit status integration: post sync results back to the commit on GitHub. Adds context to PRs ("deploy to prod-eu-west-1: succeeded").
Recipe: flux bootstrap on EKS with multi-cluster
flux bootstrap installs Flux on a cluster and configures it to manage its own config via GitOps. Step 1 — bootstrap on hub cluster: What this does: - Creates github.com/myorg/gitops-fleet (if missing). - Generates flux-system manifests in clusters/prod-hub/flux-system/. - Commits + pushes to git. - Installs Flux on the cluster. - Configures Flux to reconcile clusters/prod-hub/. After bootstrap, Flux's own manifests live in git. Self-managed. Upgrades happen by editing the gotk-components.yaml in git and pushing. Step 2 — define spoke cluster Kustomizations: Step 3 — bootstrap each spoke cluster: Each spoke runs its own Flux installation. Federated topology — each cluster manages itself from git. No central control plane. Compared to Argo CD hub-and-spoke: Flux federated approach has lower blast radius (hub failure doesn't affect spokes) but higher operational surface (5 clusters = 5 Flux installations). Step 4 — image automation (Flux's killer feature): Setters strategy: in your manifests, mark fields with a comment: Behavior: image-reflector-controller scans GHCR every 5 min; new tag matching semver range → image-automation-controller commits the updated image tag to git → source-controller picks up commit → kustomize-controller applies. Fully GitOps-managed image updates with audit trail (the auto-commit is in git history).

When to use it

  • K8s-native composability matters; want CRD-first patterns
  • Multi-tenant clusters where namespace-based isolation is desired
  • Already on Flux v1 — migration to Flux v2 is incremental
  • GitOps-managed image automation via ImageUpdateAutomation
  • Platform team comfortable extending K8s controllers with custom CRDs

Interview questions

  • Walk through Flux v2 GOTK architecture — five controllers, each role.
  • How does Flux's multi-tenancy compare to Argo CD AppProjects?
  • How does Flux handle image automation (the GitOps for container images)?
  • Federated vs hub-and-spoke — when does each fit?
  • Quick-fire interview answers — Flux essentials.

Sign up free to read the full topic

More DevOps topics

Start free on Cariara · Coding problems · System design studio