Flux Cheatsheet

Flux CheatsheetAlle Kapitel

Flux Cheatsheet im Volltext

Stand Flux 2.10 · Edition 2026.11

Cheatsheet im Volltext

Derselbe Inhalt wie im PDF, zum Mitlesen, Durchsuchen und direkten Kopieren der YAML-Snippets. Stand: Flux v2.10.0 (Edition 2026.11).

Architektur & GitOps-Toolkit

Pull statt Push

Flux zieht den deklarierten Zustand aus Git, OCI-Registries oder Buckets und wendet ihn kontinuierlich an. Quelle = Wahrheit: was nicht im Repo steht, gehört nicht in den Cluster. Jede Ressource trägt ihr eigenes interval; Änderungen laufen über Git-Push, nicht über kubectl.

Controller & CRDs

source-controller: GitRepository, OCIRepository, HelmRepository, HelmChart, Bucket. kustomize-controller: Kustomization (inkl. SOPS-Decryption). helm-controller: HelmRelease.

notification-controller: Provider, Alert, Receiver (Webhooks). image-reflector-/image-automation-controller (optional): ImageRepository, ImagePolicy, ImageUpdateAutomation.

source-watcher (optional): ArtifactGenerator (v1beta1), erzeugt ExternalArtifact (source.toolkit.fluxcd.io/v1). Optionale Controller per --components-extra zuschalten.

flux check              # Prereqs + Controller-Status
flux get all -A         # Status aller Flux-Ressourcen
kubectl get fluxcd -A   # alle Flux-CRs (Resource-Kategorie)

Neu in v2.10

Highlights

SPIFFE-mTLS zwischen den Controllern: Artefakt-Abruf, Events und Webhooks einzeln per Flag, X.509-SVIDs etwa aus SPIRE.

Object Identity GA (vorher object-level workload identity): Flux-Objekte authentisieren sich über ihren serviceAccountName, Provider per SA-Annotation credential.auth.fluxcd.io/provider (kubernetes oder spiffe); provider: generic für OCI und Images nimmt SA-Tokens.

Alert/Provider v1, neue Typen zoom, incident.io, mastodon; ArtifactGenerator über Namespaces hinweg.

Upgrade auf 2.10

Kubernetes ab 1.35.2, 1.36.1 bzw. 1.37.0; 1.34 (seit 27.10.2026 EOL) vorher heben.

Default-RBAC ohne create auf serviceaccounts/token: für Object Identity mit Provider kubernetes an source-, notification- oder image-*-controller vorher eine ClusterRole binden (fluxcd/flux2#6139).

image-reflector-controller speichert Tags im Flux-Artefaktspeicher statt in BadgerDB; der erste Lauf scannt jede ImageRepository neu, Opt-out --feature-gates=FluxStorage=false.

Alert/Provider v1beta3 ist deprecated; nach v1 entfallen spec.summary, spec.interval, spec.proxy, das statische JWT für Azure Event Hub und TLS/Proxy im secretRef (Ersatz eventMetadata.summary, certSecretRef, proxySecretRef). flux migrate (Storage), flux migrate -f <dir> (Repo), gemischte Flotte mit -v 2.9.

kubeConfig.configMapRef: statt Key audiences die SA-Annotation credential.auth.fluxcd.io/audiences.

Ablauf: Upgrade Procedure for Flux v2.7+ (fluxcd/flux2 Discussion #5572).

Stand v2.10.0 (26.10.2026): source-/kustomize-controller v1.10.1, notification v1.10.0, helm v1.7.1 (Helm 4.3.1), image-* v1.3.0, source-watcher v2.3.1.

Bootstrap

flux bootstrap

Installiert source-, kustomize-, helm- und notification-controller nach flux-system (Image Automation per --components-extra), pusht die eigenen Manifeste unter --path ins Repo und synct sich ab dann selbst. Idempotent: erneuter Lauf mit gleichen Argumenten ist der Upgrade-Pfad.

Ohne --token-auth legt bootstrap einen read-only Deploy-Key an (Image Automation braucht --read-write-key=true); mit --token-auth landet der PAT als Secret flux-system im Cluster.

Alternative zu flux bootstrap: Flux Operator (Open Source, Flux-Ökosystem) mit FluxInstance (fluxcd.controlplane.io/v1); .spec.cluster.multitenant: true schaltet den Lockdown.

export GITHUB_TOKEN=<pat>
flux bootstrap github \
  --owner=example-org --repository=fleet \
  --branch=main --path=clusters/prod

Repo-Layout pro Cluster

--path=clusters/<name> gibt jedem Cluster einen eigenen Einstiegspunkt im selben Repo. Infrastruktur (CRDs, Operatoren, Ingress) und Apps als getrennte Kustomizations verketten, dependsOn erzwingt die Reihenfolge.

Sources

GitRepository & OCIRepository

url + interval + ref: Git per branch, tag, semver oder commit; OCI per tag, semver oder digest. Auth via secretRef oder provider: Git azure/aws, OCI aws/azure/gcp per Workload Identity, Git github per GitHub App (App-Key und githubAppID oder seit 2.10 githubAppClientID im secretRef). OCIRepository liefert Manifeste als OCI-Artefakt inkl. Signatur-Prüfung (verify: cosign/notation), GitRepository prüft Commits per OpenPGP oder seit 2.9 per SSH-Key.

HelmRepository & Bucket

HelmRepository: HTTP/S-Index; type: oci ist im Wartungsmodus, OCI-Charts per OCIRepository (chartRef oder seit 2.10 chart.kind). Bucket: S3-kompatibel, per provider auch GCS und Azure Blob. Jede Source produziert ein versioniertes Artefakt, auf das Kustomization/HelmRelease per sourceRef zeigen.

apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata: {name: platform, namespace: flux-system}
spec:
  interval: 1m
  url: https://github.com/example-org/platform
  ref: {branch: main}   # oder tag/semver/commit
  secretRef: {name: git-auth}
---
apiVersion: source.toolkit.fluxcd.io/v1
kind: OCIRepository
metadata: {name: manifests, namespace: flux-system}
spec:
  interval: 5m
  url: oci://ghcr.io/example-org/manifests
  ref: {semver: ">=1.0.0 <2.0.0"}

Kustomization

Spec-Kern

path: Verzeichnis im Source-Artefakt. prune: true: Garbage-Collection gelöschter Manifeste. sourceRef: GitRepository, OCIRepository, Bucket oder ExternalArtifact (Feature-Gate ExternalArtifact, setzt bootstrap mit source-watcher).

retryInterval steuert Fehler-Retries getrennt vom regulären interval; serviceAccountName erzwingt Impersonation (RBAC-Grenze), targetNamespace zwingt alle Objekte in einen Namespace. ignore (seit 2.9) nimmt Felder fremder Controller aus Drift-Check und Apply aus.

apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata: {name: apps, namespace: flux-system}
spec:
  interval: 10m
  retryInterval: 2m
  path: ./apps/production
  prune: true            # Garbage Collection
  sourceRef: {kind: GitRepository, name: platform}
  dependsOn:
    - name: infrastructure
  wait: true             # Health aller Objekte
  timeout: 5m
  postBuild:
    substituteFrom:
      - kind: ConfigMap
        name: cluster-vars
  ignore:                # seit 2.9
    - target: {kind: Deployment}
      paths: ["/spec/replicas"]   # HPA

Health & Reihenfolge

wait: true prüft die Health aller applizierten Objekte, healthChecks gezielt einzelne (Deployment, HelmRelease, …). dependsOn gated nachgelagerte Kustomizations, bis die Abhängigkeit Ready ist. Standard-Muster: infrastructure vor apps.

postBuild-Substitution

postBuild.substituteFrom ersetzt ${var}-Platzhalter aus ConfigMaps/Secrets, cluster-spezifische Werte (Domain, Zone, Replicas) ohne Overlay-Wildwuchs. optional: true toleriert fehlende Quellen.

HelmRelease

Chart-Referenz

chart.spec + sourceRef (HelmRepository, GitRepository, Bucket) erzeugt eine HelmChart. Seit 2.10 legt chart.kind: OCIRepository mit spec.url eine OCIRepository im Namespace der HelmRelease an, Version und Values stehen dann in einem Objekt. chartRef nutzt eine vorhandene OCIRepository, HelmChart oder ExternalArtifact. SemVer-Ranges (6.x, >=0.2.0 <1.0.0) wählen die höchste passende Version.

apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata: {name: podinfo, namespace: apps}
spec:
  interval: 30m
  chart:
    kind: OCIRepository        # seit 2.10
    spec:
      url: oci://ghcr.io/stefanprodan/charts/podinfo
      ref: {semver: ">=6.0.0 <7.0.0"}
  install: {remediation: {retries: 3}}
  upgrade: {remediation: {retries: 3, strategy: rollback}}
  driftDetection: {mode: enabled}
  valuesFrom: [{kind: Secret, name: podinfo-values}]
  values:
    replicaCount: 2

Remediation & Drift

remediation.retries (Install, Upgrade): automatische Wiederholung fehlgeschlagener Releases; strategy: rollback oder uninstall. driftDetection.mode: enabled erkennt und korrigiert manuelle Änderungen am Release-Inventar (warn meldet nur). test.enable führt Helm-Tests nach Install/Upgrade aus.

Helm 4 (seit 2.8)

helm-controller arbeitet mit dem Helm-4-SDK (v2.10: 4.3.1). Neue Releases laufen per Server-Side Apply (install.serverSideApply, Default true), bestehende bleiben auf Client-Side Apply, bis upgrade.serverSideApply: enabled (Default auto) sie umstellt. Health-Checks laufen für alle Releases über kstatus (waitStrategy.name: poller). Seit 2.9 laufen Hooks durch die Post-Renderer (postRenderStrategy: combined). Je Release zurück per waitStrategy: {name: legacy} bzw. postRenderStrategy: nohooks, global per Feature-Gate UseHelm3Defaults.

Reconciliation & Betrieb

Intervalle & Trigger

Jede Ressource reconciled periodisch (interval); flux reconcile … --with-source stößt sofort an, samt Source-Fetch. Push statt Polling: Receiver (notification-controller) nimmt Webhooks von GitHub/GitLab an, Typ generic-oidc (seit 2.9) prüft ein OIDC-Token statt eines Shared Secrets. Provider/Alert melden Events an Chat-, Incident- oder Webhook-Endpunkte.

suspend / resume

flux suspend hält die Reconciliation an (Incident-Freeze, Wartungsfenster), flux resume nimmt sie wieder auf. Suspendierte Objekte driften still, Freeze immer zeitlich begrenzen.

flux reconcile ks/apps --with-source  # ab 2.10
flux reconcile source git platform
flux suspend kustomization apps
flux resume kustomization apps
flux get kustomizations --watch

Image Automation

Drei CRDs

ImageRepository scannt Registry-Tags, ImagePolicy wählt den Ziel-Tag (semver.range, alphabetisch, numerisch, Vorfilter filterTags), ImageUpdateAutomation committet den neuen Tag per Setters-Marker ins Repo. Seit 2.10 bündelt policyChangeDelay Updates in einen Commit, GitPushRetryOnFailure (Gate, opt-in) wiederholt abgelehnte Pushes.

apiVersion: image.toolkit.fluxcd.io/v1
kind: ImagePolicy
metadata: {name: podinfo, namespace: flux-system}
spec:
  imageRepositoryRef: {name: podinfo}
  policy:
    semver: {range: 6.x}
# Setters-Marker (gleiche Zeile!) im Ziel-Manifest:
#  tag: 6.9.0 # {"$imagepolicy": "flux-system:podinfo:tag"}

Multi-Tenancy

Lockdown: Flags am Controller

--no-cross-namespace-refs=true (kustomize, helm, notification, image-*, source-watcher) verbietet Sources aus fremden Namespaces, --no-remote-bases=true (kustomize) Kustomize-Remote-Bases. Mit --default-service-account=default (kustomize, helm, ab 2.10 source-watcher, dort nur für Artefakte in fremden Namespaces) laufen Objekte ohne serviceAccountName mit dem rechtelosen Default-Account des Tenant-Namespaces. Die flux-system-Kustomization braucht dann serviceAccountName: kustomize-controller.

Object Identity: dasselbe Flag auf source-, notification- und image-*-controller, dazu --default-kubeconfig-service-account (kustomize, helm) und --default-decryption-service-account (kustomize).

# clusters/prod/flux-system/kustomization.yaml
patches:
  - patch: |
      - op: add
        path: /spec/template/spec/containers/0/args/-
        value: --no-cross-namespace-refs=true
    target:
      kind: Deployment
      name: "(kustomize|helm|notification|image-.*)-controller"
  - patch: |
      - op: add
        path: /spec/template/spec/containers/0/args/-
        value: --no-cross-namespace-refs=true
    target: {kind: Deployment, name: source-watcher}
  - patch: |
      - op: add
        path: /spec/template/spec/containers/0/args/-
        value: --no-remote-bases=true
    target: {kind: Deployment, name: kustomize-controller}
  - patch: |
      - op: add
        path: /spec/template/spec/containers/0/args/-
        value: --default-service-account=default
    target:   # source-watcher erst ab 2.10
      kind: Deployment
      name: "(kustomize|helm)-controller|source-watcher"
  - patch: |
      - op: add
        path: /spec/serviceAccountName
        value: kustomize-controller
    target: {kind: Kustomization, name: flux-system}

Secrets: SOPS & age

Verschlüsselt ins Repo

Secrets liegen SOPS-verschlüsselt im Git; der kustomize-controller entschlüsselt beim Apply (decryption.provider: sops). Private Key als Secret sops-age in flux-system (Key-Datei muss auf .agekey enden). Nur data/stringData verschlüsseln, die Manifest-Struktur bleibt diff-bar.

age-keygen -o age.agekey
cat age.agekey | kubectl create secret generic \
  sops-age --namespace=flux-system \
  --from-file=age.agekey=/dev/stdin
sops --age=<public-key> --encrypt \
  --encrypted-regex '^(data|stringData)$' \
  --in-place basic-auth.yaml
# Kustomization-Ausschnitt:
spec:
  decryption:
    provider: sops
    secretRef: {name: sops-age}

Diagnose (flux CLI)

Vom Symptom zur Quelle

flux trace zeigt für ein beliebiges Cluster-Objekt, welche Kustomization/HelmRelease und welche Source es verwaltet, der schnellste Einstieg, wenn unklar ist, woher ein Objekt kommt.

Status & Events

flux get pro Kind oder all, --watch für Live-Status. flux events filtert Kubernetes-Events auf Flux-Ressourcen (--for Kind/name). flux logs aggregiert die Controller-Logs (--level=error).

flux trace -n apps deployment my-app
flux events --for Kustomization/apps
flux logs --level=error --all-namespaces

Anti-Patterns

Was du nicht tun solltest

kubectl apply am Repo vorbei: die nächste Reconciliation überschreibt den Hotfix still. Änderungen gehören ins Repo; Notfall-Stopp ist flux suspend.

prune: false als Dauerzustand: gelöschte Manifeste bleiben als Waisen im Cluster stehen: Drift, den niemand mehr sieht.

Eine Mega-Kustomization: CRDs, Operatoren und deren Custom Resources in einem Apply racen gegeneinander. Aufteilen + dependsOn/healthChecks.

Mutable Tags ohne Digest: ImagePolicy wählt per Tag-Sortierung, ein neu gepushtes latest bliebe unbemerkt. Besser unveränderliche SemVer-Tags. Muss es latest sein: filterTags.pattern: '^latest$' + policy.alphabetical, digestReflectionPolicy: Always + interval, Setter-Marker :digest.

Klartext-Secrets im Repo: SOPS/age gehört vor das erste Secret-Commit ins Setup, nicht danach.

Multi-Tenant ohne Lockdown: ohne --no-cross-namespace-refs und Default-ServiceAccount greift jeder Tenant auf fremde Sources zu.