Skip to content

A deleted kagent Harness is not recreated by the kagent HelmRelease without driftDetection or a forced reconcile (4.8.0 skip path) #409

Description

@teemow

Found by the lab proof of #406 (the image-pinning move, 2026-09-12); corrects the "skip path" statement of that design. Fixed in v4.8.1 (#410).

Problem

Since 4.8.0 the kagent Harness is rendered by the kagent chart (harness.create: true), owned by the kagent HelmRelease; the connectivity chart no longer renders it (4.7.19 added helm.sh/resource-policy: keep so the in-order upgrade hands it over without a gap). The design assumed that a Harness deleted by a consumer skipping 4.7.19 (an exactly pinned connectivity chart without keep) "is recreated by the kagent release one reconcile later". It is not:

  • kubectl -n kagent delete harness kagent at 16:34:08Z, then reconcile.fluxcd.io/requestedAt on the kagent HelmRelease: helm-controller logged "all dependencies are ready … release in-sync with desired state" and ran no helm upgrade. The kagent HelmRelease has no spec.driftDetection (default disabled); status.history[0] stayed at the previous version.
  • 600 s observed with the Harness absent; both admitted AgentTemplates had an empty .status.harnesses and were not runnable for the whole window.
  • reconcile.fluxcd.io/forceAt (+ requestedAt) on the kagent HelmRelease recreated it in 1 s (new uid), templates Ready +23 s, first turn +26 s.

Consumers whose connectivity chart follows the range already carry 4.7.19's keep and take the in-order path implicitly; the exposure is an exactly pinned connectivity chart jumping 4.7.18 → 4.8.0.

Root cause

helm-controller's reconcile of a HelmRelease whose chart and values are unchanged compares the desired release (chart version + values) with the stored release and reports in-sync; the cluster state is only compared when spec.driftDetection.mode is enabled (or warn). Without it a deleted object of the release is invisible to the controller until the next values or chart change or a forced reconcile.

Solution (option 1, shipped in v4.8.1 — #410)

spec.driftDetection.mode: enabled on the kagent HelmRelease. On every reconcile (gitops.interval, 10 min by default) helm-controller compares the manifest in the Helm storage with the cluster and re-applies what differs or is missing, as a server-side apply — no Helm revision, no forced reconcile.

  • components.<name>.driftDetection is a passthrough for every component entry (HelmRelease v2 spec.driftDetection: mode, ignore), set for kagent only; turning it on for another release is a decision per release (its objects must tolerate the re-apply). The kagent chart (0.11.0-gs.6) renders no hook, webhook or HPA-scaled Deployment and nothing edits its objects in place, so no ignore rule is needed. The Harness carries keep itself and is the release's own object — not drift.
  • tests/verify-kagent-wiring.py::check_drift_detection asserts the kagent release carries it and no other release does by default (in make verify-meta).
  • The ATS smoke test_deleted_platform_harness_comes_back_on_the_next_reconcile deletes the Harness, requests a plain reconcile (requestedAt, standing in for the interval — no forceAt), and asserts it is back with a new uid owned by the kagent release with keep, spec unchanged, both templates Ready again, Helm revision unchanged.
  • UPGRADE.md: a <current> → <next> section for the change; the 4.8.0 skip-path bullet now states the truth for an installation on 4.8.0 exactly and names the forced-reconcile recipe (kubectl -n <gitops.namespace> annotate helmrelease kagent reconcile.fluxcd.io/requestedAt=$(date -u +%Y-%m-%dT%H:%M:%SZ) reconcile.fluxcd.io/forceAt=$(date -u +%Y-%m-%dT%H:%M:%SZ) --overwrite).
  • examples/customer-bom.yaml pins the connectivity chart to the release it is published with (a pin behind 4.7.19 renders a second owner of the Harness next to the kagent release).

Option 2 (the UPGRADE note alone) was rejected as the only answer: it makes the runtime of every agent depend on an operator knowing a recipe on a path they may not know they are on. It stays as the note for installations on 4.8.0 exactly.

Acceptance criteria

  • Drift detection on the kagent HelmRelease is enabled and tests/verify-kagent-wiring.py asserts it — fix(kagent): the kagent release detects and corrects drift — a deleted platform Harness comes back on the next reconcile (#409) #410 (squash b917fbd, released as v4.8.1; push-chart-release and push-connectivity-chart-release green on the tag; helm show values oci://gsoci.azurecr.io/charts/giantswarm/agent-platform --version 4.8.1 carries components.kagent.driftDetection.mode: enabled and its render puts spec.driftDetection.mode: enabled on the kagent HelmRelease). The UPGRADE notes carry the corrected skip-path statement with the forced-reconcile recipe for 4.8.0 exactly as well.
  • Lab proof (agentlab on the released 4.8.0 with kagent 0.11.0-gs.6 and Substrate 0.0.27-gs.7, the PR chart via platform.chartPath, helm-controller v1.6.4 / Flux 2.9.5): the first reconcile with drift detection reported Drifted=False NoDriftDetected (no spurious drift on the kagent chart's objects). kubectl -n kagent delete harness kagent at 18:29:55Z with no annotation of any kind: both templates unadmitted at +10 s; the next interval reconcile at 18:38:58Z logged DriftDetected: Harness/kagent/kagent removed → DriftCorrected: Harness/kagent/kagent created; the Harness back at +545 s (new uid, meta.helm.sh/release-name: kagent, keep); both templates Ready at +567 s; Helm revision 11 unchanged. platform-test 9/9 and agents-test 6/6 (a turn as the person on the recreated Harness) afterwards; the lab restored to the released chart. On the PR the ATS smoke (execute-chart-tests, required) ran the new test green.
  • meta chart: drop kagent.tag, workerImage and the Harness digest — consume the kagent chart's stamped values, adopt the Harness from the kagent release, feed atelet's pinned set from the kagent-images ConfigMap #406's description links this issue as the skip-path follow-up.

Activity

  1. moved this to Up Next ➡️ in Roadmapon Sep 12, 2026
  2. moved this from Up Next ➡️ to Validation ☑️ in Roadmapon Sep 12, 2026
  3. moved this from Validation ☑️ to Done ✅ in Roadmapon Sep 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    • Status
      Done ✅

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions