Skip to content

feat(worker): decouple sliced compute and memory budgets#36

Merged
thxCode merged 2 commits into
mainfrom
feat/sliced-cores-memory-independent
Jul 14, 2026
Merged

feat(worker): decouple sliced compute and memory budgets#36
thxCode merged 2 commits into
mainfrom
feat/sliced-cores-memory-independent

Conversation

@thxCode

@thxCode thxCode commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

What type of PR is this?

/kind enhancement
/area worker

What this PR does / why we need it:

Removes the admission-time constraint that a sliced accelerator request's compute budget (acceleratorSlicedCoresPercentage) must be greater than or equal to its memory budget (acceleratorSlicedMemoryPercentage).

A slice's per-card compute (SM) and VRAM budgets are physically independent — the device-plugin already caps SM and VRAM separately (CUDA_DEVICE_SM_LIMIT vs CUDA_DEVICE_MEMORY_LIMIT_*; Ascend aicore-quota vs memory-quota) — so this ordering rule was an unnecessary restriction that blocked valid configurations such as a memory-heavy, compute-light slice.

The check was enforced at two admission points; both are dropped so the relaxation takes effect end-to-end:

  • InstanceWebhook.validateResourceRequests — the Instance CR create/start path.
  • PodWebhook.validateSlicedContainer — the downstream Pod the Instance controller materializes (the real runtime enforcement point). Dropping only the Instance webhook would leave the Pod webhook still rejecting the request, so the change would not have worked.

Unchanged: the [0,100] range checks, the "copy one percentage to the other when only one is set" defaulting, and the "accelerator count must be exactly 1 for a sliced request" rule.

Which issue(s) this PR fixes:

None.

Special notes for your reviewer:

  • AcceleratorSlicedCoresPercentage field doc updated and derived code regenerated via make generate (openapi / CRD / proto / applyconfiguration).
  • docs/architecture.md Pod-webhook rejection list updated to drop cores-% < memory-%.
  • The dated design spec specs/2026-06-29-instancetype-unified-pool-refactor.md still records the original constraint; left as-is as a historical design record (a later relaxation belongs in a new record, not a retroactive edit).
  • A second, independent commit (chore(api): sync applyconfiguration unit CPU comment to cores) regenerates one stale generated file whose source comment was changed in c0d4a01 but not regenerated then. Pure generated-code sync, unrelated to the constraint change — reviewable on its own.
  • Verified locally: make lint (0 issues) and make test (full suite green). The webhook unit tests that asserted cores < memory is rejected were flipped to assert it is now allowed.

Does this PR introduce a user-facing change?

Sliced accelerator requests no longer require `acceleratorSlicedCoresPercentage` to be greater than or equal to `acceleratorSlicedMemoryPercentage`; a slice's per-card compute and memory budgets are now independent.

Copilot AI review requested due to automatic review settings July 14, 2026 05:47

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR relaxes GPUStack worker admission rules for sliced accelerators so that per-card compute (SM) and memory (VRAM) percentages are treated as independent budgets, removing the prior constraint that compute must be ≥ memory.

Changes:

  • Dropped the cores% < memory% rejection from both Instance admission validation and downstream Pod admission validation.
  • Updated webhook unit tests to assert cores% < memory% is now allowed.
  • Updated API/docs commentary and regenerated derived artifacts (OpenAPI/CRD/proto/applyconfiguration) to reflect the relaxed contract.

Reviewed changes

Copilot reviewed 6 out of 10 changed files in this pull request and generated no comments.

Show a summary per file
File Description
pkg/worker/webhooks/worker/pod.go Removes Pod webhook validation that rejected cores% < memory% for sliced requests; updates comments accordingly.
pkg/worker/webhooks/worker/pod_test.go Updates Pod webhook validation test case to expect cores% < memory% to be allowed.
pkg/worker/webhooks/worker/instance.go Removes Instance webhook validation that rejected cores% < memory%; updates comment to state independence.
pkg/worker/webhooks/worker/instance_test.go Updates Instance webhook sliced-percentage contract test to allow cores% < memory%.
pkg/kubeclients/applyconfiguration/worker/v1alpha1/instanceresources.go Updates applyconfiguration field doc for sliced cores percentage to reflect independence.
docs/architecture.md Updates Pod admission webhook rejection list to remove the cores% < memory% rule.
api/worker/zz_generated.openapi.go Regenerates OpenAPI description for sliced cores percentage to reflect independence.
api/worker/v1alpha1/zz_generated.crds.go Regenerates CRD schema descriptions to reflect independence for sliced cores percentage.
api/worker/v1alpha1/instance.go Updates API type field comment for sliced cores percentage to reflect independence.
api/worker/v1alpha1/generated.proto Regenerates proto comments to reflect independence for sliced cores percentage.
Files not reviewed (4)
  • api/worker/v1alpha1/generated.proto: Generated file
  • api/worker/v1alpha1/zz_generated.crds.go: Generated file
  • api/worker/zz_generated.openapi.go: Generated file
  • pkg/kubeclients/applyconfiguration/worker/v1alpha1/instanceresources.go: Generated file

Copilot AI review requested due to automatic review settings July 14, 2026 05:56

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 11 changed files in this pull request and generated 1 comment.

Files not reviewed (5)
  • api/worker/v1alpha1/generated.proto: Generated file
  • api/worker/v1alpha1/zz_generated.crds.go: Generated file
  • api/worker/zz_generated.openapi.go: Generated file
  • pkg/kubeclients/applyconfiguration/worker/v1alpha1/instanceresources.go: Generated file
  • pkg/kubeclients/applyconfiguration/worker/v1alpha1/instancetypeunitresources.go: Generated file

Comment thread pkg/worker/webhooks/worker/pod.go Outdated
@thxCode thxCode force-pushed the feat/sliced-cores-memory-independent branch from 6368713 to ca48c25 Compare July 14, 2026 06:09
Copilot AI review requested due to automatic review settings July 14, 2026 06:09

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 11 changed files in this pull request and generated 1 comment.

Files not reviewed (5)
  • api/worker/v1alpha1/generated.proto: Generated file
  • api/worker/v1alpha1/zz_generated.crds.go: Generated file
  • api/worker/zz_generated.openapi.go: Generated file
  • pkg/kubeclients/applyconfiguration/worker/v1alpha1/instanceresources.go: Generated file
  • pkg/kubeclients/applyconfiguration/worker/v1alpha1/instancetypeunitresources.go: Generated file

Comment thread pkg/worker/webhooks/worker/pod.go Outdated
Copilot AI review requested due to automatic review settings July 14, 2026 06:23
@thxCode thxCode force-pushed the feat/sliced-cores-memory-independent branch from ca48c25 to c07c4fe Compare July 14, 2026 06:23

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 11 changed files in this pull request and generated 1 comment.

Files not reviewed (5)
  • api/worker/v1alpha1/generated.proto: Generated file
  • api/worker/v1alpha1/zz_generated.crds.go: Generated file
  • api/worker/zz_generated.openapi.go: Generated file
  • pkg/kubeclients/applyconfiguration/worker/v1alpha1/instanceresources.go: Generated file
  • pkg/kubeclients/applyconfiguration/worker/v1alpha1/instancetypeunitresources.go: Generated file

Comment thread pkg/worker/webhooks/worker/pod.go Outdated
thxCode added 2 commits July 14, 2026 14:55
Remove the validation that required acceleratorSlicedCoresPercentage to be
greater than or equal to acceleratorSlicedMemoryPercentage. The per-card
compute (SM) budget and the VRAM budget of a slice are independent, so a
sliced request may set any combination of the two percentages in [0,100].

Drop the cores>=memory check from both admission points that enforced it:
the Instance webhook (validateResourceRequests) and the downstream Pod
webhook (validateSlicedContainer). Update the AcceleratorSlicedCoresPercentage
field doc and regenerate the derived API code, and align docs/architecture.md.

Signed-off-by: thxCode <thxcode0824@gmail.com>
Regenerate InstanceTypeUnitResources applyconfiguration so its unit CPU
doc comment reads "cores", matching the source type comment that
c0d4a01 changed from "milli-cores" to "cores" but did not regenerate.
Pure generated-code sync; no behavior change.

Signed-off-by: thxCode <thxcode0824@gmail.com>
Copilot AI review requested due to automatic review settings July 14, 2026 07:01
@thxCode thxCode force-pushed the feat/sliced-cores-memory-independent branch from c07c4fe to f36c691 Compare July 14, 2026 07:01
@thxCode thxCode merged commit 1b73fdc into main Jul 14, 2026
4 checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 6 out of 11 changed files in this pull request and generated 2 comments.

Files not reviewed (5)
  • api/worker/v1alpha1/generated.proto: Generated file
  • api/worker/v1alpha1/zz_generated.crds.go: Generated file
  • api/worker/zz_generated.openapi.go: Generated file
  • pkg/kubeclients/applyconfiguration/worker/v1alpha1/instanceresources.go: Generated file
  • pkg/kubeclients/applyconfiguration/worker/v1alpha1/instancetypeunitresources.go: Generated file

Comment thread docs/architecture.md
**Three-view status.** `InstanceType.status` carries three per-card bin-packing projections computed from the `Devices` ledger (not a credits fold-down): `Accelerator` = free whole cards; `AcceleratorShared` = shareable ownership slots; `AcceleratorSliced` = sliceable VRAM-percent units. Because the reconciler watches the `Devices` CR and writes the result into a real CRD's `.status`, a `kubectl get instancetype -w` observes capacity move as pods allocate and free — a read-only projection over the ClusterQueue could not (it borrows the CQ `resourceVersion`, unchanged on a `Devices`-only allocation). The v1 (`worker.gpustack.ai/v1`) InstanceType is a thin proxy + conversion over the real `v1alpha1` CRD; the unit spec lives **only** on the InstanceType — a derived type is stamped with the fixed default at creation, and an admin edit changes only the InstanceType (never a Node or the ClusterQueue notes). The InstanceType validating webhook **requires** the complete input on create — `acceleratorGroup` (only when `acceleratable`) / `os` / `arch` plus the unit triple (`unitResources.cpu`/`.ram` + `localStorage`; an empty or partial spec is rejected), read independently of any editable setting, and a **CPU-only (`acceleratable=false`) type's unit CPU must be exactly 1 core** (an accelerated type keeps any unitless positive integer) — and **freezes the spec on update**: every field is **immutable except `displayName` (rename) and `inactive` (take in/out of service)**, so to re-size or re-point a pool you delete and re-create the type. Create-time shape checks are not re-run on update (only immutability is), so a legacy type stored before a tightened rule can still be renamed or deactivated. The defaulting webhook defaults an empty `generalGroup` to the `generic` sentinel, stamps the pool's schedule labels (`nodefeature.PoolScheduleLabels`, grouped by `instance-type-aware-cpu-manufacturer`) and the `schedule.gpustack.ai/queue-entrance` label (`nodefeature.FormatLocalQueueName(name)`), enriches the descriptors from a matching ResourceFlavor, and — when awareness is on — folds that flavor's `cpuDetail` note into `spec.cpu` (generic) or `spec.accelerator.cpu` (accelerated). The Instance validating webhook enforces the unit spec on **Create and Update**: a submission's RAM must not exceed `unitRAM × count` and its local storage must not exceed the InstanceType's `LocalStorage`. The Pod webhook reads the **InstanceType** for a slice's per-card VRAM divisor — reverse-looked-up by the `schedule.gpustack.ai/queue-entrance` label to `spec.memory` (Stage 4, Pod admission webhook) — never the user-writable LocalQueue.

**Pod admission webhook.** A `pods` CREATE webhook (objectSelector on `kueue.x-k8s.io/queue-name`, `failurePolicy: Fail`) mutates a sliced request — defaulting `.sliced.cores-percentage` to 100 and folding `.sliced.memory-percentage` / `.sliced.memory-mib` into `.sliced.units` (only when units are absent; memory-percentage wins) — and validates it (rejecting no-memory / both-memory-keys / non-positive `.sliced.*` / `cores-% < memory-%` / mixed modes). The per-card VRAM divisor for the fold is read from the operator-owned **InstanceType**'s `spec.memory` (reverse-looked-up by the `schedule.gpustack.ai/queue-entrance` label), never from the user-writable LocalQueue. Its `MutatingWebhookConfiguration` name sorts before `kueue-mutating-webhook-configuration` so the fold runs before Kueue hashes container resources.
**Pod admission webhook.** A `pods` CREATE webhook (objectSelector on `kueue.x-k8s.io/queue-name`, `failurePolicy: Fail`) mutates a sliced request — defaulting `.sliced.cores-percentage` to 100 and folding `.sliced.memory-percentage` / `.sliced.memory-mib` into `.sliced.units` (only when units are absent; memory-percentage wins) — and validates it (rejecting no-memory / both-memory-keys / non-positive `.sliced.*` / mixed modes). The per-card VRAM divisor for the fold is read from the operator-owned **InstanceType**'s `spec.memory` (reverse-looked-up by the `schedule.gpustack.ai/queue-entrance` label), never from the user-writable LocalQueue. Its `MutatingWebhookConfiguration` name sorts before `kueue-mutating-webhook-configuration` so the fold runs before Kueue hashes container resources.
Comment on lines +10 to 11
// CPU is the unit CPU resource(cores) of the InstanceType.
CPU *string `json:"cpu,omitempty"`
@thxCode thxCode deleted the feat/sliced-cores-memory-independent branch July 15, 2026 02:20
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.

2 participants