feat: add soft node-affinity stickiness for AgentRuntime and CodeInte…#440
feat: add soft node-affinity stickiness for AgentRuntime and CodeInte…#440Turbo-Jiaxxx789 wants to merge 1 commit into
Conversation
…rpreter When enabled, a new session prefers (soft / PreferredDuringScheduling) the node the previous session for the same workload landed on. The scheduled node is recorded back onto the workload via a last-node annotation after the pod is ready. Gated by a CRD-level nodeStickiness.enabled switch that defaults to off, so the feature is fully inert unless explicitly turned on. Has no effect for CodeInterpreter warm pools, since those sandboxes are pre-scheduled. Signed-off-by: Turbo-Jiaxxx789 <[email protected]>
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
There was a problem hiding this comment.
Code Review
This pull request introduces soft node stickiness across sessions for AgentRuntime and CodeInterpreter workloads. When enabled, new sessions will prefer scheduling onto the node where the previous session of the same workload landed. This is achieved by retrieving the scheduled node name of the sandbox pod, recording it asynchronously as an annotation on the owning workload, and injecting a preferred node-affinity term into the pod template spec of subsequent sessions. A review comment points out a missing RBAC permission: the patch verb needs to be added to the codeinterpreters resource rules, as the server now patches CodeInterpreter workloads when node stickiness is enabled.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| - apiGroups: ["runtime.agentcube.volcano.sh"] | ||
| resources: ["agentruntimes"] | ||
| verbs: ["get", "list", "watch"] | ||
| verbs: ["get", "list", "watch", "patch"] |
There was a problem hiding this comment.
The codeinterpreters resource under the runtime.agentcube.volcano.sh API group also requires the patch verb permission, as PatchWorkloadLastNode is called to update the last-node annotation on CodeInterpreter workloads when node stickiness is enabled. Please add the patch verb to the codeinterpreters resource rules as well.
There was a problem hiding this comment.
Pull request overview
Adds an opt-in soft node-affinity “stickiness” feature for AgentRuntime and CodeInterpreter sessions in the Workload Manager. When enabled via spec.nodeStickiness.enabled, newly created session pods prefer the node where the previous session for the same workload ran, and the actual scheduled node is written back to the workload via the runtime.agentcube.io/last-node annotation to inform subsequent sessions.
Changes:
- Add
spec.nodeStickiness.enabledto AgentRuntime and CodeInterpreter CRDs and Go API types (default off / inert unless set). - Inject
PreferredDuringSchedulingIgnoredDuringExecutionnode affinity (hostname) during sandbox pod construction when a prior node is recorded. - Record the scheduled node back onto the owning workload via a best-effort async patch after sandbox creation succeeds.
Reviewed changes
Copilot reviewed 12 out of 13 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/workloadmanager/workload_builder.go | Injects preferred hostname node-affinity when stickiness is enabled and a last-node annotation exists; sets sticky write-back metadata on sandbox entries. |
| pkg/workloadmanager/workload_builder_test.go | Adds unit coverage for affinity injection logic and stickiness behavior for AgentRuntime/CodeInterpreter (including warm pool behavior). |
| pkg/workloadmanager/server.go | Adds shutdown guard state used to prevent new best-effort background tasks during graceful shutdown. |
| pkg/workloadmanager/k8s_client.go | Extends pod lookup to return node name and adds workload patch helper to persist runtime.agentcube.io/last-node. |
| pkg/workloadmanager/k8s_client_test.go | Updates tests for the new pod-info API and adds tests for patching last-node onto workloads. |
| pkg/workloadmanager/handlers.go | Updates sandbox creation flow to capture node name and best-effort patch it back to the owning workload asynchronously. |
| pkg/workloadmanager/handlers_test.go | Updates handler tests for pod-info API and stabilizes gomonkey patching in subtests; adds basic guard-clause coverage for recordStickyNode. |
| pkg/apis/runtime/v1alpha1/zz_generated.deepcopy.go | Regenerates deepcopy code to include the new NodeStickiness fields/types. |
| pkg/apis/runtime/v1alpha1/codeinterpreter_types.go | Introduces NodeStickinessSpec and adds nodeStickiness to CodeInterpreterSpec. |
| pkg/apis/runtime/v1alpha1/agent_type.go | Adds nodeStickiness to AgentRuntimeSpec. |
| manifests/charts/base/templates/rbac/workloadmanager.yaml | Grants patch on agentruntimes so Workload Manager can write back the last-node annotation. |
| manifests/charts/base/crds/runtime.agentcube.volcano.sh_codeinterpreters.yaml | Adds CRD schema for spec.nodeStickiness.enabled on CodeInterpreter. |
| manifests/charts/base/crds/runtime.agentcube.volcano.sh_agentruntimes.yaml | Adds CRD schema for spec.nodeStickiness.enabled on AgentRuntime. |
Files not reviewed (1)
- pkg/apis/runtime/v1alpha1/zz_generated.deepcopy.go: Generated file
…rpreter
When enabled, a new session prefers (soft / PreferredDuringScheduling) the node the previous session for the same workload landed on. The scheduled node is recorded back onto the workload via a last-node annotation after the pod is ready. Gated by a CRD-level nodeStickiness.enabled switch that defaults to off, so the feature is fully inert unless explicitly turned on. Has no effect for CodeInterpreter warm pools, since those sandboxes are pre-scheduled.
What type of PR is this?
/kind feature
What this PR does / why we need it:
Adds opt-in soft node-affinity stickiness for AgentRuntime and CodeInterpreter. When spec.nodeStickiness.enabled is set, a new session prefers to schedule onto the node where the previous session for the same workload ran, improving warm-cache / local-data reuse across sessions.
In our RL experiments, enable node-affinity stickiness for AgentRuntime reduced startup time by 70%+ across ~20k containers + ~20k images.
New optional field spec.nodeStickiness.enabled (bool, default false) on both CRDs.
When enabled and a last node is recorded, a PreferredDuringSchedulingIgnoredDuringExecution node-affinity term (weight 100, key kubernetes.io/hostname) is appended to the sandbox pod spec — user-defined affinity is preserved, never overwritten.
After the session pod becomes ready, the scheduled node is written back onto the owning workload via the runtime.agentcube.io/last-node annotation.
It is a soft preference only, so scheduling never fails if the preferred node is cordoned, deleted, or full.
Which issue(s) this PR fixes: Fixes #
Special notes for your reviewer:
Backward compatible: a nil/omitted nodeStickiness is treated as disabled, so existing CRs need no migration.
Has no effect for CodeInterpreter with warmPoolSize > 0, since warm-pool sandboxes are pre-scheduled before a session claims them.
The last-node write-back is a no-op when stickiness is disabled.
Does this PR introduce a user-facing change?:
Add opt-in soft node-affinity stickiness for AgentRuntime and CodeInterpreter via
spec.nodeStickiness.enabled(default false). When enabled, sessions prefer the node used by the previous session for the same workload.