Skip to content

docs(operations): document ModelPool in the GPU-sharing guide - #1508

Merged
Defilan merged 1 commit into
defilantech:mainfrom
Defilan:docs/gpu-sharing-modelpool
Aug 11, 2026
Merged

docs(operations): document ModelPool in the GPU-sharing guide#1508
Defilan merged 1 commit into
defilantech:mainfrom
Defilan:docs/gpu-sharing-modelpool

Conversation

@Defilan

@Defilan Defilan commented Aug 11, 2026

Copy link
Copy Markdown
Member

What

Documents ModelPool in docs/operations/gpu-sharing.md, and scopes one limitation that had become misleading.

Why

ModelPool shipped in #1393 (2026-08-09). The GPU-sharing operations guide never mentioned it, so the only prose describing it is the design proposal. An operator reading the guide sees three modes and no hint a fourth pattern exists.

It is a genuinely different shape from the other three: exclusive, partitioned and shared all divide a device between workloads running at the same time, while a pool serves several models that each want the whole slot but are not needed simultaneously.

Refs #1393

How

Adds a ## ModelPool: many models, one slot section covering the spec, the observed steady state, the four status conditions, sticky semantics, swapBudget, and the single-replica router constraint.

Two corrections to the existing text:

  • No dynamic pool rebalancing read as absolute. It is specific to shared mode, and it now says so and points at ModelPool for the take-turns case.
  • Adds a limitation recording that a router with a pooled backend is pinned to one replica, because swap activation serialises through an in-process lock and a second replica would race it.

Written from an exercised pool, not from type comments

A real pool was stood up on-cluster:

NAME       POLICY   RESIDENT     PHASE   AGE
pooltest   sticky   pooltest-a   Ready   35m

pooltest-a   Ready     replicas 1
pooltest-b   Stopped   replicas 0

Observed and now documented:

  • a cold pool warms spec.default; non-resident members are set to replicas: 0 by the operator, and Stopped is the normal held state rather than a failure
  • SlotAllocated=True/Resident names the owner; with members missing it reports False/MissingMembers and the pool sits Degraded
  • editing spec.default on a warm pool does not move the slot. Repointing it at the other member left the incumbent resident two minutes later. This is correct (sticky keeps the incumbent, and default only applies to a cold pool) but it is the first thing an operator will try, so it is called out explicitly.

Not exercised

The demand-driven swap itself, and swapBudget expiry returning 503 + Retry-After. Those are documented from the API contract. Driving a swap needs a Proxy data-plane router, and the cluster's only router runs dataPlane: Gateway, so there was no way to exercise it without standing up new infrastructure. Flagging so a reviewer knows which claims are observed and which are read.

Checklist

  • Tests added/updated — n/a, documentation only
  • make test passes locally — n/a, no code changed
  • make lint passes locally — n/a, no code changed
  • Commit messages follow conventional commits
  • All commits are signed off (git commit -s) per DCO
  • AI assistance (if any) is disclosed above, per CONTRIBUTING.md
  • Documentation updated (if user-facing change)

Assisted-by: Claude Code (drafted the section). Before writing, the CRD schema and field semantics were read off the live cluster with kubectl explain, a ModelPool was created and driven through Degraded, Swapping and Ready, and the warm-pool default behaviour was tested rather than assumed. What could not be exercised is labelled above.

ModelPool shipped in defilantech#1393 and the GPU-sharing operations guide never
mentioned it. The only prose was the design proposal, so an operator
reading docs/operations/gpu-sharing.md saw three modes and no hint that
a fourth pattern exists.

It is a genuinely different shape from the other three. exclusive,
partitioned and shared all divide a device between workloads running at
the same time; a pool is for several models that each want the whole
slot but are not needed simultaneously, with one resident and the rest
held at replicas 0.

Written from an exercised pool rather than from the type comments:

  NAME       POLICY   RESIDENT     PHASE   AGE
  pooltest   sticky   pooltest-a   Ready   35m
  pooltest-a   Ready     replicas 1
  pooltest-b   Stopped   replicas 0

That run also produced the gotcha now called out explicitly: editing
spec.default on a WARM pool does not move the slot. default names the
member to warm on a cold pool, and sticky keeps the incumbent, so the
edit is inert until the pool next goes cold. Repointing default at the
other member left the incumbent resident two minutes later.

Also scopes the 'no dynamic pool rebalancing' limitation, which read as
absolute and is specific to shared mode, and records that a router with
a pooled backend is pinned to one replica because swap activation
serialises through an in-process lock.

Signed-off-by: Christopher Maher <chris@mahercode.io>
@Defilan
Defilan merged commit c2c3a84 into defilantech:main Aug 11, 2026
8 checks passed
@codecov

codecov Bot commented Aug 11, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

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.

1 participant