TL;DR

Flux is a CNCF GitOps controller using Kubernetes CRs — GitRepository fetches source, Kustomization or HelmRelease applies it. Many clients use Flux instead of or alongside ArgoCD. Know the CRs and flux CLI for on-call.

ArgoCD vs Flux

AspectArgoCDFlux
Config modelApplication CR (+ ApplicationSet)GitRepository + Kustomization/HelmRelease
UIBuilt-in web UIOptional (Weave GitOps); CLI-first
Helm supportNative in Application specHelmRelease CR (helm-controller)
Secrets in GitExternal/Sealed SecretsNative SOPS integration
Multi-tenancyAppProjectNamespace-scoped CRs + RBAC

Core CRDs

CRDControllerRole
GitRepositorysource-controllerClone/fetch Git repo on interval
HelmRepositorysource-controllerFetch Helm chart index/OCI
Kustomizationkustomize-controllerApply Kustomize overlay from source
HelmReleasehelm-controllerInstall/upgrade Helm chart
Bucketsource-controllerS3/GCS source (less common)

GitRepository + Kustomization

This is the basic Flux pull model: one object fetches Git and another applies a path from that source. Use it when Flux should reconcile a Kustomize overlay on a schedule.

yaml flux-kustomize.yaml
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
  name: platform-apps
  namespace: flux-system
spec:
  interval: 1m
  url: https://github.com/example/platform-apps.git
  ref:
    branch: main
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: web-api
  namespace: flux-system
spec:
  interval: 5m
  sourceRef:
    kind: GitRepository
    name: platform-apps
  path: ./apps/web-api/overlays/prod
  prune: true
  targetNamespace: app
  wait: true
  timeout: 5m

HelmRelease

A HelmRelease lets Flux install or upgrade a Helm chart declaratively. Use it when the desired chart version and values should live in Git instead of being applied by a CI job.

yaml helmrelease.yaml
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
  name: web-api
  namespace: app
spec:
  interval: 5m
  chart:
    spec:
      chart: ./charts/web-api
      sourceRef:
        kind: GitRepository
        name: platform-apps
        namespace: flux-system
  values:
    image:
      tag: abc123f
  install:
    remediation:
      retries: 3
  upgrade:
    remediation:
      retries: 3

Flux CLI

Use these commands to force reconciliation, trace source-to-apply status, and debug why Flux has not picked up a Git or Helm change yet.

bash flux-cli.sh
flux check                          # Verify controllers are healthy.
flux get sources git                  # GitRepository status.
flux get kustomizations               # Kustomization reconcile status.
flux get helmreleases -A              # HelmRelease status across namespaces.

flux reconcile source git platform-apps
flux reconcile kustomization web-api --with-source
flux suspend kustomization web-api    # Pause reconciles during incident.
flux resume kustomization web-api

flux logs --follow --all-namespaces   # Controller logs.

Reading Status

These status checks show whether Flux can fetch the source, build the manifests, and apply them. Use them to split repository problems from Kubernetes apply problems.

bash flux-status.sh
kubectl get gitrepositories,kustomizations,helmreleases -A
kubectl describe kustomization web-api -n flux-system
# Look at status.conditions — Ready=False means reconcile failed.
# Check status.lastAppliedRevision vs Git HEAD.

Gotchas

  • !Interval delays — changes may take up to the reconcile interval to apply (default 1–5 min).
  • !Prune deletes — resources removed from Git are deleted from cluster when prune: true.
  • !HelmRelease != helm upgrade — managed by helm-controller; don't run manual helm against Flux releases.
  • !flux-system namespace — bootstrap installs here; don't delete controller resources casually.