Skip to content

fix: Keep the leader lease renewing under API load - #30

Merged
ecv merged 1 commit into
mainfrom
fix/leader-lease-own-client
Oct 2, 2026
Merged

ecv merged 1 commit into
mainfrom
fix/leader-lease-own-client

Conversation

@ecv

@ecv ecv commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

Summary

A leader replica could lose its lease and restart whenever the API server throttled requests or the connection slowed, because lease renewals queued on the same connection and behind the same rate limit as all other controller traffic. This happened to milo in production on 2 Oct: milo-os/milo#811

Lease renewals now get their own connection and their own small rate limit, so other traffic cannot hold them up.

A stopping leader now gives up its lease, so a rollout or drain hands over straight away instead of waiting for the lease to expire.

Why releasing the lease on shutdown is safe

Both controllers in this repository get the fix. In each, the manager is the only thing the process runs, and the process exits as soon as the manager stops, so no controller can keep working after the lease is released.

Test plan

  • New unit tests show leader election keeps its own rate limit and connection when the main client is throttled, and fail with the old behaviour
  • Build, vet, lint and unit tests pass locally (the end-to-end suite needs a Kind cluster and was not run)
  • After rollout, a rolling restart hands the lease to the standby within seconds and the new leader logs no lease renewal failures under load

Related to https://github.com/datum-cloud/infra/issues/6603

Lease renewals shared each manager's API connection and client-side rate
limiter with every other request. When the API server throttled or the
connection slowed, renewals queued behind controller traffic, the renew
deadline passed, and the replica lost its lease and restarted. This was
seen in production on 2 Oct for milo, where lease GET and PUT timed out
awaiting headers during throttling.

Key changes:
- Build a dedicated client config for leader election in both the VPC
  controller and the fabric identity controller: a copy of the base config
  with its own dialer, no shared rate limiter, and QPS 5, burst 10
- Release the lease when the manager stops, so a rollout or drain hands
  over at once instead of waiting out the lease. The manager is the only
  thing either process runs and each exits when it returns, so no
  controller can act after the lease is released
- Add tests showing the base config is untouched, and that leader election
  ignores a saturated main limiter and opens its own connection
@ecv

ecv commented Oct 2, 2026

Copy link
Copy Markdown
Contributor Author

Two limits found in review, neither a blocker.

The change that matters is the dedicated dialer, which gives lease renewal its own connection. Nothing here sets a custom rate limiter on the base config, so dropping the shared limiter and the test for a saturated limiter guard a case this binary does not hit today.

The tests cover the helper, not the wiring: removing the leader election config or release on cancel from the manager options would leave them green. Release on cancel is safe without a shutdown wrapper because controller-runtime stops every leader-elected runnable before it releases the lease, and this binary runs no leader-only work outside the manager.

@ecv
ecv marked this pull request as ready for review October 2, 2026 17:04
@ecv
ecv requested a review from a team as a code owner October 2, 2026 17:04
@ecv
ecv requested review from kevwilliams and scotwells October 2, 2026 17:04

@kevwilliams kevwilliams left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sound. Same fix as datum#301, applied to both controllers in this repo through a shared internal/leaderelection package rather than duplicating the logic per binary. Same connection-isolation and rate-limit-isolation tests, same mutation-safety test. ReleaseOnCancel is safe since each controller's process exits immediately after its manager stops. CI green.

@ecv
ecv merged commit d67594a into main Oct 2, 2026
8 checks passed
@ecv
ecv deleted the fix/leader-lease-own-client branch October 2, 2026 23:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants