feat(sdk): route Go SDK exec and forward to the sandbox owner replica (#4852)

* feat(sdk): route Go SDK exec and forward to the sandbox owner replica

The Go SDK now does what the CLI already does for long-lived sandbox
calls. The GetSandbox check that Exec.Run, Exec.Stream, Exec.Interactive,
TCP.Forward and SSH.Tunnel already make also asks the gateway for the
owner replica. The call then sends it in the x-openshell-replica header
and retries once without the header when the edge proxy reports that the
owner's route has no ready endpoints.

No extra round trip is added. Without a reported owner the calls are
unchanged.

Part of #4223

Signed-off-by: divesh <dgude@nvidia.com>

* refactor(sdk): address Go replica routing review

Share the header check between the routed attempt and its retry, keep the
first-frame EOF rule in one bidi helper, reuse Get's request for the owner
lookup, and document the header contract next to the replica routing docs.

Part of #4223

Signed-off-by: divesh <dgude@nvidia.com>

* docs(kubernetes): refer to the SDKs collectively in replica routing

Part of #4223

Signed-off-by: divesh <dgude@nvidia.com>

---------

Signed-off-by: divesh <dgude@nvidia.com>
This commit is contained in:
Divesh
2026-10-29 17:18:41 +00:00
committed by GitHub
parent 077d43131e
commit cc9995438f
7 changed files with 335 additions and 35 deletions
+1 -1
View File
@@ -257,7 +257,7 @@ helm upgrade <release-name> oci://ghcr.io/nvidia/openshell/helm-chart \
--set grpcRoute.replicaRouting.enabled=true
```
The chart renders one Service per replica and a GRPCRoute rule that matches the `x-openshell-replica` request header. The CLI and the Rust SDK set that header from the owner the gateway reports and retry without it if the named replica is unavailable. Replica routing requires `workload.kind=statefulset`, `workload.allowMultiReplicaStatefulSet=true`, and at most 15 replicas.
The chart renders one Service per replica and a GRPCRoute rule that matches the `x-openshell-replica` request header. The CLI and SDKs send `x-openshell-want-owner: 1` on `GetSandbox`, read the owner from the `x-openshell-owner` response header, and set it as `x-openshell-replica`. If the proxy answers `UNAVAILABLE` with an empty message, `no healthy upstream`, or `connection failure`, they retry once without it. Replica routing requires `workload.kind=statefulset`, `workload.allowMultiReplicaStatefulSet=true`, and at most 15 replicas.
If the release uses `workload.kind=deployment`, this upgrade replaces the Deployment with a StatefulSet, so every gateway pod restarts at once. The StatefulSet also requests a 1Gi PersistentVolumeClaim per replica, which stays `Pending` on clusters without a default StorageClass.