Git, CI/CD & GitOpsLXXVIII · FluxKustomize
Kustomization controller — reconciling Kustomize manifests into the cluster
What you'll learn
- Describe what kustomize-controller does and which CRD it owns
- Read a Kustomization spec and identify the source reference, interval, path, prune, wait, and health-check fields
- Configure prune and dependsOn for a production Kustomization
- Use `flux create kustomization` to manage a Kustomization against a GitRepository source
Prerequisites
Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x
kustomize-controller is the workhorse of a Flux install. It owns
the Kustomization CRD, consumes a source artifact from
source-controller, runs kustomize build against a path inside
that artifact, and applies the rendered manifests into the
target cluster.
What kustomize-controller does
The controller watches Kustomization CRDs. For each one it
performs four phases per reconcile:
- Read source. Look up the source CRD named in
spec.sourceRef, wait for itsReady=Truecondition, and fetch the artifact from the in-cluster URL. - Build. Run
kustomize buildagainstspec.pathinside the artifact. - Diff. Compare the rendered manifest set against the cluster’s live state.
- Apply and prune. Apply the diff into the cluster; prune
any resource present in the previous apply but absent in the
new one if
spec.prune=true.
flowchart LR
K["Kustomization CRD"] --> KC["kustomize-controller"]
KC --> R["Read source artifact"]
R --> B["kustomize build path/"]
B --> D["diff against live state"]
D -->|"diff empty"| OK["Ready=True"]
D -->|"diff present"| AP["server-side apply"]
AP --> K8s["Cluster"]
KC --> H["Health checks"]
The Kustomization spec
The fields that matter:
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: apps
namespace: flux-system
spec:
sourceRef:
kind: GitRepository
name: apps
interval: 10m0s
path: ./clusters/production
prune: true
wait: true
timeout: 5m0s
force: false
healthChecks:
- apiVersion: apps/v1
kind: Deployment
name: payments-api
namespace: payments
dependsOn:
- name: namespaces
spec.sourceRef- the source CRD this Kustomization consumes. The controller waits forReady=True.spec.interval- the reconcile interval. Production default is10m0s.spec.path- the path inside the source artifact tokustomize build. Must contain akustomization.yaml.spec.prune- if true, the controller deletes any resource present in the cluster from a prior apply but absent in the new build.spec.wait- if true, the controller blocks the reconcile until applied resources reportReady.spec.healthChecks- explicit health checks the controller runs alongside the built-inkstatuschecks.spec.dependsOn- an ordered list of Kustomizations that must complete before this one applies.
Creating a Kustomization
flux create kustomization apps \
--source=GitRepository/apps \
--path=./clusters/production \
--prune=true \
--wait=true \
--interval=10m0s \
--depends-on=namespaces \
--export
--source takes Kind/name and resolves to sourceRef.
--depends-on repeats for multiple dependencies. --export
prints the YAML; without it, the command applies the CRD.
Inspect and reconcile:
flux get kustomizations
flux reconcile kustomization apps
flux get kustomization apps --status
flux get kustomizations --status includes the last applied
revision, the last failed revision, and the inventory of
applied objects - the audit answer to “what is running here”.
Pruning, drift, and the apply contract
When spec.prune=true, the controller deletes any cluster
resource it owns that is absent in the new build. The
controller inventories every resource it applies, identified
by the kustomize.toolkit.fluxcd.io/name label. A resource
that was never applied by the controller is not pruned.
Under the hood
The controller’s apply is server-side apply with force ownership. The controller owns every field it applies; any out-of-band change to a managed field is reverted on the next reconcile.
Production discipline
spec.pathcontains akustomization.yaml. A bare manifest directory loses the post-build hooks that make Kustomize worth using.spec.prune=trueis paired with branch protection. A broken PR should not auto-prune before review.spec.dependsOnis used for ordering, not fan-in. Split the tree into smaller Kustomizations.
Cross-course references
- Kubernetes for Production Sysadmins - Parts VII-VIII (Workloads) cover the Deployments the Kustomization applies.
- Git, CI/CD & GitOps for Infrastructure Engineers - Part
LXXVI (GitOps Repo Architecture) is the repository layout
spec.pathpoints at.
Quiz
Knowledge check · 4 questions
Q1. Which field in a Kustomization spec tells the controller to delete any cluster resource it previously applied that is absent from the new build?
Q2. A Kustomization with `spec.prune=false` will leave drift in the cluster and still report Ready=True, because the controller's only contract is to apply the new build, not to delete the old.
Q3. Name the four phases of a kustomize-controller reconcile in order, and identify which phase invokes the kubectl apply.
Q4. Diagnose why a Kustomization is reporting Ready=False, reason=DependencyNotReady, and recommend the fix.
A team runs `flux get kustomizations` and sees that the `apps` Kustomization is reporting Ready=False, reason=DependencyNotReady. The team runs `flux get kustomization apps -o yaml` and sees spec.dependsOn contains a `namespaces` Kustomization that no longer exists. The `namespaces` directory was deleted from the Git tree six weeks ago; the `apps` Kustomization spec was not updated.
Passing score: 75%. Answers are checked in this browser.