Skip to main content
RunBook Academy

Git, CI/CD & GitOpsLXXIV · ReconciliationTools

Flux reconciliation mechanics — GitRepository, Kustomization, the source controller

Advanced⏱ ~24 mingit

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

Not yet marked complete on this device.

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:

  1. Fetches from Git at the specified ref.
  2. Computes the commit SHA and the file contents.
  3. Packages the contents into a tar artifact stored in an in-cluster object storage (the source controller’s internal S3-compatible store).
  4. Writes the artifact’s URL and revision into the GitRepository status 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:

  1. Reads the source controller’s status to find the current artifact URL and revision.
  2. Downloads the artifact (if not cached locally).
  3. Runs kustomize build against the configured path.
  4. Queries the cluster API for the live state of every resource the build produced.
  5. Computes the diff and applies the result.
  6. 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

  1. 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.
  2. 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.
  3. Use flux reconcile for 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

  1. Q1. Which Flux controller is responsible for fetching from Git and producing the artifact that the kustomize-controller consumes?

  2. Q2. flux reconcile kustomization forces the source-controller to refetch from Git.

  3. Q3. Name the three Flux controllers involved in a reconciliation tick and the CRD each one reconciles.

  4. 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.