Skip to content

fix(kserve): a GPU pool at scale-to-zero can be served — the fit check answers without a node and load proceeds - #91

Merged
teemow merged 2 commits into
mainfrom
kserve-pool-scale-from-zero
Sep 16, 2026
Merged

teemow merged 2 commits into
mainfrom
kserve-pool-scale-from-zero

Conversation

@teemow

@teemow teemow commented Sep 16, 2026

Copy link
Copy Markdown
Member

Problem

On gazelle the GPU pool gpu-l4 (cluster-manager, Karpenter, scale-to-zero) had no node, and model-manager refused to serve the first model on it (#90, seen in giantswarm/giantswarm#37714):

check_fit {backend: kserve, preset: qwen3-4b-instruct} → fits: false,
reason: "no eligible node: ip-10-0-164-72…: outside the serving node selector (giantswarm.io/machine-pool=gazelle-gpu-l4); …"

fitCheck needs a node matching the pool selector; with none, Fits is false and Load / Pull return ErrUnfit — but the pending predictor is exactly what makes the autoscaler launch the node. The pool could only be used once something else had scaled it up.

Solution

When the discovery's spec.gpuPool.nodeSelector names a pool no node belongs to yet, and no explicit node was asked for, the fit check answers fits: true with no node, budgetSource: pool-scale-from-zero and a reason that says the pool scales from zero and the fit against its accelerator is unverified. Load and Pull proceed without a node pin: the predictor / download Job carry the pool's toleration and selector (scheduling.go), go Pending, and Karpenter brings the node. Unchanged: an explicit node outside the pool, a pool whose nodes exist but do not fit, and no pool selector at all (no accelerator node).

TestFitCheckPoolScalesFromZero: pool selector set, no pool node → fits without a node; explicit node → refused; Load creates the serving object without a node pin; once a pool node exists the fit is against that node again. CHANGELOG.

Verification

  • go test ./... -count=1: every package ok (kserve 2.5 s). golangci-lint run: 0 issues.
  • Live cause read on gazelle: the check_fit answer above with the pool at 0 nodes and the discovery ConfigMap's gpuPool.nodeSelector in effect.

Plan bumblebee-plans#46 (D5/D10), epic giantswarm/giantswarm#37639.

Fixes #90.

@teemow
teemow requested a review from a team as a code owner September 16, 2026 14:03
@circleci-architect

circleci-architect Bot commented Sep 16, 2026 •

Copy link
Copy Markdown

Published Helm chart model-manager

0.23.3-dev.kserve-poo--e-from-zero.2026-09-16.14-12-23.ha3972ae
Chart model-manager
Version 0.23.3-dev.kserve-poo--e-from-zero.2026-09-16.14-12-23.ha3972ae
OCI reference oci://gsoci.azurecr.io/charts/giantswarm/model-manager:0.23.3-dev.kserve-poo--e-from-zero.2026-09-16.14-12-23.ha3972ae
Digest sha256:6ad72a0f81f0f9860f1dc94bc0f1c4b90250c09650ebab12303874f299025c67
Registry public — gsoci.azurecr.io
Git catalog giantswarm-test-catalog (index)
Pull this chart
helm pull oci://gsoci.azurecr.io/charts/giantswarm/model-manager --version 0.23.3-dev.kserve-poo--e-from-zero.2026-09-16.14-12-23.ha3972ae

Posted by architect-orb · build 1230 · commit a3972ae · updated in place on every push

@teemow
teemow merged commit 5a8043a into main Sep 16, 2026
10 checks passed
@teemow
teemow deleted the kserve-pool-scale-from-zero branch September 16, 2026 14: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.

kserve: a GPU pool at scale-to-zero has no eligible node, so check_fit is false and load_model refuses — the first model can never be served on it

1 participant