Migration and Production Patterns
Moving to Flux v2 from Flux v1, the Helm Operator, or an imperative CI pipeline — then the operational patterns that keep Flux healthy at hundreds of clusters: sharding, concurrency tuning, webhooks, self-upgrade, and disaster recovery.
Overview
Getting there, and growing
Two things separate a team that has read about Flux from a team that runs it: how they got there, and what they changed once the estate got large. Both come up in interviews because both are where the real decisions live.
Three migration paths into Flux v2
- Flux v1 — An architecture change — Daemon flags and workload annotations become custom resources; garbage collection stops needing cluster-wide discovery access; applies become atomic after server-side validation, so latent invalid manifests surface on day one
- Helm Operator — Narrower but fiddlier — API group moves to helm.toolkit.fluxcd.io/v2; inline chart splits into a separate HelmRepository or GitRepository source; values sources change shape and lose cross-namespace references; rollback becomes structured install and upgrade remediation
- Imperative CI pipeline — The most common case, and not really a tooling migration — A change in who holds cluster credentials
The honest Argo CD answer
There is no automated converter.
- Application — Kustomization or HelmRelease
- Sync waves — spec.dependsOn
- Projects — Namespaces plus RBAC
- ApplicationSet — Does not map cleanly
- UI — Not in Flux core
> [!TIP] Saying that plainly reads as judgment; claiming full parity reads as a sales pitch.
Scaling levers, in order
- Vertical — Raise --concurrent, raise CPU and memory limits, run kustomize builds on a tmpfs /tmp, cache Helm indexes, give source-controller a PVC so artifacts survive restarts
- Horizontal — Each instance owns a labeled subset; the main instances exclude sharded resources with a negated selector
- Latency — Intervals long enough not to hammer Git and the API server; Receivers for responsiveness
Flux manages itself
Upgrading Flux is a commit like any other, and customizing Flux is a Kustomize patch like any other.
> [!WARNING] A bad patch to gotk-components.yaml is applied by the very controllers it breaks.
Disaster recovery
If cluster state is entirely in Git, rebuilding is flux bootstrap against the same repository.
- Controllers, sources, Kustomizations, HelmReleases — Secrets
- PVC declarations — Persistent volume data
> [!IMPORTANT] An interviewer asking about DR is usually checking whether you know that boundary.
Key concepts
- Annotation model to CRD model
- Flux v1 configured behaviour with daemon flags and per-workload annotations such as fluxcd.io/automated and fluxcd.io/ignore. Flux v2 configures everything with custom resources. The direct equivalent of fluxcd.io/ignore is the kustomize.toolkit.fluxcd.io/reconcile: disabled annotation, and the equivalent of downscaling the v1 daemon to pause is spec.suspend on a single object.
- Atomic server-side validated apply
- Flux v2 applies a Kustomization only if server-side validation of the whole set passes. One invalid manifest blocks every resource in that Kustomization. Flux v1 applied what it could. This is the most common surprise during a v1 to v2 migration and it is a correctness improvement, not a regression.
- HelmRelease v1 to v2
- helm.fluxcd.io/v1 becomes helm.toolkit.fluxcd.io/v2. The inline spec.chart.repository/name/version splits into a HelmRepository source plus spec.chart.spec.sourceRef. valuesFrom entries become kind plus name plus valuesKey with no cross-namespace references. Helm v2, downloader plugins, and external URL values are removed.
- --watch-label-selector
- The sharding flag. A shard runs with --watch-label-selector=sharding.fluxcd.io/key=shard1 and the main instance with --watch-label-selector=!sharding.fluxcd.io/key so the two sets are disjoint. Supported by source-controller, kustomize-controller and helm-controller; notification-controller does not shard.
- --concurrent
- Number of reconciliations a controller runs in parallel. The documented high-scale tuning raises it to 10 on kustomize-controller, helm-controller and source-controller, paired with container limits around 2000m CPU and 2Gi memory. This is the first lever to pull, before sharding.
- --requeue-dependency
- How often a controller re-checks whether the dependencies named in spec.dependsOn have become ready. The tuned reference value is 5s. Too high and dependency chains deploy slowly; too low and a deadlocked chain generates constant API traffic for nothing.
- Receiver
- notification.toolkit.fluxcd.io/v1 resource that creates an inbound webhook endpoint on notification-controller (port 9292 behind the webhook-receiver Service). An HMAC token in a Secret authenticates the payload, and a matching event triggers immediate reconciliation of the listed resources instead of waiting for the interval.
- flux-system Kustomization
- The self-referential loop created by bootstrap. gotk-components.yaml holds the controller Deployments and gotk-sync.yaml holds the GitRepository and Kustomization that reconcile them. Upgrading Flux means committing a new gotk-components.yaml; customising Flux means adding a Kustomize patch alongside it.
When to use it
- Planning a move off archived Flux Legacy or the archived Helm Operator, where there is no upstream support and no path back
- Replacing a CI pipeline that holds long-lived cluster credentials — the security case for pull-based delivery is usually stronger than the workflow case
- An estate that has outgrown a single controller instance: hundreds of Kustomizations, large monorepos, or reconcile queues that never drain
- Multi-tenant platforms that need blast-radius isolation between teams at the controller level, not just at the namespace level
- Designing cluster disaster recovery, where the question is what reconciles back from Git and what does not
- Evaluating Flux against Argo CD when non-platform stakeholders need self-service visibility into sync status
Interview questions
- Walk me through migrating a team from Flux v1 to Flux v2. What has no direct equivalent?
- How do you migrate a CI pipeline that runs helm upgrade --install to Flux, without an outage?
- An estate has 400 Kustomizations across 60 clusters and reconciles are falling behind. How do you scale Flux?
- How does Flux manage and upgrade itself, and what can go wrong with that?
- A cluster is gone. How do you rebuild it with Flux, and what does not come back?
- Give me an honest comparison of moving between Argo CD and Flux, and what Flux does not have.
Sign up free to read the full topic
More DevOps topics
- Lifecycle Hooks and Tests
- Linking Deep Dive
- Linux Cron & Task Scheduling
- Local Kubernetes Cluster Setup (minikube / kind / k3d)
- Log Aggregation
- Microservices Design
- Monitoring and Troubleshooting
- Monorepo Build Systems
- MSVC Toolchain and Windows Native Build
- Multi-Cluster GitOps
- Native Artifact Signing and Release
- Native Debugging — gdb, Core Dumps and Symbols
Start free on Cariara · Coding problems · System design studio