Skip to content

Shorten bootstrap time

dependsOn, wait, timeout and retryInterval decide how long a new cluster takes to come up, and how long a bad change takes to fail. fluxlint treats them as a scheduling problem and finds the longest path through it.

Read the critical path

fluxlint check -v clusters/production
  info    FL-T001 critical-path  worst-case bootstrap bound is 8m0s
            t<=0s       start(flux-system/a)      +0s      created by parent
            t<=5m0s     ready(flux-system/a)      +5m0s    apply and health timeout
            t<=5m30s    start(flux-system/b)      +30s     dependsOn
            t<=7m30s    ready(flux-system/b)      +2m0s    apply and health timeout
            t<=8m0s     start(flux-system/c)      +30s     dependsOn

Every component has two events. start is the moment Flux first applies it. ready is the moment it reports Ready. Each line gives the latest time the event can happen in a bootstrap that still succeeds, what that step adds, and why.

The bound is what your settings allow, not what usually happens. A component with wait: true and timeout: 5m may be ready in ten seconds, but Flux will wait five minutes before it gives up, and everything behind it waits too.

What fluxlint suggests

Rule Meaning
FL-T002 one timeout makes up most of the bound and sits on the critical path
FL-T004 a dependsOn that nothing rendered justifies: the dependent uses no namespace, CRD, source or Secret from the dependency
FL-T005 a dependsOn already implied by another path
FL-T006 the reverse: a component needs something from another and nothing orders them, so it fails and retries until the other catches up
FL-T007 no retryInterval, so a failed apply waits a full interval before the next try
FL-T008 a wait: true parent gives up before the things it waits for
FL-T010 a ConfigMap read by substituteFrom changes, but nothing makes its readers reconcile, so they keep the old values until their next interval

For FL-T004, fluxlint says what removing the dependency would save:

  info    FL-T004 unjustified-dependency  flux-system/c: dependsOn flux-system/b, but nothing rendered in flux-system/c imports anything from flux-system/b
            at clusters/prod/all.yaml:37
            on the critical path: removing it lowers the worst-case bound by 30s

Treat this as a question, not an order. fluxlint sees what is rendered. It cannot see that a controller in c calls a webhook served from b. If that is the reason, keep the dependency, and consider a contract so the reason is written down.

Add real durations

Give fluxlint the reconcile durations your controllers report and it adds an expected time beside the bound:

kubectl -n flux-system port-forward deploy/kustomize-controller 8080 &
curl -s localhost:8080/metrics | grep gotk_reconcile_duration_seconds > observed.prom
fluxlint check --observed observed.prom

A YAML map works too:

flux-system/infrastructure: 95s
flux-system/apps: 20s
HelmRelease/cert-manager/cert-manager: 48s

Set a budget

# .fluxlint.yaml
timing:
  maxBootstrapBound: 30m

A change that pushes the bound past the budget fails with FL-T100. This stops a bootstrap from growing slower one reasonable-looking timeout at a time.