Skip to content

Fleetlock janitor sidecar fails to release stale reboot leases #46

Description

@letan-assistant

Summary

The janitor sidecar in files/fleetlock.yaml (added in e952c15, deployed 2026-03-08) is supposed to delete the fleetlock-default lease when its holderIdentity no longer matches any current node's machine ID. It does not work.

Impact

On 2026-06-06 the cluster's OS auto-updates were found to be fully stalled. The fleetlock-default lease (namespace default) had been held for ~112 days by machine ID 010bf3597d08415bad40906d032083a8, which matches no current node — it is a ghost from an original node destroyed in a prior make deploy (deploys recreate cloud instances).

Because the ghost holder never releases the lock, every node loops forever in upgrade-os.sh on POST /v1/pre-reboot getting a non-200, so staged rpm-ostree upgrades never reboot. Agent nodes were stuck on FCOS 43.20260202 for ~4 months.

The janitor was added specifically to prevent this, but failed to do its job.

Evidence the janitor is broken

  • Pod running 90 days, janitor container: 0 restarts.
  • Janitor logs are completely empty (it should log "Lease holder ... not found among current nodes, deleting lease").
  • kubectl invoked inside the janitor container hangs (in-pod kubectl exec into control-plane pods also hangs).
  • The lease survived the entire 90 days and had to be deleted manually.

Likely contributing factors in the script

  • No --request-timeout on the kubectl calls → a hung get-lease wedges the while loop forever on the first iteration.
  • 2>/dev/null on the get-lease swallows any error, so failures are invisible in logs.
  • 1800s sleep makes iteration slow to observe.

Proposed fix (not yet applied)

  • Add --request-timeout=30s to all kubectl calls.
  • Drop 2>/dev/null so failures surface in logs.
  • Possibly shorten the sleep / add explicit logging per iteration.
  • Investigate why in-pod kubectl hangs on the control-plane node (API reachability from pod network, kubelet exec stream) — the fleetlock Go client on the same pod works fine, so this is specific to the kubectl path.

Workaround

kubectl --kubeconfig elsa.yaml delete lease fleetlock-default -n default

Safe and self-healing — fleetlock recreates the lease on the next real reboot request. After deletion a waiting node acquired the lock within 15s and proceeded to reboot.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions