Skip to content

A bad FluxInstance change cannot be corrected by GitOps, because the Kustomization that applies it waits on its health #3006

Description

@devantler

🤖 Generated by the Agentic Engineer

Evidence

A bad FluxInstance change cannot be corrected by GitOps, because the Kustomization that applies the
FluxInstance waits on that same FluxInstance becoming healthy. Measured live on prod today, while
#3005 was in progress.

The applying Kustomization is in the loop. kustomization/infrastructure-controllers has 177
inventory entries and one of them is flux-system_flux_fluxcd.controlplane.io_FluxInstance — so it
applies the FluxInstance, and Flux then waits for the applied object to report healthy:

HealthCheckFailed | health check failed after 25m0.034713948s:
  timeout waiting for: [FluxInstance/flux-system/flux status: 'InProgress']

Observed twice in 27 minutes (19:24:56Z, 19:52:01Z), i.e. it re-enters the same wait indefinitely.

Field ownership shows there is no other writer. kustomize-controller owns
spec.kustomize.patches on fluxinstance/flux via server-side apply. Nothing outside the GitOps path
writes that field, so the only route to correct it is the route the fault disables.

The observed chain (from #3005). A FluxInstance patch put an unsatisfiable verify on the root
OCIRepository → the source failed verification → the FluxInstance reported InProgress → the
Kustomization that applies it timed out for 25m cycles → infrastructure and apps went
DependencyNotReady. Three of eleven Kustomizations were stalled for roughly 5.5 hours, with
lastAppliedRev frozen at …82e0d0bf while lastAttemptedRev sat at …e6039d0a.

Affected audience and impact

Anyone operating this cluster. The specific verify misconfiguration in #3005 is one instance of the
class; any FluxInstance change that leaves the instance unhealthy produces the same lock. Recovery
today required direct cluster mutation, which is exactly the capability GitOps exists to remove from
the routine path — and the automated 🩹 Heal Prod fallback runs through the same channel, so it does
not help either.

Expected behaviour

A configuration error delivered through GitOps should be correctable by delivering a corrected
configuration through GitOps. The delivery tree should not require an out-of-band cluster edit to
recover from a change it applied itself.

Acceptance criteria

  • A FluxInstance change that leaves the instance unhealthy can be reverted by merging the revert,
    with no manual kubectl mutation — demonstrated end-to-end against a deliberately bad change.
  • That demonstration includes a negative control: the same bad change before the fix
    reproduces the lock, so the test is not vacuous.
  • A FluxInstance-level fault surfaces distinguishably rather than as a generic 25m health-check
    timeout on infrastructure-controllers (complements The handoff quiesce timeout hides its own cause, which is already in hand #3002, which covers a different message on
    the same symptom).
  • The chosen mechanism is recorded with its trade-off. Candidates, not a decision:
    apply the FluxInstance from a Kustomization outside the health-gated dependency chain; drop it
    from health gating; or provide a documented break-glass that does not need improvised commands.

Size

Small-to-medium. The diagnosis is settled; the work is choosing the decoupling and proving it with a
reproduction plus negative control.

Related: #3005 (the incident this was measured during), #3002 (the timeout message hiding its cause),
#2996 (a FluxInstance patch matching no target is silently discarded — same "FluxInstance changes fail
quietly" family).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    Status
    ✅ Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions