Git, CI/CD & GitOpsLXXIV · ReconciliationTools
Flux reconciliation mechanics — GitRepository, Kustomization, the source controller
What you'll learn
- Identify the three Flux controllers involved in a reconciliation tick and what each one does
- Trace the path of a commit from GitRepository through Kustomization to cluster apply
- Explain the role of the source-controller and the artifact it produces for downstream controllers
- Use flux reconcile kustomization as the operator-facing lever for forcing a tick
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
Flux splits reconciliation across controllers that communicate through Kubernetes custom resources. The split is more modular than Argo CD’s: each controller is its own deployment, runs its own loop, and exposes its own CRD. The source-controller watches Git and produces an artifact; the kustomize-controller consumes the artifact, renders manifests, and applies them. The helm-controller does the same for Helm releases.
flowchart LR
G["Git repo"] -->|"fetch"| SC["Source controller"]
SC -->|"GitRepository CR"| ART["Artifact (tar / oci)"]
ART -->|"consume"| KC["Kustomize controller"]
KC -->|"Kustomization CR"| K8S["Cluster API"]
K8S -->|"observed"| KC
SC -->|"HelmRelease source"| HC["Helm controller"]
HC -->|"apply"| K8S
The diagram shows the three controllers and the Kubernetes CRDs that link them. Each controller runs its own reconciliation loop on its own CRD; the CRDs are the contract.
The source controller
The source controller’s job is to fetch source material - Git repositories, Helm repositories, OCI artifacts, S3 buckets - and produce a stable artifact that downstream controllers consume.
A GitRepository CRD describes what to fetch:
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: payments-api
namespace: flux-system
spec:
interval: 1m
url: https://github.com/example/payments-api
ref:
branch: main
The source controller reconciles this CRD on the configured interval. Each tick:
- Fetches from Git at the specified ref.
- Computes the commit SHA and the file contents.
- Packages the contents into a tar artifact stored in an in-cluster object storage (the source controller’s internal S3-compatible store).
- Writes the artifact’s URL and revision into the
GitRepositorystatus subresource.
The artifact is the contract between the source controller and downstream controllers. The kustomize-controller does not fetch from Git directly; it reads the artifact URL from the GitRepository’s status.
The kustomize controller
The kustomize controller’s job is to consume artifacts from the source controller, render manifests, and apply them.
A Kustomization CRD describes what to apply:
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: payments-api
namespace: flux-system
spec:
interval: 10m
sourceRef:
kind: GitRepository
name: payments-api
path: ./clusters/production
prune: true
wait: true
timeout: 5m
The kustomize controller reconciles this CRD on the configured interval. Each tick:
- Reads the source controller’s status to find the current artifact URL and revision.
- Downloads the artifact (if not cached locally).
- Runs
kustomize buildagainst the configured path. - Queries the cluster API for the live state of every resource the build produced.
- Computes the diff and applies the result.
- Records the revision, the apply status, and any inventory metadata in the Kustomization’s status subresource.
The kustomize controller is the closest analogue to Argo CD’s application controller. It does the diff, the apply, and the status reporting. It differs from Argo CD in that the source controller is a separate process - the kustomize controller does not fetch from Git directly.
The helm controller
The helm controller handles Helm releases. It consumes a
HelmRepository (or GitRepository for chart sources) and a
HelmRelease CRD:
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: payments-api
namespace: flux-system
spec:
interval: 10m
chart:
spec:
chart: payments-api
version: "1.2.3"
sourceRef:
kind: HelmRepository
name: payments-api
The helm controller runs the same kind of loop as the kustomize
controller, but with Helm-specific rendering. The controller
downloads the chart, runs helm template with the release’s
values, computes the diff against the live release, and applies
the upgrade. It records the revision, the chart version, and the
release status in the HelmRelease’s status subresource.
The operator-facing lever
flux reconcile kustomization "$KS_NAME"
This Flux CLI command forces an out-of-band reconcile of a
Kustomization. The kustomize controller receives the annotation,
drops its cached observed state, and runs a fresh tick. The
source controller is not triggered; the reconcile uses the
artifact the source controller already published. To force the
source controller to refetch from Git, use flux reconcile source git "$SOURCE_NAME".
The CLI commands map onto the CRDs they reconcile:
flux reconcile source git <name>- the GitRepository CRD.flux reconcile kustomization <name>- the Kustomization CRD.flux reconcile helmrelease <name>- the HelmRelease CRD.
Status subresources and the contract between controllers
The contract between Flux controllers is the status subresource on each CRD. The source controller publishes the artifact URL and revision in the GitRepository’s status; the kustomize controller reads it. The kustomize controller publishes the apply status and the inventory in the Kustomization’s status; Flux’s CLI and dashboards read it.
The status subresource is what makes the modular split work. A controller does not need to know what other controllers are doing; it only needs to read and write the status fields it cares about. A failure in one controller’s status update does not block the other controllers - they continue with their last known state until the failing controller recovers.
Production discipline
- Tune the source and reconcile intervals independently. The source controller fetches from Git on its own cadence (typically one minute); the kustomize controller renders and applies on its own (typically ten minutes). Tightening one without the other either wastes work or underuses capacity.
- Watch the source-controller’s artifact store. The in-cluster S3-compatible store is small and ephemeral. A misconfigured source controller can fill it; a healthy one keeps it bounded. The store’s disk usage is a metric worth dashboarding.
- Use
flux reconcilefor the common case, not the broken case. Forcing a reconcile is the right tool for “I just committed and want it applied now”. It is the wrong tool for “the loop is failing” - that requires reading the logs and fixing the underlying problem.
Cross-course references
- Kubernetes for Production Sysadmins - Parts on custom resources and controllers cover the underlying pattern Flux inherits.
- Helm for Production Sysadmins - Parts on Helm release management cover the helm-controller’s domain.
- Terraform for Production Sysadmins - Parts on the operator pattern cover the pull analogue for infrastructure.
Quiz
Knowledge check · 4 questions
Q1. Which Flux controller is responsible for fetching from Git and producing the artifact that the kustomize-controller consumes?
Q2. flux reconcile kustomization forces the source-controller to refetch from Git.
Q3. Name the three Flux controllers involved in a reconciliation tick and the CRD each one reconciles.
Q4. Diagnose which Flux controller is failing based on the symptoms and propose the right remediation.
Team P runs Flux with a GitRepository named 'infra', a Kustomization named 'production', and several HelmReleases. The team committed a change 25 minutes ago. `flux get kustomizations` shows production is 'Ready' with the old revision; `flux get sources git` shows infra is 'Ready' with the new revision. The HelmReleases show 'Ready' with the new revision. The team is confused why the Kustomization has not picked up the new commit.
Passing score: 75%. Answers are checked in this browser.