The post describes its new extension point twice and the two descriptions disagree, the pin matches neither, the feature reached stable four releases later and was never locked, and the use case the post was written to serve appears in exactly one file in the tree, which is this post¶
Post — Kubernetes 1.26: Pod Scheduling Readiness, 2022-12-26.
5,465 bytes over 129 lines, by Wei Huang (Apple) and Abdullah Gharaibeh (Google): the last walk
post of the year, and the fourth-shortest of its thirteen. It introduces one Pod field, draws the
same queue twice in mermaid, gives one use case, and points at the concept page and a KEP.
As written
Scheduling gates are keys that tell the scheduler when a Pod is ready to be considered (:11-12).
The problem they solve is stated as cost: the scheduler picks up every Pod the moment it is created,
a scheduling cycle may take ≅20ms or more (:19-20), and a Pod that cannot possibly run yet burns
one cycle after another being found unschedulable. The first mermaid diagram (:24-47) draws those
wasted cycles as a loop.
A Pod with a non-empty spec.schedulingGates is declared not ready, and those Pods will also be
ignored by Cluster Autoscaler (:49-52). Clearing the gates is explicitly the responsibility of
external controllers (:54-55) — the post proposes the mechanism and hands the policy to somebody
else. The second mermaid diagram (:57-85) redraws the queue with the gate in it, and its three
decisive edges are queue==>|PreEnqueue check|popout, popout-->|Yes|sched_cycle and
popout==>|No|queue (:66-68): the check happens when a Pod comes out of the queue, and failing
it puts the Pod back.
The field behaves very similar to Finalizers (:89). More than one gate can be added, but they
all should be added upon Pod creation (e.g., you can add them as part of the spec or via a mutating
webhook) (:91-92). A gated Pod shows SchedulingGated in kubectl get pods (:94-97). Gates
do not need to be removed all at once, but only when all the gates are removed the scheduler will
start to consider the Pod for scheduling (:99-101). Then the implementation note: scheduling
gates are implemented as a PreEnqueue scheduler plugin, a new scheduler framework extension point
that is invoked at the beginning of each scheduling cycle (:103-104).
One use case is given, and the post calls it an important use case this feature enables: dynamic
quota management (:106-118). ResourceQuota is enforced by the API server at Pod creation, so an
over-quota Pod is rejected outright and whoever created it must keep retrying — a delay between
resources becoming available and the Pod actually running, or load on the API server from constant
attempts. The proposal is an external quota manager that adds an example.com/quota-check gate to
every Pod through a mutating webhook and removes it when quota exists. To try any of it, the
PodSchedulingReadiness gate must be enabled in the API Server and scheduler (:120-121), and
the post closes by pointing at the concept page and KEP-3521 (:125-129).
As it runs now
There is nothing to enable. PodSchedulingReadiness went alpha in v1.26 for exactly one release,
beta and on by default in v1.27, and stable in v1.30; the gate file declares no locked: and no
removed:, so on the lab's v1.35 cluster the field is simply part of the Pod API. The instruction
at :120-121 is the one line of the post a reader can no longer carry out, and the reason is that
it succeeded.
The mechanism is unchanged and the post's description of it still reads as current. The status
string is still the literal SchedulingGated. Gates can still be removed one at a time with no
effect until the last one goes. The creation-only rule the post states as advice is stated by the
pin as a rule: SchedulingGates can only be set at pod creation time, and be removed only
afterwards (pod-v1.md:193). The concept page the post points at is still there, still named
pod-scheduling-readiness.md, and carries `{{< feature-state for_k8s_version="v1.30" state="stable"
}}
at:9`.
The extension point is also unchanged, and this is where the post and the pin part company.
scheduling-framework.md:58-67 gives PreEnqueue a section of its own: These plugins are called
prior to adding Pods to the internal active queue, where Pods are marked as ready for scheduling,
and only when all PreEnqueue plugins return Success, the Pod is allowed to enter the active
queue. Otherwise, it's placed in the internal unschedulable Pods list, and doesn't get an
Unschedulable condition (:60-64). Before the queue, not at the start of a cycle, and not on the
way out of the queue either — so the post's prose and the post's own diagram are both describing
something other than what the pin describes, and they are not describing the same wrong thing as
each other.
A fourth thing belongs here and is not a behaviour: the pin disagrees with itself about which Pod
fields you may change after creation. pods/_index.md:247-249 gives a closed list — Pod updates
may not change fields other than spec.containers[*].image, spec.initContainers[*].image,
spec.activeDeadlineSeconds, spec.terminationGracePeriodSeconds, spec.tolerations or
spec.schedulingGates — and .spec.nodeSelector and .spec.affinity are not in it. Elsewhere in
the same tree, pod-scheduling-readiness.md:94-113 says you may mutate both while a Pod is gated,
under four numbered rules, the first of which is for .spec.nodeSelector, only additions are
allowed. If absent, it will be allowed to be set (:99). A reader who trusts the Pod page will not
attempt the patch the scheduling page documents. One kubectl patch settles which page is right,
and it is step 4.
What this exercise does not cover, and where it lives
The observable shape of a gated Pod is already a lab. A pod the scheduler declines to look
at owns the PodScheduled=False condition with
reason SchedulingGated, the scheduler_pending_pods{queue="gated"} gauge, the absence of any
FailedScheduling event, the refusal when a gate is added to a Pod that is already gated, the
sub-second requeue when the last gate goes, the PreEnqueue source reading under pkg/scheduler/,
and the motivating question in KEP-3521. Nothing below re-derives any of that: Do spends its
refusals on two cases the lab does not hold, a Pod that never had a gate and a Pod that has finished
being gated.
What holds Pods at the PreEnqueue extension point at the pin is gang scheduling, and that belongs
to a later year's row, which owns it. The absence of Kueue from the documentation tree belongs to
this year's Introducing Kueue row, which owns it. Step 9 counts both; it does not explain either.
The diff, and why
Wrong when it was published. The post describes its own extension point twice and the two
descriptions do not agree. The prose says the PreEnqueue plugin is invoked at the beginning of
each scheduling cycle (:103-104). The diagram says the check happens on the way out of the queue,
and that failing it puts the Pod back: queue==>|PreEnqueue check|popout, popout==>|No|queue
(:66-68). The pin says neither — prior to adding Pods to the internal active queue, and a Pod
that fails is placed in the internal unschedulable Pods list, and doesn't get an Unschedulable
condition (scheduling-framework.md:60-64). The difference is the whole argument of the post. A
check at the beginning of a scheduling cycle is a check that has already cost a scheduling cycle,
which is the ≅20ms the post opens by objecting to (:19-20); the diagram's placement still pops the
Pod before deciding; only the pin's placement means the Pod is never queued and no cycle is spent.
The prose is not a later drift, because the diagram beside it already disagreed on the day it
published. Step 7 prints all three.
The same section understates one rule into advice. Gates should be added upon Pod creation
(:91-92), on the model of Finalizers — but Finalizers can be added at any time and gates cannot.
pod-v1.md:193 states it as a refusal, not a convention, and a reader who took the post's "should"
at face value would build the controller the post itself proposes at :115-118 and discover the API
will not have it. Step 6 collects the refusal from both sides: a Pod that never had a gate, and a
Pod that has finished being gated.
Still right. The mechanism is intact, down to the strings. SchedulingGated is still what
kubectl get pods prints (step 2). Gates still come off one at a time with no effect until the last
one (:99-101, step 3). The field is still list-of-names and still only initialisable at creation.
The Finalizers analogy still holds for the removal half even though it fails for the addition half.
And the one claim here about something outside the tree was not left to rot: those Pods will also
be ignored by Cluster Autoscaler (:49-52) is repeated and sharpened by the stable announcement
sixteen months later, where gating doesn't just cut the load on the scheduler, it can also save
money, because without scheduling gates, the autoscaler might otherwise launch a node that doesn't
need to be started (kubernetes-v1-30-release.md:95-98). The pin cannot verify a component it does
not contain; what it shows is that the claim was made twice, four releases apart.
Never absorbed. The post gives exactly one use case and calls it an important use case this
feature enables: dynamic quota management by an external manager that adds
example.com/quota-check through a mutating webhook. At the pin the phrase quota manager appears
in one file in the whole of content/en, and it is this post; under docs/ it appears zero times,
and the feature's own concept page contains the word quota zero times. The field was absorbed
completely and its reason for existing was not absorbed at all. Step 9 counts it. Naming only still
right here would record a feature that graduated and miss that the argument for it never reached
the documentation — and what does hold Pods at PreEnqueue in the pinned tree arrived from
somewhere else entirely, which is a later year's row and it owns that.
Retired by being agreed with. PodSchedulingReadiness was alpha for a single release, beta the
next, and stable four releases after this post. It was never locked and never removed; its file
records three stages and nothing else. The stronger evidence is where the field turned up: it is now
one of six names in the general rule for what a Pod update may change, sitting beside
spec.tolerations on the Pod concept page (pods/_index.md:247-249), which is not where features
live. And the posts stopped. Four posts in the archive have ever named schedulingGates — the 1.26
release note, this one, the 1.27 note that took it to beta, and the 1.30 note that took it to stable
— and the last of them is 2024-04-17, two years and four months before the pin. Step 10 lists all
four.
The subject is one gate and it climbed without a detour.
PodSchedulingReadiness
| stage | default | locked | releases |
|---|---|---|---|
| alpha | false |
— | v1.26 – v1.26 |
| beta | true |
— | v1.27 – v1.29 |
| stable | true |
— | v1.30 – |
No file-level fact sits under this table: PodSchedulingReadiness.md declares no removed:, no
locked: on any stage, and no former_titles:. The one-release alpha is not unusual on its own —
151 of the 487 gate files at the pin have fromVersion equal to toVersion on some stage — but
taken with the rest of the row it is the shape of a feature nobody argued about.
Topology
solo — one node, 4096MB, 4 vCPU, at 10.10.10.180,
running Kubernetes v1.35. One node is the right number: a gated Pod is not rejected by a node, it is
never offered to one, so a second node would add nothing to watch. Steps 1 to 6 run against the
cluster in a namespace called gates; steps 7 to 10 are offline and read the pinned checkout.
Do
- The field, before the post is opened.
kubectl explain pod.spec.schedulingGates
kubectl explain pod.spec.schedulingGates.name
kubectl create ns gates
- The pin's own example, applied without a character changed —
examples/pods/pod-with-scheduling-gates.yaml, which is the post's manifest with a name on it.
kubectl -n gates apply -f - <<'YAML'
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
schedulingGates:
- name: example.com/foo
- name: example.com/bar
containers:
- name: pause
image: registry.k8s.io/pause:3.6
YAML
kubectl -n gates get pod test-pod
- The post's claim at
:99-101: gates come off one at a time and nothing happens until the last.
kubectl -n gates patch pod test-pod --type=json \
-p '[{"op":"remove","path":"/spec/schedulingGates/1"}]'
kubectl -n gates get pod test-pod -o jsonpath='{.spec.schedulingGates}'; echo
kubectl -n gates get pod test-pod
- Which of the two pages is right.
pods/_index.md:247-249says.spec.nodeSelectormay not be changed after creation;pod-scheduling-readiness.md:99says it may, on a gated Pod, as long as you only add. Ask the cluster.
kubectl -n gates patch pod test-pod --type=merge \
-p '{"spec":{"nodeSelector":{"kubernetes.io/os":"linux"}}}'
echo "add exit $?"
kubectl -n gates patch pod test-pod --type=merge \
-p '{"spec":{"nodeSelector":{"kubernetes.io/os":"windows"}}}'
echo "change exit $?"
kubectl -n gates get pod test-pod -o jsonpath='{.spec.nodeSelector}'; echo
- Remove the last gate.
kubectl -n gates patch pod test-pod --type=json \
-p '[{"op":"remove","path":"/spec/schedulingGates"}]'
kubectl -n gates wait --for=condition=Ready pod/test-pod --timeout=60s
kubectl -n gates get pod test-pod -o wide
- The one-way door, from the two sides the lab does not hold: a Pod that never had a gate, and a Pod that has finished being gated.
kubectl -n gates run ungated --image=registry.k8s.io/pause:3.10 --restart=Never
kubectl -n gates wait --for=condition=Ready pod/ungated --timeout=60s
kubectl -n gates patch pod ungated --type=merge \
-p '{"spec":{"schedulingGates":[{"name":"example.com/late"}]}}'
echo "never-gated exit $?"
kubectl -n gates patch pod test-pod --type=merge \
-p '{"spec":{"schedulingGates":[{"name":"example.com/again"}]}}'
echo "once-gated exit $?"
- Offline from here. The extension point, described three times.
cd /path/to/kubernetes/website/content/en
echo "--- the post says ---"
sed -n '103,104p' blog/_posts/2022/pod-scheduling-readiness.md
echo "--- the post draws ---"
sed -n '66,68p' blog/_posts/2022/pod-scheduling-readiness.md
echo "--- the pin says ---"
sed -n '58,64p' docs/concepts/scheduling-eviction/scheduling-framework.md
- Every page that names the field, and the two rules that disagree.
cd /path/to/kubernetes/website/content/en
unwrap() { tr '\n' ' ' | tr -s ' ' | sed 's/^ //' | fold -s -w 92 | sed 's/ *$//'; echo; }
echo "--- pages naming the field ---"
grep -rl 'schedulingGates' --include='*.md' . | sed 's|^\./||' | sort
echo "--- the general Pod-update rule ---"
sed -n '247,249p' docs/concepts/workloads/pods/_index.md | unwrap
echo "--- the feature page, on the gates ---"
sed -n '24,27p' docs/concepts/scheduling-eviction/pod-scheduling-readiness.md | unwrap
echo "--- the feature page, on everything else ---"
sed -n '94,99p' docs/concepts/scheduling-eviction/pod-scheduling-readiness.md | unwrap
echo "--- the API reference ---"
sed -n '193p' docs/reference/kubernetes-api/core/pod-v1.md | sed 's/<[^>]*>//g' | unwrap
- What the extension point holds Pods for now, and what became of the use case.
cd /path/to/kubernetes/website/content/en
echo "--- every page that names the extension point ---"
grep -rlw 'PreEnqueue' --include='*.md' . | sed 's|^\./||' | sort
echo "--- what it holds Pods for at the pin ---"
grep -nw 'PreEnqueue' docs/concepts/scheduling-eviction/gang-scheduling.md | cut -c1-92
echo "--- the use case the post gives, counted ---"
printf 'quota manager, docs %s\n' "$(grep -rli 'quota manager' --include='*.md' docs | wc -l | tr -d ' ')"
printf 'quota manager, content/en %s\n' "$(grep -rli 'quota manager' --include='*.md' . | wc -l | tr -d ' ')"
printf 'Kueue, docs %s\n' "$(grep -rl 'Kueue' --include='*.md' docs | wc -l | tr -d ' ')"
printf 'Kueue, content/en %s\n' "$(grep -rl 'Kueue' --include='*.md' . | wc -l | tr -d ' ')"
-
The ladder, the trail of posts, and the drawings.
cd /path/to/kubernetes/website/content/en echo "--- the ladder ---" sed -n '/^stages:/,/^---/p' \ docs/reference/command-line-tools-reference/feature-gates/PodSchedulingReadiness.md | sed 's/ *$//' echo "--- every post that names the field, in date order ---" for f in $(grep -rl 'schedulingGates' --include='*.md' blog/_posts); do printf '%s %s\n' "$(grep -m1 '^date:' "$f" | sed 's/^date: *//')" "${f#blog/_posts/}" done | sort echo "--- and the drawings ---" printf 'posts in the archive containing "mermaid" %s\n' \ "$(grep -rl 'mermaid' --include='*.md' blog/_posts | wc -l | tr -d ' ')" printf '{{< mermaid >}} blocks in this post %s\n' \ "$(grep -c '{{< mermaid >}}' blog/_posts/2022/pod-scheduling-readiness.md | tr -d ' ')" printf '{{< figure >}} blocks on the feature page %s\n' \ "$(grep -c '{{< figure' docs/concepts/scheduling-eviction/pod-scheduling-readiness.md | tr -d ' ')"
Expect
Step 1 finds the field already there. kubectl explain answers for both paths without a word about
a feature gate, and the description it prints for schedulingGates is the sentence step 8 pulls out
of the API reference — the same text, because explain reads the OpenAPI schema that page is
generated from. Nothing in the post's closing instruction (:120-121) applies to this cluster:
there is no gate to enable, and no flag to pass to the scheduler.
Step 2 reproduces :94-97 exactly. test-pod is 0/1, SchedulingGated, 0 restarts. No node is
assigned, no event is emitted, and the Pod will sit there indefinitely. The manifest is the pin's
example file unchanged, which means it still pins registry.k8s.io/pause:3.6 while the rest of this
repository has moved to 3.10; leave it, because the image is not what is being tested and changing
it would make the manifest no longer the pin's.
Step 3 is the post's sentence at :99-101 made visible. The JSON patch removes index 1, the
jsonpath prints a one-element list holding example.com/foo, and get pod still says
SchedulingGated. One gate removed changed nothing, because the test is emptiness and not count.
Step 4 settles the disagreement, and the scheduling page wins. The first patch succeeds and prints
pod/test-pod patched, with add exit 0: .spec.nodeSelector was absent, so it was allowed to be
set, exactly as pod-scheduling-readiness.md:99 says. The second patch is rejected by the Pod
update validator and change exit is non-zero, because changing linux to windows is not an
addition. The jsonpath then prints {"kubernetes.io/os":"linux"} — the value from the first patch,
untouched. So pods/_index.md:247-249 is not the closed list it reads as; a gated Pod has a wider
mutable surface than the Pod page describes, and a reader who trusted that page would never have
tried.
Step 5 schedules. Removing the whole field leaves nothing to test for emptiness, the scheduler takes
the Pod, and wait returns pod/test-pod condition met in about a second. get pod -o wide shows
Running with the node name filled in; the kubernetes.io/os=linux selector added in step 4
matches, so the tightening did not cost anything.
Step 6 collects two refusals that say the same thing. ungated reaches Running normally, and
patching a gate onto it is rejected — never-gated exit is non-zero. Patching a gate back onto
test-pod, which had two gates a minute ago and now has none, is rejected the same way, and
once-gated exit is non-zero as well. There is no state in which a gate can be added to an existing
Pod. That is the hard version of the post's they all should be added upon Pod creation (:91-92),
and the reason the Finalizers analogy at :89 only half works: Finalizers can be added at any time.
Step 7 prints the three placements next to each other.
--- the post says ---
Under the hood, scheduling gates are implemented as a PreEnqueue scheduler plugin, a new scheduler
framework extension point that is invoked at the beginning of each scheduling cycle.
--- the post draws ---
queue==>|PreEnqueue check|popout
popout-->|Yes|sched_cycle
popout==>|No|queue
--- the pin says ---
### PreEnqueue {#pre-enqueue}
These plugins are called prior to adding Pods to the internal active queue, where Pods are marked as
ready for scheduling.
Only when all PreEnqueue plugins return `Success`, the Pod is allowed to enter the active queue.
Otherwise, it's placed in the internal unschedulable Pods list, and doesn't get an `Unschedulable` condition.
Read the three as a sequence and the post argues against itself. Its prose puts the check at the
beginning of each scheduling cycle, which is a check that has already paid for the cycle. Its
diagram puts the check on the edge out of the queue — queue==>|PreEnqueue check|popout — which
still pops the Pod first. The pin puts it before the queue, where the Pod is never made a candidate
and the cycle is never started, and adds the detail neither version of the post gives: a Pod that
fails the check doesn't get an Unschedulable condition, which is why a gated Pod has nothing to
show for itself in its events. Only the third placement saves the ≅20ms the post was written about.
Step 8 shows how small the field's footprint is, and prints the two rules in full.
--- pages naming the field ---
blog/_posts/2022/kubernetes-1.26-blog.md
blog/_posts/2022/pod-scheduling-readiness.md
blog/_posts/2023/kubernetes-1.27-release.md
blog/_posts/2024/kubernetes-v1-30-release.md
docs/concepts/scheduling-eviction/pod-scheduling-readiness.md
docs/concepts/workloads/pods/_index.md
docs/reference/command-line-tools-reference/feature-gates/PodSchedulingReadiness.md
docs/reference/kubernetes-api/core/pod-v1.md
--- the general Pod-update rule ---
- Pod updates may not change fields other than `spec.containers[*].image`,
`spec.initContainers[*].image`, `spec.activeDeadlineSeconds`,
`spec.terminationGracePeriodSeconds`, `spec.tolerations` or `spec.schedulingGates`. For
`spec.tolerations`, you can only add new entries.
--- the feature page, on the gates ---
The `schedulingGates` field contains a list of strings, and each string literal is
perceived as a criteria that Pod should be satisfied before considered schedulable. This
field can be initialized only when a Pod is created (either by the client, or mutated
during admission). After creation, each schedulingGate can be removed in arbitrary order,
but addition of a new scheduling gate is disallowed.
--- the feature page, on everything else ---
You can mutate scheduling directives of Pods while they have scheduling gates, with certain
constraints. At a high level, you can only tighten the scheduling directives of a Pod. In
other words, the updated directives would cause the Pods to only be able to be scheduled on
a subset of the nodes that it would previously match. More concretely, the rules for
updating a Pod's scheduling directives are as follows: 1. For `.spec.nodeSelector`, only
additions are allowed. If absent, it will be allowed to be set.
--- the API reference ---
SchedulingGates is an opaque list of values that if specified will block scheduling the
pod. If schedulingGates is not empty, the pod will stay in the SchedulingGated state and
the scheduler will not attempt to schedule the pod. SchedulingGates can only be set at pod
creation time, and be removed only afterwards.
Eight files in the whole tree, four of them posts and four of them documentation, and the four posts
are this one plus three release notes. The two rules are worth reading against each other slowly.
The Pod page's list is grammatically closed — may not change fields other than — and
.spec.nodeSelector is not on it. The feature page opens a second, wider door that exists only
while a Pod is gated. Both can be true at once — gating is itself a Pod state, and the two pages
write their rules at different scopes, one per state and one per field — but neither page says so,
and neither links to the other. Step 4 is the only thing in this file that tells you which page to
believe.
Step 9 is where the post's argument and the post's mechanism separate.
--- every page that names the extension point ---
blog/_posts/2022/pod-scheduling-readiness.md
blog/_posts/2024/scheduler-queueinghint/index.md
blog/_posts/2026/workload-aware-scheduling-1-36.md
docs/concepts/scheduling-eviction/gang-scheduling.md
docs/concepts/scheduling-eviction/scheduling-framework.md
docs/reference/config-api/kube-scheduler-config.v1.md
--- what it holds Pods for at the pin ---
35:1. The scheduler holds Pods in the `PreEnqueue` phase until:
80:queue in the `PreEnqueue` phase until it satisfies the **hierarchical quorum**. This quor
--- the use case the post gives, counted ---
quota manager, docs 0
quota manager, content/en 1
Kueue, docs 0
Kueue, content/en 11
The extension point this post introduced is in the config API and has its own section in the
framework reference, so it was not a one-feature hook. What holds Pods there in the pinned
documentation is gang scheduling, waiting on a quorum — an in-tree scheduler feature that arrived
years later and belongs to a later year's row, which owns it. The last four lines are the post's use
case, counted. Quota manager occurs in exactly one file in all of content/en, and that file is
this post, at :55 and :115; under docs/ it occurs zero times, and the feature's own concept
page does not contain the word quota at all. The project that did build queueing on top of the
idea appears in eleven files in content/en and none under docs/, which this year's Introducing
Kueue row already owns. The mechanism graduated; the reason given for it never got written down
anywhere but here.
Step 10 prints the ladder, the trail, and the drawings.
--- the ladder ---
stages:
- stage: alpha
defaultValue: false
fromVersion: "1.26"
toVersion: "1.26"
- stage: beta
defaultValue: true
fromVersion: "1.27"
toVersion: "1.29"
- stage: stable
defaultValue: true
fromVersion: "1.30"
---
--- every post that names the field, in date order ---
2022-12-09 2022/kubernetes-1.26-blog.md
2022-12-26 2022/pod-scheduling-readiness.md
2023-04-11 2023/kubernetes-1.27-release.md
2024-04-17 2024/kubernetes-v1-30-release.md
--- and the drawings ---
posts in the archive containing "mermaid" 11
{{< mermaid >}} blocks in this post 2
{{< figure >}} blocks on the feature page 1
Three stages, no locked: on any of them, and the trailing --- is the gate file's own front
matter ending — there is nothing after the ladder to print. The trail is four posts across sixteen
months and then nothing for the two years and four months to the pin, which for a Pod field that
every cluster now carries is the quiet ending rather than the loud one. The last three lines are a
smaller observation with the same shape: this post drew its queue twice in mermaid, one of eleven
posts in the whole archive to use the shortcode at all, and the concept page that inherited the
feature drew it once as a checked-in SVG. The diagrams did not survive the move either; only the
field did.
Read on
-
docs/concepts/scheduling-eviction/scheduling-framework.md:58-67, the wholePreEnqueuesection. Ten lines, and they contain the correction to this post's:103-104plus one fact the post never had a reason to mention: a Pod rejected here is put on an internal unschedulable list and given no condition. Read it before reading any of the post's two diagrams again. -
docs/concepts/scheduling-eviction/pod-scheduling-readiness.md:92-113, the four rules for mutating a gated Pod's scheduling directives. Rule 3 (:103-109) is the one worth the time: it allows additions tomatchExpressionsbut no changes to existing ones, and then gives the reason — the terms innodeSelectorTermsare ORed while the expressions inside a term are ANDed, so adding a term widens and adding an expression narrows. Step 4 only tests rule 1. -
blog/_posts/2024/kubernetes-v1-30-release.md:93-102, the stable announcement. It makes the cost argument this post only gestures at, and makes it in a currency: not ≅20ms of scheduler time but a node the autoscaler starts for a Pod that was never going to run. It is also the last time any post in the archive names the field. -
docs/concepts/scheduling-eviction/gang-scheduling.md:28-51, named and not explained here. It is what occupies the extension point this post created, and a later year's row owns it. Reading the two mechanisms in the wrong order makes gang scheduling look like the reasonPreEnqueueexists, which is backwards by several releases. -
Unanswerable from the pin: whether any external quota manager was ever built on the gate. The post proposes one at
:115-118and calls the use case important; four years later the phrase appears nowhere in the tree but in this post. The pin is one revision of a documentation tree, so it cannot distinguish between an idea nobody implemented, an idea implemented out of tree by people who never wrote it up, and an idea overtaken by Kueue before anyone finished. What it can tell you is that the field outlived the argument for it by a wide margin, and that the argument was never restated.
Teardown