Repository navigation
feat(pool-relay): register the routing pool with Global Discovery - #18077
Conversation
PoolHeartbeat registers a pool with POST /pools and renews it on each lease's heartbeat interval, sending the latest registration each time. A failed call is retried after 1 s, doubling up to the heartbeat interval, and once more 1 s before the lease ends, so an outage that ends in time does not lapse it. Every failure is retried, a 501 included: every Global Discovery mode takes registrations, and with MCS a pool is listed only while its registration is within the lease. Cancel and drop stop it. The service has no DELETE, so a stopped pool drops out one lease later. error_chain moves to client.rs, next to DiscoveryClientError, now that the caches and the heartbeat share it. Signed-off-by: Jacob Ioffe <jioffe@nvidia.com>
Signed-off-by: Jacob Ioffe <jioffe@nvidia.com>
PoolHeartbeat now takes a watch of Option<PoolRegistration>. While the value is None it sends nothing, so the service drops the pool once its lease passes, and the next registration goes out at once. The PoolRelay needs this because a registration names a model, and the Relay learns the model only when workers appear. Signed-off-by: Jacob Ioffe <jioffe@nvidia.com>
Global Discovery lists a pool only while it has a registration inside its lease, in every mode. With --routing-pool, the Relay now registers the pool with POST /pools and renews it on the lease heartbeat through PoolHeartbeat. RoutingPoolRegistration builds the registration from the serving topology. It keeps the registered model while the model is in the topology, and otherwise picks the one Ready model, or the only model while none is Ready. The new flags --routing-pool-region (required with --routing-pool) and --routing-pool-frontends supply the location and the frontends. The health field routing_pool_unregistered_reason says why the pool is not registered. Signed-off-by: Jacob Ioffe <jioffe@nvidia.com>
|
No actionable comments were generated in the recent review. WalkthroughThe Pool Relay accepts routing-pool region and frontend settings. It selects a model from the serving topology and registers the pool with Global Discovery. A lease heartbeat renews the registration, and health reports the reason when registration is absent. ChangesRouting-pool registration
Estimated code review effort: 4 (Complex) | ~45 minutes Merge Risk:
|
✅ Dynamo PR CI passed — run 41868450128 (attempt 1) on
|
Second upstream merge for the split v2 PR: 36 commits past the first merge's base 182039d, 17 conflicted paths, each upstream change placed in the crate that owns the code at the stack head, upstream behavior whole, the stack's moves intact, no shims. - ai-dynamo#17723 flatten policy classes: flat PolicyProfile (from_classes, UnknownPolicyClassError) in lib/router/admission profile.rs; the YAML half (default_policy_class, removed keys rejected) in lib/router/kv-router policy_config.rs; KvSchedulerError::UnknownPolicyClass via From in the kernel; 400/InvalidArgument in lib/llm (UnknownPolicyClassRefusal) and ext-proc. - ai-dynamo#17724 EDF ordering: RouterQueuePolicy::Edf in admission profile.rs; due-time order, DueKey and class budgets in admission queue.rs; the restored score keys (RouterSchedulingPolicy::score_policy) as the kernel's policy.rs (ordered-float back in dynamo-scheduler). - ai-dynamo#17725 controlled delay: head expiry and with_class_budget_expiry in admission queue.rs; ClassTimers, due-time checks, DRR charged on admission (extract_next/settle) and the retained overlap refresh in the kernel's queue.rs and overlap_refresh.rs; metrics in lib/llm. - ai-dynamo#17437 image-aware KV routing for TRT-LLM sidecars: zmq_wire/trtllm.rs in lib/kv-events; the sidecar depends on kv-events, kv-hashing, multimodal and protocol instead of kv-router. - ai-dynamo#14775 prefill cancellation, ai-dynamo#17716/ai-dynamo#18077 pool relay, ai-dynamo#17707 NVTX range, ai-dynamo#18102 LiveEngine buffering, ai-dynamo#17887 shared replay clock: lib/llm, bindings, mocker, bench, auto-merged with import re-points. Tests: upstream's queue tests split as the stack does (YAML-driven policy queue tests in kv-router through testing hooks; kernel tests build the flat profile through PolicyProfile::from_classes); every upstream test in the touched modules is present (97 kernel queue, 40 policy queue, 21 policy config, 53 config, 15 policy, 52 zmq_wire). AGENTS.md text for the queue placed in the two owner crates. CODEOWNERS regenerated; four lockfiles regenerated and --locked clean. Signed-off-by: Ishan Dhanani <ishandhanani@gmail.com>
Overview
Global Discovery lists a pool in
GET /poolsonly while the pool has a registration inside its lease. That holds in every mode:registrations,karmada, andmcs. Until now nothing sent that registration. A Relay started with--routing-poolpublished its state to the Global Routers, but its pool never appeared inGET /pools. With this change the Relay registers the routing pool withPOST /poolsand renews the registration on the lease heartbeat. When the Relay stops, it stops renewing, and the pool leavesGET /poolsone lease later.Linear: LLM-214
Key Changes
PoolHeartbeatindynamo-global-discovery-client(heartbeat.rs) registers a pool and renews it on each lease's heartbeat interval. It retries a failed call after 1 s, doubles the wait up to the heartbeat interval, and makes one more call 1 s before the lease ends, so an outage that ends before then keeps the pool listed. It retries every failure,501included. It reads the registration from awatchofOption<PoolRegistration>and sends nothing while the value isNone.RoutingPoolRegistration(lib/llm/src/pool_relay/routing_pool.rs) builds the registration from the Relay's serving topology. A registration names one model:--routing-pool-regionand--routing-pool-frontendsto the Python CLI, the bindings, andPoolRelayConfig.--routing-poolnow requires--routing-pool-region.PoolRelay::startrejects a frontend that is not an HTTP or HTTPS URL.routing_pool_unregistered_reasonsays why the pool is not registered: no model yet, several models, a failed call, or the Relay stopped. It does not affecthealthy.Validation
PoolHeartbeattests run on paused Tokio time. They check renewal timing, retries and the backoff reset, the retry before the lease ends,Nonehandling, and stopping on cancel or drop.RoutingPoolRegistrationtests check model selection, staying on the registered model, withdrawing the registration when the Relay stops, and the health reason.dynamo-global-discovery-client, 269 indynamo-llmpool_relay::, and 96 inpool_relay/tests/test_cli.py.cargo clippy --no-deps --all-targets -- -D warningsis clean ondynamo-global-discovery-client,dynamo-llm, and the Python bindings.registrationsmode with a 2 s heartbeat and a 6 s lease, and adynamo.mockerworker shared file discovery with the Relay.GET /poolslisted the pool with the topology's model,Qwen/Qwen3-0.6B, and with the region and frontends.GET /pools5.0 s after the Relay got SIGTERM, and 5.4 s after it in an earlier run.mcsnorkarmadamode ran end to end, because both need Kubernetes. The Global Discovery tests inbackends/registered.rscover listing a registered pool in those modes.Issues and Ongoing Work
--routing-pool-regionbreaks no deployment:--routing-poolmerged in feat(pool-relay): share live pool state across router connection modes #17716 on 2026-11-04, and nothing deploys it yet.DynamoPoolRelayCRD fields, is follow-up work.capacityandcapabilitiesempty. The Global Router design'sRegisterPool()carries both, and blue/green relies on capacity changes, but nothing reads either field yet, and the Relay has no GPU SKU source. Filling them is follow-up work.DYN_CLUSTER_IDmatch the cluster name MCS uses?Pull Request Checklist
/pr-checklistskill.Summary by CodeRabbit