Flux — GitOps Toolkit for Kubernetes

Kubernetes
Published

July 22, 2026

Modified

July 31, 2026

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 OCIRepository source type.
    • Artifacts stored in OCI registries instead of Git
    • Same reconciliation model …different source backend -Useful for binary manifests, Helm charts, container images
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:

  1. Watch a Custom Resource (e.g., GitRepository)
  2. Fetch the latest artifact from the source
  3. Compare current state against desired state
  4. Apply changes to the cluster
  5. 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 .yaml manifests, 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-demo

flux 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 all
NAME                                          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=Warning
LAST 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 -A
NAMESPACE       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 — True means reconciliation is paused; False means active
  • READY — overall health of the last reconciliation attempt
    • True is healthy. False indicates 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 -A

Resources

Isolate broken resources

flux get all -A --status-selector ready=false

Displays 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 -w

Objects

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 -A

Logs show the progression through fetch → compare → apply stages for each reconciliation loop.