k8wiz
All graphs

Flux CD graph

Flux dependencies: Git and OCI sources, Kustomizations and HelmReleases

How Flux objects depend on each other: a GitRepository feeding two Kustomizations ordered with dependsOn, a HelmRelease from a HelmRepository, another from an OCIRepository, variable substitution and Slack alerts.

Flux splits GitOps into sources and appliers. Source objects (GitRepository, OCIRepository, HelmRepository) fetch something and store it as an artifact inside the cluster. Applier objects (Kustomization, HelmRelease) take an artifact and apply it. Each kind has its own controller, and they only talk to each other through these objects.

Ordering comes from dependsOn. Here the apps Kustomization waits for infra to be ready, so cert-manager's CRDs exist before any app asks for a Certificate.

Interactive graph

Click a resource to see what it does, or follow the setup step by step.

Outside the clusterComes with an add-onYou write itCreated by a controllertrafficreferencescreates

How it works

All 14 resources and what they do

Git repository github.com/acme/fleet
The fleet repo, with one directory per layer: clusters/production for the Flux objects themselves, infrastructure/ for shared add-ons and apps/production/ for the workloads.
Secret flux-systemv1
The SSH deploy key that flux bootstrap created and added to the repo. source-controller uses it to clone.
GitRepository flux-systemsource.toolkit.fluxcd.io/v1
Every minute, source-controller fetches main, packs the files into a tarball artifact and records the commit in status.artifact.revision. Kustomizations read that artifact, not Git.
Kustomization infrakustomize.toolkit.fluxcd.io/v1
Applies ./infrastructure from the Git artifact. wait: true makes it report ready only once everything it applied is healthy, which is what dependsOn waits for. prune: true deletes objects you remove from Git.
Kustomization appskustomize.toolkit.fluxcd.io/v1
Applies ./apps/production, but only after infra is ready. Before applying, it replaces ${cluster_name} and other variables in the manifests with values from the cluster-vars ConfigMap.
ConfigMap cluster-varsv1
Values that differ per cluster, such as the cluster name and the base domain. The same apps/ directory can then deploy to several clusters.
HelmRepository jetstacksource.toolkit.fluxcd.io/v1
A classic HTTPS chart repository, stored in Git under infrastructure/. source-controller downloads its index.yaml every hour.
HelmRelease cert-managerhelm.toolkit.fluxcd.io/v2
Installs cert-manager from the jetstack repository, any 1.19 patch release. helm-controller turns spec.chart into a HelmChart object and installs whatever chart that produces.
HelmChart cert-manager-cert-managersource.toolkit.fluxcd.io/v1
Created by helm-controller from the HelmRelease's spec.chart, in the HelmRepository's namespace and named <namespace>-<release>. source-controller resolves 1.19.x to a real version and stores the chart as an artifact.
OCIRepository podinfosource.toolkit.fluxcd.io/v1
Pulls the podinfo Helm chart as an OCI artifact from a container registry. With OCI there's no index to download: Flux lists the tags and picks the newest that matches semver. Signature checks with cosign can go here too.
HelmRelease podinfohelm.toolkit.fluxcd.io/v2
Installs the chart that the OCIRepository fetched, through chartRef. No HelmChart object is needed. ${base_domain} is filled in by the apps Kustomization before this is applied.
Deployment podinfoapps/v1
Created by helm-controller as part of the Helm release. helm list -n apps shows the release, and Flux checks its health after every upgrade.
Provider slacknotification.toolkit.fluxcd.io/v1beta3
Where notifications go: a Slack channel, through a bot token kept in a Secret.
Alert prod-failuresnotification.toolkit.fluxcd.io/v1beta3
Sends error events from every Kustomization and HelmRelease to the slack Provider, so a failed reconcile reaches a human.

Common mistakes

  • dependsOn waits for the other Kustomization to be ready, and without wait: true or healthChecks ready only means "applied". The dependent then starts before the CRDs or webhooks it needs are serving.
  • Changing a Kustomization's path or removing a whole directory with prune: true deletes what it applied. Rename carefully, and use kustomize.toolkit.fluxcd.io/prune: disabled on objects that must survive.
  • A wildcard version such as 1.19.x upgrades as soon as a new patch is published. Pin an exact version where you want upgrades to go through review.
  • flux get all -A shows every source and applier with its ready state and last revision. flux reconcile kustomization apps --with-source fetches Git and applies right away instead of waiting for the interval.
  • A variable that substituteFrom can't find is replaced with an empty string unless it has a default, such as ${base_domain:=example.com}. A typo silently produces a broken hostname.

The manifests you write

Everything above that is marked "You write it", in one file. The rest comes from add-ons and controllers.

apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: infra
  namespace: flux-system
spec:
  interval: 10m
  sourceRef:
    kind: GitRepository
    name: flux-system
  path: ./infrastructure
  prune: true
  wait: true
  timeout: 5m
---
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: apps
  namespace: flux-system
spec:
  interval: 10m
  dependsOn:
    - name: infra
  sourceRef:
    kind: GitRepository
    name: flux-system
  path: ./apps/production
  prune: true
  postBuild:
    substituteFrom:
      - kind: ConfigMap
        name: cluster-vars
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: cluster-vars
  namespace: flux-system
data:
  cluster_name: prod-eu-1
  base_domain: example.com
---
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
  name: jetstack
  namespace: flux-system
spec:
  interval: 1h
  url: https://charts.jetstack.io
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
  name: cert-manager
  namespace: cert-manager
spec:
  interval: 30m
  chart:
    spec:
      chart: cert-manager
      version: "1.19.x"
      sourceRef:
        kind: HelmRepository
        name: jetstack
        namespace: flux-system
  values:
    crds:
      enabled: true
---
apiVersion: source.toolkit.fluxcd.io/v1
kind: OCIRepository
metadata:
  name: podinfo
  namespace: apps
spec:
  interval: 10m
  url: oci://ghcr.io/stefanprodan/charts/podinfo
  ref:
    semver: ">=6.7.0 <7.0.0"
  layerSelector:
    mediaType: application/vnd.cncf.helm.chart.content.v1.tar+gzip
    operation: copy
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
  name: podinfo
  namespace: apps
spec:
  interval: 30m
  chartRef:
    kind: OCIRepository
    name: podinfo
  values:
    replicaCount: 2
    ingress:
      enabled: true
      hosts:
        - host: podinfo.${base_domain}
          paths:
            - path: /
              pathType: Prefix
---
apiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Provider
metadata:
  name: slack
  namespace: flux-system
spec:
  type: slack
  channel: deploys
  secretRef:
    name: slack-bot-token
---
apiVersion: notification.toolkit.fluxcd.io/v1beta3
kind: Alert
metadata:
  name: prod-failures
  namespace: flux-system
spec:
  providerRef:
    name: slack
  eventSeverity: error
  eventSources:
    - kind: Kustomization
      name: "*"
    - kind: HelmRelease
      name: "*"
      namespace: apps

Keep going

More graphs