Flux — GitOps Toolkit for Kubernetes
Overview
Flux CD1 — Open-source continuous delivery solution for Kubernetes
Terminology
Deterministic State Machine (for Kubernetes clusters)
- Keeps clusters in sync with configuration sources
- Translates the configuration source through a series of orchestrated controllers and Custom Resource Definitions (CRDs)
Declarative Idempotency
Desired configuration state is continuously enforced. Closely relation to:
- Continuous Delivery — Deliver software updates frequently and reliably.
- Continuous Deployment — Automatically deploy code changes to production (after automated testing).
GitOps2
- Infrastructure and applications managed declaratively with Git as source of truth
- Key principles:
- Entire system described declaratively
- State is version controlled (Git)
- Automated process ensures deployed state matches repository state
- A human can change state only through version-controlled mechanisms
- Flux implements the GitOps loop: Git → reconcile → cluster → status back to Git_
- Gitless GitOps
- Flux pioneered “Gitless GitOps”3 in 2022 with the
OCIRepositorysource type. - Artifacts stored in OCI registries instead of Git
- Same reconciliation model …different source backend -Useful for binary manifests, Helm charts, container images
- Flux pioneered “Gitless GitOps”3 in 2022 with the
Sources4
- Origin of a repository containing the desired state of the system
- Sources produce an artifact that is consumed by other Flux components to perform actions, like applying the contents of the artifact on the cluster.
- The origin of the source is checked for changes on a defined interval, if there is a newer version available that matches the criteria, a new artifact is produced.
Reconciliation
All Flux controllers follow the same pattern5 by execution a continuous deployment loop:
- Watch a Custom Resource (e.g.,
GitRepository) - Fetch the latest artifact from the source
- Compare current state against desired state
- Apply changes to the cluster
- Report status back to the Custom Resource
Each controller runs on a configurable reconciliation interval (default: every 1–2 minutes).
A Source is the upstream location where the raw configuration or artifact lives before Flux uses it. Sources are always read-only relative to the cluster. The term resource has two related meanings depending on context:
- Target Resources — The actual Kubernetes objects (Deployments, Services, PVCs) that live in your cluster. When Flux applies a Kustomization or HelmRelease, it creates, updates, or deletes these target resources. You can audit them with flux tree.
- Flux Resources — Flux’s own internal Custom Resources, such as Kustomization and HelmRelease. These act as the instructions telling Flux how to process a Source and apply changes to Target Resources.
Architecture
The GitOps Toolkit6 is a modular architecture…
- …collection of specialized tools, Flux Controllers, composable APIs, Go packages
- …continuous Delivery workflow on Kubernetes using GitOps principles
Rather than a single monolithic application, Flux is a collection of independent controllers:
| Controller | Description |
|---|---|
| Source Controller7 | Watches Git repos, Helm charts, OCI repos, buckets; downloads artifacts |
| Kustomize Controller8 | Reconciles Kustomization resources; applies manifests from sources |
| Helm Controller9 | Reconciles HelmRelease resources; manages Helm chart lifecycle |
| Image Automation Controller10 | Triggers updates when container image tags change |
| Notification Controller11 | Sends alerts (Slack, Discord, webhook, etc.) on events |
Kustomization
Kustomization is a custom resource (CRD) controlled by the Kustomize Controller. — It acts as the engine that takes configuration fetched from a Source and deploys it directly into your Kubernetes cluster.
- Source — Points to a specific
GitRepository(or other artifact) and defines the exact path within that source containing your YAML manifests. - Transformation — Before applying the manifests to your cluster, it runs them through Kustomize transformations. This lets you dynamically patch things—like changing image tags, injecting a default namespace, or adding labels—without modifying the original upstream code.
- Application & Pruning — Ensures the cluster matches the source exactly
- If a Deployment exists in the source but not the cluster, it creates it.
- If a resource already exists, it updates it.
- If a resource was deleted from the source automatically prune (delete) it from the cluster.
Kustomization vs. HelmRelease: Both are applicable in Flux, but they process different formats
- Kustomization — Deploying raw
.yamlmanifests, or standard Kubernetes configurations - HelmRelease — Deploying applications that rely on templated Helm charts
Installation
Download the flux CLI binary12 or use flux-install13
Simple example of Flux controllers based on Kubernetes with kind14:
kind create cluster --name flux-demo
# Check that your cluster meets all the required prerequisites
flux check --pre
# Installs only the Flux controllers (CRDs + Controllers) into your cluster
flux install
kubectl -n flux-system get pods
# clean up
kind delete flux-demoflux bootstrap15 installs and sets up the GitOps self-hosting loop.
Bootstrap
The process of installing the Flux components in a GitOps manner is called a bootstrap. Flux integrates with popular Git providers16 to simplify the initial setup of deploy keys and other authentication mechanisms.
The manifests are applied to the cluster, a GitRepository and Kustomization are created for the Flux components, then the manifests are pushed to an existing Git repository (or a new one is created).
Manifest path to a particular cluster’s definitions under $CLUSTER_PATH/flux-system/:
| File | Description |
|---|---|
gotk-components.yaml |
Pre-generated manifest used by Flux to install its core components into your Kubernetes cluster |
gotk-sync.yaml |
Manifest that tells Flux where and how to sync your cluster state from Git |
kustomization.yaml |
Declare how to apply a specific folder of Kubernetes manifests from your Git repository |
GitLab
For accessing the GitLab API17, the bootstrap command requires a GitLab personal access token (PAT) with complete read/write access to the GitLab API.
# if not set, commands will prompt
export GITLAB_TOKEN=$token
flux bootstrap gitlab --hostname=$hostname \
--owner=$user --repository=flux-demo \
--branch=master --path=apps#…
✔ cloned repository
#…
✔ generated component manifests
#…
✔ generated sync manifests
#…Inspect
Verify the component in Flux system namespace:
kubectl -n flux-system get allNAME READY STATUS RESTARTS AGE
pod/helm-controller-5f98857c49-hv68x 1/1 Running 0 23h
pod/kustomize-controller-5c867fd7bd-t298c 1/1 Running 0 23h
pod/notification-controller-f788699df-xwwwr 1/1 Running 0 23h
pod/source-controller-854fd9756d-t7brm 1/1 Running 0 23h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/notification-controller ClusterIP 10.96.58.139 <none> 80/TCP 23h
service/source-controller ClusterIP 10.96.242.77 <none> 80/TCP 23h
service/webhook-receiver ClusterIP 10.96.21.196 <none> 80/TCP 23h
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/helm-controller 1/1 1 1 23h
deployment.apps/kustomize-controller 1/1 1 1 23h
deployment.apps/notification-controller 1/1 1 1 23h
deployment.apps/source-controller 1/1 1 1 23h
NAME DESIRED CURRENT READY AGE
replicaset.apps/helm-controller-5f98857c49 1 1 1 23h
replicaset.apps/kustomize-controller-5c867fd7bd 1 1 1 23h
replicaset.apps/notification-controller-f788699df 1 1 1 23h
replicaset.apps/source-controller-854fd9756d 1 1 1 23h
NAME AGE READY STATUS
kustomization.kustomize.toolkit.fluxcd.io/flux-system 22h True Applied revision: master@sha1:d9d8b862bd7738c1d7ed561c07b0833d5b395207
NAME URL AGE READY STATUS
gitrepository.source.toolkit.fluxcd.io/flux-system https://…/flux-demo.git 22h True stored artifact for revision 'master@sha1:d9d8b862bd7738c1d7ed561c07b0833d5b395207'Show flux warning events
kubectl get events -n flux-system --field-selector type=WarningLAST SEEN TYPE REASON OBJECT MESSAGE
14h Warning GitOperationFailed gitrepository/flux-system failed to checkout and determine revision: unable to list remote for … connect: connection refused
#…Sources
The flux get family of commands prints resource status tables across all Flux custom resources.
# All source types across every namespace
flux get sources all -ANAMESPACE NAME REVISION SUSPENDED READY MESSAGE
flux-system ocirepository/flux-operator 0.52.0@sha256:e25cf78b False True stored artifact for digest '0.52.0@sha256:e25cf78b'
NAMESPACE NAME REVISION SUSPENDED READY MESSAGE
flux-system gitrepository/flux-system main@sha1:3588f7dd False True stored artifact for revision 'main@sha1:3588f7dd'
flux-system gitrepository/keycloak-operator 26.6.4@sha1:9af888f3 False True stored artifact for revision '26.6.4@sha1:9af888f3'
NAMESPACE NAME REVISION SUSPENDED READY MESSAGE
cert-manager helmrepository/jetstack sha256:76be6202 False True stored artifact: revision 'sha256:76be6202'
headlamp helmrepository/headlamp sha256:7d33b525 False True stored artifact: revision 'sha256:7d33b525'
kube-system helmrepository/cilium sha256:769c270b False True stored artifact: revision 'sha256:769c270b'
#…
NAMESPACE NAME REVISION SUSPENDED READY MESSAGE
cert-manager helmchart/cert-manager-cert-manager v1.20.2 False True pulled 'cert-manager' chart with version 'v1.20.2'
headlamp helmchart/headlamp-headlamp 0.42.0 False True pulled 'headlamp' chart with version '0.42.0'
# …Each row shows a source — the upstream artifact that Flux has fetched.
Source type indicates the external backend where the raw configuration or artifact lives:
| Type | Description |
|---|---|
ocirepository/ |
Pulls artifacts from an OCI registry (images, manifests, Helm charts) |
gitrepository/ |
A Git repository (e.g., GitHub/GitLab). Used for standard GitOps manifests stored in YAML/JSON |
helmrepository/ |
A remote Helm chart index. Doesn’t store charts itself; it tracks available chart versions in index.yaml |
helmchart/ |
A specific chart + version actually downloaded from a helmrepository. Packages the templates/files ready for deployment. |
The output is grouped by source type with following columns:
- NAMESPACE — where the resource CRD lives
- NAME —
<type>/<resource-name>identifying both the source kind and instance - REVISION — the latest artifact version or digest Flux has fetched (e.g.,
main@sha1:…)- A stagnant revision after pushing new commits means:
- …either the reconciliation interval hasn’t fired yet (default 1–2 min)
- …or an error is being silently suppressed
- …follow up with
flux logs -k <type>/<resource-name>.
- SUSPENDED —
Truemeans reconciliation is paused;Falsemeans active - READY — overall health of the last reconciliation attempt
Trueis healthy.Falseindicates a problem.- Inspect the MESSAGE column first in case of problems.
- MESSAGE — controller-provided summary explaining the current state
List sources, look for Ready=True:
kubectl get gitrepositories.source.toolkit.fluxcd.io -A
kubectl get helmrepositories.source.toolkit.fluxcd.io -AResources
Isolate broken resources
flux get all -A --status-selector ready=falseDisplays the current reconciliation status of all Kustomization resources.
flux get kustomizations
# Show linked source repoitories
flux get kustomizations -A --show-source
# Only show broken deployments
flux get kustomizations -A --status-selector ready=false
# Stream live updates while you push commits
flux get kustomizations -n $namespace -wObjects
flux tree lists the Kubernetes objects managed by a Flux resource.
# Resources reconciled by a Kustomization
flux tree kustomization <name>
# Compact view (Flux-managed resources only)
flux tree kustomization <name> --compact
# Resources from a HelmRelease
flux tree artifact <helmrelease-name> -n <namespace>Useful for auditing what Flux controls and planning upgrades or rollbacks.
Logs
Tail reconciliation output from all controllers:
# Stream logs for a specific resource
flux logs -k kustomization/<name> -n <namespace>
# All resources across all namespaces
flux logs -ALogs show the progression through fetch → compare → apply stages for each reconciliation loop.
Footnotes
Weaveworks GitOps Principles
https://www.weave.works/practices/gitops↩︎Gitless GitOps with OCI artifacts
https://fluxcd.io/flux/components/source/ocirepositories↩︎Source Controller, Flux Documentation
https://fluxcd.io/flux/components/source↩︎Flux End-to-End Workflow
https://fluxcd.io/flux/flux-e2e↩︎Flux GitOps Toolkit Components
https://fluxcd.io/flux/components↩︎Source Controller
https://fluxcd.io/flux/components/source↩︎Kustomize Controller
https://fluxcd.io/flux/components/kustomize↩︎Helm Controller
https://fluxcd.io/flux/components/helm↩︎Image Automation Controller
https://fluxcd.io/flux/components/image↩︎Notification Controller
https://fluxcd.io/flux/components/notification↩︎Install flux CLI
https://fluxcd.io/flux/installation↩︎flux-installScript, GitHub
https://github.com/vpenso/kubernetes-playground/blob/master/bin/flux-install↩︎Kind Documentation
https://kind.sigs.k8s.io↩︎Bootstrap with Flux CLI, Flux Documentation
https://fluxcd.io/flux/installation/#bootstrap-with-flux-cli↩︎Bootstrap, Flux Documentation
https://fluxcd.io/flux/installation/bootstrap↩︎Flux bootstrap for GitLab, Flux Documentation
https://fluxcd.io/flux/installation/bootstrap/gitlab
https://fluxcd.io/flux/cmd/flux_bootstrap_gitlab↩︎