Skip to content

feat(agent): scale-to-zero wake-on-traffic datapath (Phase 3) - #29

Merged
syscod3 merged 1 commit into
mainfrom
feat/phase3-scaletozero-datapath
Jul 8, 2026
Merged

feat(agent): scale-to-zero wake-on-traffic datapath (Phase 3)#29
syscod3 merged 1 commit into
mainfrom
feat/phase3-scaletozero-datapath

Conversation

@syscod3

@syscod3 syscod3 commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Phase 3 — Scale-to-Zero wake-on-traffic datapath

Adds the ScaleToZero desiredState mode (not a Running↔Suspended flip, which would flap): a ScaleToZero VM auto-suspends when its TAP goes idle and auto-resumes when a packet arrives for its IP. Lands the idle-detector, VTEP-retention, and activator/resume together so a VM can never suspend into a state it can't wake from ("roach motel").

How it works

  • Idle detect — per-VM TAP byte-counter delta (netlink link stats). Any traffic resets the idle clock; a freshly-resumed VM always gets a full idleTimeout of grace (anti-thrash hysteresis). Idle past the timeout → Suspending.
  • Wake — one per-node AF_PACKET raw socket observes inbound overlay frames; a wakeRegistry matches the destination IP to a suspended VM and enqueues an in-process reconcile (no spec write, no new RBAC). Suspended + pending wake → Resuming.
  • VTEP retention — a ScaleToZero VM keeps its VTEP/FDB entry across suspend so the overlay still delivers the wake frame.

Test strategy (host-only; hardware validation deferred)

Host-untestable syscalls (netlink stats, AF_PACKET) sit behind linkStatsFunc / PacketSource seams with fakes, so all logic is host-unit-testable:

  • Neutral unit tests (-race): wake registry match/dedup/clear/full-channel-retry/re-register, idle observe hysteresis.
  • envtest (linux): auto-suspend idle VM, busy VM stays Running, Suspended→wake→Resuming→Running.

Deferred (needs a live cluster / Firecracker host): confirming the AF_PACKET hook actually observes the first frame destined to a TAP-less suspended VM. Marked UNVALIDATED in-code; the PacketSource interface exists precisely so the hook can be swapped to tc-BPF without touching any logic. Cold-ARP-cache and cross-resume packet buffering are named follow-ups.

Gating

Off by default. Enable per-node with IMP_SCALE_TO_ZERO=true; the webhook emits an experimental admission warning on ScaleToZero VMs.

Implements the full auto-suspend/auto-resume loop for desiredState=ScaleToZero,
landing Phases 3+4+5 together so there is no roach-motel intermediate state.
Cluster/hardware validation is deferred (see UNVALIDATED note); the feature is
gated off by default behind the agent's IMP_SCALE_TO_ZERO opt-in.

Core (internal/agent/scaletozero.go, platform-neutral + fully unit-tested):
- wakeRegistry: tracks suspended VMs by IP, fires a reconcile via a
  source.Channel GenericEvent on the first matching packet, with dedup and
  no-lost-wake-on-full-channel semantics.
- ScaleToZero.observe: TAP byte-counter idle detector; any traffic resets the
  clock, so a freshly-resumed VM always gets a full idleTimeout grace.
- The two host-only syscalls are injected behind seams (linkStatsFunc,
  PacketSource) with fakes in tests; real netlink + AF_PACKET impls live in
  scaletozero_linux.go behind the swappable PacketSource (tc-BPF later).

Reconciler wiring:
- handleRunning: ScaleToZero VMs poll TAP traffic and auto-suspend when idle.
- handleSuspending (Phase 4): keep the VTEP for ScaleToZero so the overlay still
  delivers the wake packet; register the VM's IP with the activator.
- handleSuspended: resume only once a wake packet is observed.
- handleResuming: clear wake state.
- SetupWithManager: run the activator as a per-node runnable + wire the wake channel.

Webhook: emit an experimental admission warning for desiredState=ScaleToZero.

Tests: registry + idle math run with -race on the host; envtest state-machine
cases (idle->suspend, wake->resume, busy stays running) run in CI on linux.
@syscod3
syscod3 merged commit edb6352 into main Jul 8, 2026
17 checks passed
@syscod3
syscod3 deleted the feat/phase3-scaletozero-datapath branch July 8, 2026 20:56
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.

1 participant