Flux Architecture
Flux Architecture
Flux is the second major GitOps engine for Kubernetes, created by Weaveworks (who also coined the term "GitOps") and now a CNCF Graduated project. Where ArgoCD presents a monolithic control-plane with a rich UI, Flux takes a radically different philosophy: a composable toolkit of small, focused controllers, each responsible for a single concern, all communicating through Kubernetes Custom Resource Definitions (CRDs). Understanding Flux's architecture is essential because it underpins how large-scale GitOps pipelines are built at companies like Weaveworks, Grafana Labs, and Microsoft Azure's own GitOps service.
This lesson covers the three controller families that make up the Flux control loop — source, kustomize, and helm — and the two CRDs you will write daily: GitRepository and Kustomization.
The Toolkit Philosophy
Flux is not a single binary. It is a set of Kubernetes controllers — called the GitOps Toolkit — each installed as a Deployment in the flux-system namespace. The key controllers are:
- source-controller — watches external sources (Git repos, OCI registries, Helm repos, S3 buckets) and fetches their content. It exposes that content as an in-cluster HTTP artifact server for other controllers to consume.
- kustomize-controller — reads a
KustomizationCRD, pulls the manifests artifact from source-controller, runskustomize build, and applies the result to the cluster. Despite the name, it can apply plain YAML too — Kustomize is optional. - helm-controller — reads a
HelmReleaseCRD, pulls aHelmChartartifact from source-controller, and performs Helm install/upgrade/rollback operations. It replaces the need to runhelmimperatively in CI pipelines. - notification-controller — routes events from all other controllers to external systems (Slack, Teams, PagerDuty, GitHub commit statuses, webhooks). This enables rich observability without polluting the reconciliation controllers with notification logic.
- image-reflector-controller + image-automation-controller — scan image registries for new tags and automatically write updated image references back to the Git repository. This closes the loop for fully automated delivery pipelines.
Installing Flux: The Bootstrap Command
Flux is bootstrapped with the flux CLI, which creates the flux-system namespace, installs all controller Deployments, and commits the resulting manifests back to your Git repository — so Flux immediately manages itself via GitOps.
The GitRepository CRD: Source Controller in Depth
A GitRepository object tells source-controller where to fetch content and how often to check for changes. It is the entry point for any Git-backed GitOps pipeline. When source-controller successfully fetches and archives a revision, it updates the object's .status.artifact field with a URL pointing to a tarball on its built-in HTTP server — which other controllers reference to download manifests without needing Git credentials themselves.
After applying, you can inspect the artifact status with flux get source git gitops-fleet. A healthy output shows a non-empty URL in the ARTIFACT REVISION column. If the column is empty or shows failed, check kubectl -n flux-system describe gitrepository gitops-fleet — the Conditions section explains precisely what failed (auth error, SSH host key mismatch, network timeout, etc.).
The Kustomization CRD: Kustomize Controller in Depth
The Kustomization CRD (not to be confused with the Kustomize kustomization.yaml file) instructs kustomize-controller to take an artifact from a source, optionally run it through Kustomize, and apply the result to the cluster. It is the primary reconciliation object you will create for every workload.
prune: true: Without prune: true, resources deleted from Git will remain in the cluster indefinitely. This is the most common source of "ghost" resources in Flux-managed clusters — old Deployments, Services, and CronJobs that nobody remembers but that still consume resources and occasionally break things. Always set prune: true in production. The risk of accidental deletion is mitigated by the fact that the deletion itself is a git commit that can be reverted.The Helm Controller and HelmRelease CRD
The helm-controller removes the need to run helm upgrade --install in CI pipelines, which is stateless and difficult to observe. Instead, you declare the desired Helm release state in a HelmRelease CRD and the controller owns the full release lifecycle — install, upgrade, test, rollback, and uninstall — recording history in Helm's release secrets just as a manual helm CLI would.
HelmRelease manifest while environment-specific overrides come from a ConfigMap referenced by valuesFrom. This avoids duplicating entire values blocks across staging and production HelmRelease objects — a common cause of configuration drift when teams copy-paste manifests. Use spec.valuesFrom referencing a ConfigMap or Secret for any values that differ per environment.Observing Flux Reconciliation in Real Time
Understanding reconciliation status is critical for debugging deployments. Flux provides first-class observability through the CLI and Kubernetes events.
Production Failure Modes and How to Diagnose Them
The most common Flux failure patterns in production, and how to resolve each:
- GitRepository stuck on "GitOperationFailed": Almost always an SSH key rotation or GitHub token expiration. Check the Secret referenced by
secretRef, recreate it with the new credential, thenflux reconcile source git <name>. - Kustomization "health check timeout": A resource applied by Flux failed its own readiness check (e.g., a Deployment that never reaches its desired replica count). The Kustomization itself is healthy — the underlying workload is not. Debug the workload directly:
kubectl describe pod,kubectl logs. - HelmRelease stuck in "upgrade retries exhausted": The chart values are invalid or the chart has a bug. Flux will have rolled back automatically if
remediateLastFailure: true. Inspect the Helm history:helm history ingress-nginx -n infrastructureto see which revision failed and what error Helm returned. - Drift not being corrected: Verify
intervalhas elapsed and that the Kustomization's.status.lastAppliedRevisionmatches the Git HEAD. A mismatch means source-controller has new content that kustomize-controller has not yet consumed — check source-controller logs.
Summary
Flux's toolkit architecture separates fetching (source-controller), rendering (kustomize-controller), and releasing (helm-controller) into independent, replaceable components. The GitRepository CRD is your entry point for any Git-backed source, and the Kustomization CRD is the reconciliation object that translates Git content into live cluster state. Mastering these two CRDs — and understanding how source-controller's artifact model decouples credential handling from reconciliation — is the foundation for building production-grade Flux pipelines covered in the next lessons.