Skip to content

Commit b940444

Browse files
committed
docs(design): align Infeasible semantics with implementation, pin Deferred charge as a contract
Generation-aware Infeasible was rejected during implementation (the observedGeneration field requires a non-GA gate; upstream reason-only semantics adopted and pinned by a characterization test) - update the design to match. Note that the Deferred max(spec, actual) charge is a dependency of deferred-resize eviction (#1872 / #2051): the reserved target prevents backfill thrash after victim eviction. Signed-off-by: gshaibi <gshaibi@nvidia.com>
1 parent c397fd9 commit b940444

1 file changed

Lines changed: 22 additions & 11 deletions

File tree

  • docs/developer/designs/in-place-pod-resize

docs/developer/designs/in-place-pod-resize/README.md

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ Pod resource vector. Per container and resource, before Pod-level aggregation:
4343
normal / Deferred / in progress:
4444
effective = max(spec request, allocatedResources, status.resources)
4545
46-
Infeasible (current generation only):
46+
Infeasible:
4747
effective = max(allocatedResources, status.resources)
4848
```
4949

@@ -53,14 +53,25 @@ vector. Do not plumb a separate desired-resource vector through the
5353
scheduler; read the raw spec only for intent (proposed target, user-facing
5454
desired fields, infeasible diagnostics).
5555

56-
**Generation-aware `Infeasible`:** exclude the desired spec only when
57-
`PodResizePending=True`, reason `Infeasible`, `observedGeneration > 0`, and
58-
`observedGeneration == metadata.generation`. Ignore or sanitize stale
59-
conditions. On a new resize (new generation), an inherited `Infeasible` from
60-
the previous target must not hide the proposed spec until the kubelet reports
61-
that generation infeasible.
62-
63-
Implementation: one helper around upstream `resource.PodRequests` (status
56+
**`Infeasible` detection** delegates to upstream
57+
`resource.IsPodResizeInfeasible`, which keys off the condition reason alone.
58+
The kubelet owns the condition lifecycle — it clears or replaces
59+
`PodResizePending` when a new resize is submitted — so generation tracking is
60+
not needed, and `observedGeneration` is only populated behind the non-GA
61+
`PodObservedGenerationTracking` gate (a guard on it would disable `Infeasible`
62+
handling on gate-off clusters). Upstream semantics are pinned by a
63+
characterization test so a future upstream tightening surfaces as a failure.
64+
65+
The `Deferred` charge at `max(spec, actual)` is load-bearing beyond
66+
accounting: deferred-resize eviction
67+
([#1872](https://github.com/kai-scheduler/KAI-Scheduler/issues/1872),
68+
[#2051](https://github.com/kai-scheduler/KAI-Scheduler/pull/2051)) relies on
69+
the deferred target already being reserved in node and queue accounting, so
70+
capacity freed by evicting victims is not backfilled before the kubelet
71+
enacts the resize. Charging `Deferred` at actual only would reintroduce
72+
eviction thrash.
73+
74+
Implementation: upstream `resource.AggregateContainerRequests` (status
6475
resources enabled), then KAI custom-resource logic.
6576

6677
### Best-effort resize quota admission
@@ -122,12 +133,12 @@ Exact CR field names TBD at implementation.
122133
123134
| Topic | Decision |
124135
| --- | --- |
125-
| Accounting model | Upstream effective request; generation-aware `Infeasible` |
136+
| Accounting model | Upstream effective request; upstream reason-only `Infeasible` semantics (kubelet owns the condition lifecycle) |
126137
| Resize admit path | Keep native `pods/resize`; validate in webhook (do **not** convert to a KAI-owned scheduling API — breaks VPA / API contract) |
127138
| Non-preemptible growth past quota | Reject at webhook; keep reject at allocate |
128139
| Concurrent-resize / scheduler races | Best effort; optional `blockUpsizeOnBoundedQueues`; reservation ledger only if a concrete issue appears |
129140
| Drain-until-under-limit action | Rejected — poor UX; reclaim stays demand-driven |
130-
| Deferred resize preemption | Separate track: [#1872](https://github.com/kai-scheduler/KAI-Scheduler/issues/1872) |
141+
| Deferred resize preemption | Separate track: [#1872](https://github.com/kai-scheduler/KAI-Scheduler/issues/1872) / [#2051](https://github.com/kai-scheduler/KAI-Scheduler/pull/2051). Depends on `Deferred` charged at max(spec, actual) — the reserved target is its thrash safety |
131142
| Wait for upstream resize gates / KEP-5836 only | Rejected as sole plan — ship Goals accounting + admit now; upstream remains complementary ([kubernetes#131835](https://github.com/kubernetes/kubernetes/issues/131835)) |
132143

133144
## Known gaps

0 commit comments

Comments
 (0)