Flux
Summary
- Flux is a set of Kubernetes controllers (the GitOps Toolkit) that reconcile a cluster from Git, splitting "fetch the source" from "apply the manifests" into separate resources.
- Insight: Flux is composable. Source, kustomize, helm, notification, and image controllers each own one job, so you install only what you need.
- Key Concepts: GitRepository, Kustomization, HelmRelease, dependsOn, image automation.
- When to Use: Teams that want a lightweight, per-cluster, CLI-and-YAML workflow without a central UI, and native registry-driven image updates.
- Limitations: No built-in visual diff UI; observability comes from
fluxCLI, events, and metrics rather than a dashboard. - Related: Argo CD for a UI-centric alternative; drift detection for the reconciliation behavior.
Recipe
Install the controllers, then declare a source and a Kustomization that applies a path from it.
flux installCommit a GitRepository and a Kustomization, apply them once, and Flux reconciles on its interval from then on.
kubectl apply -f flux/web.yaml
flux get kustomizationsWorking Example
A source that polls the repo, and a Kustomization that applies an overlay with pruning and health checks.
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: manifests
namespace: flux-system
spec:
interval: 1m
url: https://github.com/acme/manifests.git
ref:
branch: main
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: web
namespace: flux-system
spec:
interval: 5m
retryInterval: 1m
timeout: 3m
sourceRef:
kind: GitRepository
name: manifests
path: ./apps/web/overlays/prod
prune: true
wait: true
healthChecks:
- apiVersion: apps/v1
kind: Deployment
name: web
namespace: webwait: true with a healthCheck makes the Kustomization report Ready only after the Deployment is actually available.
prune: true deletes cluster resources when they are removed from Git, keeping the cluster a faithful projection of the repo.
For Helm charts, Flux uses a HelmRepository source and a HelmRelease.
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: ingress-nginx
namespace: flux-system
spec:
interval: 10m
chart:
spec:
chart: ingress-nginx
version: "4.x"
sourceRef:
kind: HelmRepository
name: ingress-nginx
values:
controller:
replicaCount: 2Deep Dive
Source separated from apply
The source-controller fetches artifacts. A GitRepository clones the repo at an interval and stores the commit as an internal artifact.
The kustomize-controller consumes that artifact. A Kustomization renders path and applies the result to the cluster.
This separation means one GitRepository can feed many Kustomization objects, each reconciling a different path on its own interval.
Ordering with dependsOn
Flux expresses ordering between Kustomizations declaratively.
spec:
dependsOn:
- name: crds
path: ./apps/webThe web Kustomization will not apply until the crds Kustomization is Ready, which prevents "no matches for kind" errors.
Bootstrap
flux bootstrap is the recommended install path. It commits Flux's own manifests into your repo and configures Flux to manage itself.
flux bootstrap github \
--owner=acme \
--repository=manifests \
--branch=main \
--path=clusters/prodAfter bootstrap, Flux is itself under GitOps: upgrading Flux is a commit to the flux-system path.
Image automation
Flux can watch a registry and write new tags back into Git, closing the loop from build to deploy.
Three resources cooperate. An ImageRepository scans tags, an ImagePolicy selects one, and an ImageUpdateAutomation commits the change.
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImagePolicy
metadata:
name: web
namespace: flux-system
spec:
imageRepositoryRef:
name: web
policy:
semver:
range: ">=1.0.0"A marker in the manifest tells Flux where to write the selected tag.
image: registry.example.com/web:1.4.2 # {"$imagepolicy": "flux-system:web"}The images themselves are built by Docker/BuildKit and pushed to the registry; Flux only tracks which tag Git should pin.
Notifications
The notification-controller sends events to Slack, Teams, or Git providers, and receives webhooks to trigger immediate reconciliation instead of waiting for the interval.
Gotchas
Forgetting prune: true leaves deleted-from-Git resources running in the cluster, silently accumulating orphans.
A Kustomization stuck Reconciling with wait: true usually means the health check target never became ready; inspect the Deployment, not Flux.
dependsOn references must be in the same namespace unless you qualify them; a typo leaves the dependent Kustomization waiting forever.
Image automation needs write access to Git. If the deploy key is read-only, the ImageUpdateAutomation cannot commit and updates silently stall.
Editing a live resource that Flux manages is temporary; the next reconciliation reverts it, which is drift correction working as designed.
Alternatives
Argo CD offers a UI, projects, and ApplicationSets, at the cost of a heavier central component. See Argo CD.
Plain Kustomize with kubectl apply -k in CI is push-based and does not reconcile continuously or correct drift.
Helm alone installs charts but lacks a reconciliation loop; Flux's HelmRelease adds continuous reconciliation around Helm.
FAQs
Does Flux need a central cluster? No. Flux is typically installed into each cluster it manages, which keeps the blast radius per cluster.
How do I see status without a UI? Use flux get kustomizations, flux get sources git, and Kubernetes events; Flux also exports Prometheus metrics.
Can Flux and Argo CD coexist? Yes, but avoid pointing both at the same resources, or they will contend over the same fields.
How are secrets handled? With SOPS-encrypted files that the kustomize-controller decrypts, Sealed Secrets, or an external secrets operator.
What runs the pods Flux applies? containerd via CRI on the nodes; Docker Engine is only the build tool, never the in-cluster runtime.
How fast does Flux react to a commit? On the GitRepository interval by default, or immediately if you wire a provider webhook to the notification-controller.
Related
Stack versions: This page was written for Kubernetes 1.36.2, Docker Engine 29.6.1 (BuildKit default), containerd (CRI runtime on nodes), Helm 3, Compose v2, Argo CD (latest - verify at build), and Gateway API (GA - verify controller support at build).