Kustomization and Reconciliation
The Kustomization CRD is the apply engine of Flux: it builds manifests from a Source, substitutes variables, decrypts secrets, server-side applies with field ownership, health-checks the result, and prunes what Git removed.
Overview
Where Flux starts changing the cluster
Source controllers produce artifacts; kustomize-controller turns one artifact into applied, health-checked, garbage-collected cluster state. Everything an interviewer means by "how does Flux actually deploy" lives in this one CRD.
Two things called Kustomization
- Flux Kustomization CRD — kustomize.toolkit.fluxcd.io/v1 — The reconciler
- kustomization.yaml file — kustomize.config.k8s.io — The build recipe kustomize reads
Flux points at the directory holding the file via spec.path. With no kustomization.yaml there, it synthesizes one over the plain YAML it finds.
> [!WARNING] Candidates who conflate the two lose credibility immediately: every question about patches, components and overlays depends on knowing which layer you are in.
The reconciliation loop
Each stage maps to a spec field and has its own failure mode.
What separates Flux from a kubectl CI job
- Server-side apply, fieldManager kustomize-controller — Per-field ownership lives in metadata.managedFields; the controller dry-run applies each interval, compares only its own fields and corrects drift without fighting an HPA over spec.replicas
- Client-side kubectl apply (the contrast) — Diffed against a last-applied-configuration annotation that went stale as soon as another actor touched the object
- status.inventory — Ledger of everything the last successful apply produced; makes prune a scoped garbage collector, not a namespace-wide delete
Operational surface for real platforms
- dependsOn — Ordering across Kustomizations, so cert-manager lands before the Ingress that needs its CRDs
- postBuild — Injects cluster-specific values into identical manifests, so one repo drives many clusters
- decryption — Wires SOPS so encrypted Secrets can live in Git
- serviceAccountName — Impersonates a tenant ServiceAccount, so a tenant cannot escalate beyond its RBAC
- force — Handles the immutable-field wall, such as a changed Job selector or Service clusterIP
How interviewers probe this topic
> [!WARNING] A mis-scoped rename plus prune: true deletes a live workload and recreates it seconds later. The end state is correct, and it is still an outage.
Key concepts
- Kustomization CRD
- kustomize.toolkit.fluxcd.io/v1. Describes when and how to reconcile manifests from a Source into the cluster. Distinct from kustomization.yaml (kustomize.config.k8s.io), which is the overlay file that kustomize build reads inside spec.path.
- sourceRef
- Points at the object producing the artifact: GitRepository, OCIRepository, Bucket, or ExternalArtifact. Optional namespace field allows a Kustomization to consume a Source from another namespace, subject to cross-namespace reference policy.
- Inventory
- status.inventory lists group, version, kind, name, and namespace for every object the last successful apply produced. Prune deletes exactly the inventory entries missing from the current build, which is what makes garbage collection scoped rather than cluster-wide.
- Server-side apply and field ownership
- kustomize-controller applies with fieldManager kustomize-controller. Kubernetes records per-field ownership in metadata.managedFields, replacing the client-side last-applied-configuration annotation model and enabling precise drift correction alongside other controllers.
- Drift detection and correction
- Each interval the controller performs a server-side dry-run apply and compares the response against the live object. Differences on Flux-owned fields trigger a real apply plus a change event. spec.ignore exempts specific JSON Pointer paths, such as /spec/replicas on an HPA-managed Deployment.
- postBuild substitution
- Runs after kustomize build. spec.postBuild.substitute is an inline map; substituteFrom pulls variables from a ConfigMap or Secret. Supports bash-style defaults and replacements. Disabled per resource with the annotation kustomize.toolkit.fluxcd.io/substitute set to disabled.
- dependsOn
- Ordering primitive. A Kustomization reconciles only after each listed dependency reports Ready. Pair with wait: true on the dependency so Ready means rolled out. readyExpr adds a CEL predicate for stricter gating, such as requiring matching version labels.
- serviceAccountName impersonation
- The controller assumes the named ServiceAccount in the Kustomization namespace when applying. This is the multi-tenancy control: a tenant Kustomization can only create what that ServiceAccount RBAC permits, regardless of the far broader permissions held by the controller itself.
When to use it
- Applying any directory of Kubernetes manifests from a GitRepository, OCIRepository, or Bucket source with continuous drift correction
- Enforcing deploy ordering across components — infrastructure Kustomization first, then CRDs, then application Kustomizations via dependsOn
- Driving many clusters from one manifest tree, with per-cluster differences supplied by postBuild substituteFrom ConfigMaps
- Multi-tenant clusters where each tenant Kustomization must be constrained to a tenant ServiceAccount via impersonation
- Any workflow that needs Git deletions to become cluster deletions, which requires prune and the inventory
- Managing a remote cluster from a management cluster via spec.kubeConfig without running controllers in the remote cluster
Interview questions
- A Flux Kustomization and a kustomization.yaml are not the same thing. Explain the difference.
- How does Flux detect and correct drift, and how does its field ownership model differ from kubectl apply?
- What exactly does prune delete, and what is the inventory?
- How do you enforce deploy ordering across Kustomizations, and what does Ready actually guarantee?
- Explain postBuild substitution and substituteFrom. When is it the right tool, and when is it a mistake?
- How does Flux enforce multi-tenancy, and what happens if you forget serviceAccountName?
Sign up free to read the full topic
More DevOps topics
- Kubernetes Secrets Management
- Kubernetes Security: Pod Security and Runtime Hardening
- Kubernetes Services
- Kubernetes Storage
- Kubernetes the Hard Way
- Kubescape and Kubernetes Runtime Security
- Lease and Reservation Control Planes
- libstdc++, libc++, glibc and Symbol Versioning
- Lifecycle Hooks and Tests
- Linking Deep Dive
- Linux Cron & Task Scheduling
- Local Kubernetes Cluster Setup (minikube / kind / k3d)
Start free on Cariara · Coding problems · System design studio