A deep dissection of every GitOps Toolkit controller: the Source Controller with its various source types and verification, the Kustomize Controller, the Helm Controller, the Notification Controller, and the Image Automation Controllers.

In episode 2 you learned the five GitOps Toolkit controller groups and their position in the reconciliation flow. Now let's dissect each one: which CRDs each controller provides, how configuration is written, and the technical details that make each of them work. This episode is your core technical reference — feel free to come back here any time you're confused by a term in the hands-on episodes.
The Source Controller is the entry point of the entire flow: it pulls, validates, and stores the source into the cluster as a Kubernetes object. All other controllers read the output of the Source Controller.
Defines a Git repository that is pulled periodically. It can point to a branch, tag, specific commit, or a semver reference:
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: web-app
namespace: flux-system
spec:
interval: 1m
url: https://github.com/acme/web-app
ref:
semver: ">=1.0.0"
verify:
provider: cosignNotice interval: 1m — this determines how often FluxCD checks Git. The ref reference supports branch, tag, commit, and semver, plus submodules and GPG verification support to ensure the source hasn't been tampered with.
HelmRepository points to a chart repository (for example a Helm index), while HelmChart is the derived result that FluxCD produces after fetching the index — this object is what the Helm Controller consumes.
Bucket points to object storage such as S3, GCS, or Azure Blob for manifests stored as artifacts. OCIRepository points to OCI images that contain manifests. More and more teams use the OCI pattern because the artifacts are immutable and verifiable.
Sources can be verified with two mechanisms: GPG (signing Git commits) and Cosign (signing OCI artifacts). With verification, only content signed by trusted keys is allowed into the cluster.
The Kustomize Controller is the main worker: it reads the source (usually from the Source Controller) and materializes manifests into cluster objects.
The Kustomization object specifies which source to use, the path within it, and the target namespace:
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: web-app
namespace: flux-system
spec:
sourceRef:
kind: GitRepository
name: web-app
path: ./deploy
prune: true
interval: 10mThe controller pulls the source, processes the manifests (including a Kustomize kustomization.yaml file if present), then applies the result. prune: true enables garbage collection: objects present in the cluster but no longer in Git will be removed — this keeps the cluster clean and perfectly aligned with the repo.
A Kustomization can declare dependencies on other Kustomizations via dependsOn, guaranteeing the deployment order. The controller also assesses the health of reconciled objects by checking object conditions — for example waiting for a Deployment to reach ready before considering it successful.
The Helm Controller brings Helm's power into the declarative world. Instead of running helm install manually, everything is declared through HelmRelease objects.
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
name: nginx
namespace: web
spec:
chart:
spec:
chart: nginx
version: ">=4.0.0"
sourceRef:
kind: HelmRepository
name: ingress-nginx
values:
controller.replicaCount: 2Values are taken from the chart defaults and can be overridden through the values block, valuesFrom files (from ConfigMap or Secret), or a chart reference. All these strategies can be combined with a clear precedence order.
If an upgrade fails, FluxCD can automatically roll back to the previous release version. The Helm Controller also detects drift: manual changes to a release that aren't in Git will be detected and reconciled back.
Warning
Because the Helm release is fully managed by FluxCD, don't modify a release with a manual helm upgrade on a cluster already managed by a HelmRelease — that change will be treated as drift and reverted.
The Notification Controller turns FluxCD from a silent system into a communicative one.
These three controllers close the image update loop without human intervention:
| CRD | Function |
|---|---|
ImageRepository | Registers the registry and images to scan. |
ImagePolicy | Version selection rules (semver, alphabetical, regex). |
ImageUpdateAutomation | Writes image updates back to Git as commits/PRs. |
The flow: the controller scans the registry, compares against the policy, then ImageUpdateAutomation creates a commit that updates the manifests in Git — and normal FluxCD reconciliation takes over to apply the new version.
Episode 3 completes your technical understanding of the toolkit:
In episode 4 we start real hands-on work: installing FluxCD on your cluster — preparing the prerequisites, choosing the installation method, running flux bootstrap github, and verifying the entire installation. See you there!