SymptomSeven Helm releases installed cleanly, GitHub Actions jobs queued forever, and the AutoscalingRunnerSet custom resources
simply did not exist — while Helm insisted they did. Our controller's logs showed it failing to add a finalizer to a resource that had
vanished between two reconcile steps.
InvestigationRe-applied a resource by hand with a watch running (
kubectl get -w --output-watch-events): ADDED, then
DELETED, two seconds apart, no deletion timestamp phase — something with delete authority was killing it instantly. No owner
references, so not garbage collection. The Helm chart's own discovery error had earlier revealed a second, cluster-wide
actions-runner-controller installed by another team — and ARC deletes any runner set whose version label doesn't match its own build.
Ours was 0.14.2; theirs was unknown and unreadable (no cross-namespace access).
Root causeTwo ARC controllers watching the same resources. The foreign one enforced version-mismatch cleanup on everything
cluster-wide, deleting our resources seconds after creation — a mutual-destruction design where only one controller's version can
survive.
FixScaled our controller to zero, then applied thirteen probe resources labeled with every plausible ARC version — the
sole survivor identified the foreign controller as 0.13.0. Rather than downgrade onto an unknown team's controller, wrote a
ValidatingAdmissionPolicy denying deletion of our runner sets by any service account outside our namespace, restored our
controller, and re-created the resources. They survived; jobs ran within minutes.
LessonWhen something disappears in Kubernetes, watch it die before theorizing — the event stream distinguishes GC, finalizers,
and direct deletes in one look. And a probe matrix turns "we can't see the other tenant's config" into data.