Repository navigation
Conversation
…licas (closes #5434) Signed-off-by: divesh <dgude@nvidia.com>
|
🌿 Preview your docs: https://nvidia-preview-pr-5436.docs.buildwithfern.com/openshell |
|
/ok to test 0f34dee |
Compatibility review (advisory)New or updated breaking changes; see the full report for all findings. 1. rust-sdk — No explicit risk acceptance foundUnder openshell_sdk::raw::proto::supervisor_host::v1, HostHello gains stay and host_gateway_message::Payload gains Redirect, invalidating formerly complete literals and exhaustive matches.
Review details
Advisory review; publication gates are unchanged. |
Signed-off-by: divesh <dgude@nvidia.com>
|
/ok to test fb1e825 |
TaylorMutch
left a comment
There was a problem hiding this comment.
I found two correctness issues in the placement and redirect handling; details are attached inline.
Validation: ran 12 existing ring tests and two isolated reproductions using the PR's placement functions. All passed, confirming that concurrent arrivals and handoffs can exceed the intended cap. I did not run the full build or Kubernetes E2E.
| .attach(identity, request.into_inner(), |member_id| { | ||
| host_home( | ||
| &state, | ||
| &controller.pool_view().unwrap_or_default().members, |
There was a problem hiding this comment.
Concurrent arrivals or handoffs can permanently defeat the placement cap. Every decision reads the cached pool view, without reserving capacity or revalidating it at the destination; redirected hosts then disable further redirects. For example, two arrivals can both see an empty view and hash to the same gateway, leaving a 2:0 distribution. With three gateways initially serving 2:1:1 supervisors, the two supervisors on a stopping gateway can also both choose the same remaining gateway from the shared snapshot, leaving 3:1 instead of 2:2. I reproduced both cases using this PR's placement functions. Previously placement depended on the Service; the new cap still leaves operators with persistent skew because accepted hosts never rebalance. Please account for in-flight placement decisions and validate capacity before making a connection sticky, and cover simultaneous arrivals/handoffs. The new sequential restart E2E does not exercise this case.
There was a problem hiding this comment.
Good catch: the records lag about 2 seconds, so a burst of connects piled onto one replica. Each gateway now counts the placements it just made, and placements run one at a time. Hosts follow at most 2 redirects in a row, so the receiving gateway can correct a placement once.
There was a problem hiding this comment.
Rechecked at 9e93a2c. The local placement accounting fixes bursts through one gateway, but I reproduced a remaining race across gateways before the next observation. A host accepted after two redirects sets accepts_redirect = false, so the controller skips home() and the actual destination never records that acceptance in its local SupervisorSpread.
With three gateways and three hosts, this schedule settles at 2:1:0 instead of 1:1:1:
sup-2arrives atgw-2, which redirects it togw-1.sup-1arrives atgw-1and is accepted there.sup-2follows its redirect togw-1, which redirects it togw-0.sup-2is accepted atgw-0with redirects disabled;gw-0does not count it yet.sup-0arrives atgw-0and is accepted because its local placement state still appears empty.
I reproduced this using the updated GatewayRing and SupervisorSpread implementations with separate spread instances per gateway and the two-hop protocol. Since established hosts do not rebalance, the skew persists after the records catch up. Please immediately account for every accepted host at its actual destination, including hosts that disable redirects, and add coverage with separate placement state per gateway. The current spread tests all exercise one instance.
There was a problem hiding this comment.
Thanks, reproduced it., : every host a replica keeps now counts there, including hosts that refuse redirects. replicas_count_every_host_they_keep replays your schedule with separate placement state per gateway: 2:1:0 before, 1:1:1 now.
…s after a redirect Signed-off-by: divesh <dgude@nvidia.com>
|
/ok to test 9e93a2c |
…at refuse redirects Signed-off-by: divesh <dgude@nvidia.com>
|
/ok to test fed4dae |
Summary
Shared supervisors now spread evenly across gateway replicas. A supervisor that comes in through the Service goes to the first gateway clockwise on the existing gateway ring that serves fewer than ⌈supervisors ÷ gateways⌉, and a stopping gateway hands its supervisors off the same way. Supervisors move only when they reconnect through the Service; there is no rebalancer.
Related Issue
Closes #5434
Changes
HostGatewayMessage.redirect(HostRedirect { peer_endpoint }) andHostHello.stay.stayis redirected, before any session starts, when the ring and cap place the member elsewhere.MemberView.gateway_replica).GatewayRing::first_below.stay.stayon the sticky redial (token refresh, blips) and on the Service fallback after a failed redirect, so a stale ring cannot loop it.stay.openshell_server_supervisor_hosts(supervisors per gateway) andopenshell_server_supervisor_host_instances_max(busiest supervisor's sandboxes). The second is a max rather than a per-supervisor label because member IDs are pod names, which would make the label set grow without bound.Known trade-off: nothing moves after placement, so two cases can stay uneven until supervisors restart:
Gateway rollouts and crashes, and supervisor restarts, end even.
Testing
cargo clippy -D warningsandcargo fmt --checkforopenshell-server,openshell-supervisor,openshell-supervisor-control, and the e2e crateopenshell-server, 293 inopenshell-supervisor, 12 inopenshell-supervisor-control, all pass. New tests:first_belowskips full replicas and falls back to the ownerspread_homeignores the member's own record and leaving membersstay, then falls back to the Service withstaysupervisors_spread_evenly_across_gateways(restart each supervisor, then roll the gateways, and assert one supervisor per gateway): passed 3 of 3 runspool_sessions_follow_their_supervisors_gateway: passedlosing_a_supervisor_pod_moves_its_sandboxes_without_restarting_themstops at its first host-endpoint call withpolicy_dns_trusted_gateway_unavailable, before any supervisor or gateway moves. The hand-built cluster lacks the host-gateway DNS setup the CI lane provides.Checklist