# Flux — Derived Rules > Derives from `domains/gitops-operators/first-principles.md`. > Applies P1–P10 to Flux specifically. For the ArgoCD-vs-Flux > decision, see the decision matrix at the end of this doc and in > `argocd.md`. ## What Flux Is (P1 Git is the Source of Truth, P3 Pull, Don't Push) - Flux is a set of composable controllers — the GitOps Toolkit — that run inside the target cluster, pull desired state from git or OCI registries, and reconcile the cluster to match. CI never holds `kubectl` rights against the cluster (P3). - The composable-controller architecture is a C6 (Composability) exemplar: each controller does one thing (source, kustomize, helm, notification) and the controllers compose into a full GitOps system. - Flux supports Helm releases, Kustomize overlays, and raw manifests — see `domains/kubernetes/helm.md` and `domains/kubernetes/kustomize.md`. ## GitOps Toolkit Controllers (P6 Composability, P4 Continuous Reconciliation) - **source-controller** — pulls git, Helm, OCI, and bucket sources; emits artifacts (tarballs) with a digest. The source is the pinned input to reconciliation (P5 versioning by digest). - **kustomize-controller** — reconciles Kustomization CRDs against the artifacts from source-controller. Runs continuously (P4). - **helm-controller** — reconciles HelmRelease CRDs against Helm charts from source-controller. - **notification-controller** — emits events and notifications for sync, health, and source-readiness events (P9). - **image-automation-controller** (optional) — updates git with new image tags when a policy matches, closing the "latest image" loop declaratively. ## Kustomization CRD (P2 Declarative Over Imperative, P4) - A Kustomization binds "this source" to "this target namespace" with a reconciliation interval. The reconciler loops continuously; drift is corrected automatically (P4). ```yaml apiVersion: kustomize.toolkit.fluxcd.io/v1 kind: Kustomization metadata: name: payments-api namespace: flux-system spec: sourceRef: kind: GitRepository name: platform namespace: flux-system path: ./manifests/prod targetNamespace: payments interval: 1m prune: true wait: true healthChecks: - apiVersion: apps/v1 kind: Deployment name: payments-api namespace: payments ``` - `prune: true` deletes resources removed from git. `wait: true` waits for health checks before declaring the Kustomization ready. Disable prune for workloads that need manual removal gates. ## HelmRelease CRD (P6 Composability, cross-link helm.md) - A HelmRelease binds a Helm chart (from a HelmRepository or OCI source) to target values and a target namespace. helm-controller renders and applies it. See `domains/kubernetes/helm.md` for the chart model. - Pin the chart version in the HelmRepository or the HelmRelease. Never float `latest` — unversioned charts drift (P5). ## OCI Sources (P5 State is Immutable and Versioned) - source-controller can pull from OCI registries (Helm charts as OCI artifacts, or generic OCI repositories). The digest is the version — immutable by construction (P5). - OCI sources close the supply-chain loop: the manifest is signed and immutable in the registry, and Flux pulls it by digest. Cross- link `domains/security/supply-chain.md` for signed-provenance principles. ## Reconciliation and Drift (P4 Continuous Reconciliation, P8) - Flux reconciles on `interval` (default 1m) and on webhook event. Drift between git and cluster is detected each interval and corrected (with `prune` + `selfHeal` semantics). - Hand-edited drift on a Flux-managed resource is overwritten on the next loop — the hand edit was never truth (P8). The recovery is to fix git, not to `kubectl apply`. ## Notifications and Events (P9 Failure is Observable and Surfaced) - notification-controller emits events for source readiness, sync success/failure, and health transitions. Wire them to Slack, PagerDuty, or a webhook. Silent drift is the bug (P9). - Events flow to `domains/observability/metrics.md` via the notification controller's provider model — sync and health as first-class signals. ## RBAC and Multi-Cluster (P10 Least Privilege Reconciliation, P4) - Flux's controllers run with a ServiceAccount in `flux-system`. Scope that account to the namespaces Flux reconciles. Do not bind it to `cluster-admin` (P10). See `domains/kubernetes/rbac.md` and `domains/security/authorization.md`. - Flux is per-cluster by design (one Flux install per cluster). For multi-cluster, use one repo with per-cluster paths, or a fleet tool that bootstraps Flux per cluster. Per-cluster autonomy is a feature, not a limitation — it bounds the blast radius of a compromised controller (P4 locality, P10). ## Secrets (P10, cross-link security/secrets) - Do not store raw Secrets in the GitOps repo. Use the SOPS-compatible decryption in kustomize-controller, or External Secrets Operator, so the git store holds encrypted material only. See `domains/security/secrets.md`. ## ArgoCD vs Flux — Decision Matrix (IDEATE-21, D-039) | Axis | ArgoCD | Flux | |------|--------|------| | Architecture | Monolithic controller + Application CRD | Composable GitOps Toolkit controllers (source, kustomize, helm, notification) | | Reconciliation unit | Application (one CRD per app) | Kustomization / HelmRelease (one per deploy unit) | | UI | Web UI + CLI (full dashboard, tree view, diff viewer) | CLI-first; UI via Weave GitOps or FluxUI (add-on) | | Sync model | Periodic poll or webhook; sync waves + hooks | Poll + webhook; runs continuously, no explicit sync waves | | Multi-cluster | One ArgoCD manages many clusters (hub-and-spoke) | One Flux per cluster (per-cluster autonomy) | | Templating in repo | Helm, Kustomize, ksonnet, raw manifests, Jsonnet | Helm, Kustomize, raw manifests | | RBAC | Built-in RBAC + SSO + AppProjects | Kubernetes RBAC (no built-in RBAC layer) | | Progressive delivery | Argo Rollouts (sister project, tight integration) | Flagger (sister project, tight integration) | | Best for | Teams wanting a UI, multi-cluster from one pane, App-of-Apps bootstrapping | Teams wanting composable controllers, per-cluster autonomy, minimal footprint | | Watch out for | Monolithic controller scaling, UI as ops crutch, AppProject sprawl | No native UI, steeper learning curve, manual multi-cluster orchestration | - Use Flux when you want composable controllers, per-cluster autonomy, and a minimal footprint. Use ArgoCD when you want a UI, central multi-cluster management, and sync-wave ordering. - Both are CNCF graduated and both implement the OpenGitOps principles. The choice is architectural fit, not correctness. See `argocd.md` for the ArgoCD-side perspective. ## What Violates Flux Discipline | Violation | Principle | |-----------|-----------| | CI pipeline with `kubectl` rights pushing to the cluster | P3 Pull, Don't Push | | HelmRelease with no pinned chart version | P5 State is Immutable and Versioned | | Flux ServiceAccount bound to `cluster-admin` | P10 Least Privilege Reconciliation | | Kustomization with no `healthChecks` on a prod app | P9 Failure is Observable and Surfaced | | No notification provider wired for sync failures | P9 Failure is Observable and Surfaced | | Raw Secret in the GitOps repo | P10, `domains/security/secrets.md` | | Manual `kubectl edit` on a Flux-managed resource | P8 Reconcile, Don't Mutate by Hand | | `interval: 24h` on a prod Kustomization (drift window too wide) | P4 Continuous Reconciliation |