A Flux Kustomization fails on a fresh cluster when its objects need CRDs the same step installs
Production applies these fine because the CRDs already exist. On a cluster rebuilt from nothing, a Kustomization with a HelmRelease and objects of the kinds that chart installs fails its dry run. Monitors for a Prometheus operator that is not there fail the same way. Split it into two stages.
My Flux manifests had only ever been applied to a cluster that already had every CRD, so I never saw this. When I rebuilt a test cluster from nothing and pointed Flux at the same manifests, three things broke in a row. All three come down to one fact: Flux dry-runs everything in a Kustomization before it applies anything in it.
Objects of a kind the release hasn’t installed yet
A Kustomization that holds a HelmRelease for cert-manager and also a ClusterIssuer
and a Certificate fails with no matches for kind "Certificate". The CRDs come
from the HelmRelease, which doesn’t exist yet because the dry run failed first.
Same thing happened with a Traefik Middleware next to the Traefik release.
The fix is two stages. The second Kustomization lists the first in dependsOn
and holds everything that needs the CRDs:
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: apps-config
spec:
dependsOn:
- name: apps
path: ./clusters/test/apps-config
wait: trueMonitors for an operator that isn’t installed
The charts for MetalLB, Traefik and cert-manager all had a PodMonitor or
ServiceMonitor switched on, which needs the Prometheus operator’s CRDs. Those
only exist where the monitoring stack runs. The HelmRelease install failed with
no matches for kind "PodMonitor" ... ensure CRDs are installed first, and with no
install retries configured it stayed failed after the first attempt. Turn the
monitors off in the overlay for a cluster that has no operator.
Things the base assumed
I also had to switch off persistence for Traefik, because its volume wanted a storage class the test cluster doesn’t have, and delete a DNS challenge webhook that had no use there.
The order of failures is the lesson. Each fix just let Flux get one step further and show the next problem, and every one was invisible on a cluster that already had the CRDs. A rebuild from nothing is the only real test of a base.