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: appsFlux 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.
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/productionfor the Flux objects themselves,infrastructure/for shared add-ons andapps/production/for the workloads. - Secret flux-systemv1
- The SSH deploy key that
flux bootstrapcreated 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 instatus.artifact.revision. Kustomizations read that artifact, not Git. - Kustomization infrakustomize.toolkit.fluxcd.io/v1
- Applies
./infrastructurefrom the Git artifact.wait: truemakes it report ready only once everything it applied is healthy, which is whatdependsOnwaits for.prune: truedeletes objects you remove from Git. - Kustomization appskustomize.toolkit.fluxcd.io/v1
- Applies
./apps/production, but only afterinfrais ready. Before applying, it replaces${cluster_name}and other variables in the manifests with values from thecluster-varsConfigMap. - 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 itsindex.yamlevery hour. - HelmRelease cert-managerhelm.toolkit.fluxcd.io/v2
- Installs cert-manager from the
jetstackrepository, any 1.19 patch release. helm-controller turnsspec.chartinto 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 resolves1.19.xto 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 theappsKustomization before this is applied. - Deployment podinfoapps/v1
- Created by helm-controller as part of the Helm release.
helm list -n appsshows 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
slackProvider, so a failed reconcile reaches a human.
Common mistakes
dependsOnwaits for the other Kustomization to be ready, and withoutwait: trueorhealthChecksready only means "applied". The dependent then starts before the CRDs or webhooks it needs are serving.- Changing a Kustomization's
pathor removing a whole directory withprune: truedeletes what it applied. Rename carefully, and usekustomize.toolkit.fluxcd.io/prune: disabledon objects that must survive. - A wildcard version such as
1.19.xupgrades as soon as a new patch is published. Pin an exact version where you want upgrades to go through review. flux get all -Ashows every source and applier with its ready state and last revision.flux reconcile kustomization apps --with-sourcefetches Git and applies right away instead of waiting for the interval.- A variable that
substituteFromcan'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.
Keep going
More graphs
- Deployment, Service and Ingress: how a request reaches your Pods
- Gateway API: GatewayClass, Gateway and HTTPRoute with a canary split
- PVC, StorageClass and CSI: how a cloud disk ends up in your Pod
- RBAC: how a ServiceAccount gets its permissions
- cert-manager with Let's Encrypt: Certificate, CertificateRequest, Order and Challenge
- A private CA with cert-manager and trust-manager
- Istio traffic management: Gateway, VirtualService, DestinationRule and policies
- Argo CD: ApplicationSet, AppProject and the Applications it generates
- Inside an OCI image: tag, index, manifests, config and layers
- OCI artifacts: Helm charts, Flux artifacts and image volumes