Skip to content

docs: document that endpoint discovery honours custom pod readinessGates - #2604

Open
almogtavor wants to merge 2 commits into
llm-d:mainfrom
almogtavor:docs/readiness-gates
Open

docs: document that endpoint discovery honours custom pod readinessGates#2604
almogtavor wants to merge 2 commits into
llm-d:mainfrom
almogtavor:docs/readiness-gates

Conversation

@almogtavor

Copy link
Copy Markdown

What type of PR is this?

/kind documentation

What this PR does / why we need it:

The issue asks whether the router honours custom pod readinessGates, and notes
"the router may already support this; I just couldn't find any documentation."

It does, and it already behaves exactly as requested. Every readiness decision in
the EPP goes through podutil.IsPodReady (pkg/epp/util/pod/pod.go), which reads
the pod's aggregate Ready condition. The kubelet computes Ready as
ContainersReady AND every condition listed in spec.readinessGates, so an
unsatisfied gate holds the pod out of the routing pool with no EPP configuration
required, fail-closed. The same is true of the other two readiness call sites
(pkg/epp/datastore/datastore.go, the topology extractor).

So the gap was purely that this was never written down. This PR:

  1. Documents the contract in docs/discovery.md, including the detail that a
    gated pod still shows 1/1 in kubectl get pods (that column counts ready
    containers, not the Ready condition) -- which is the thing that makes this
    confusing to verify by hand.
  2. Adds IsPodReady cases for a satisfied and an unsatisfied readiness gate, so
    the behaviour is pinned rather than incidental.

The unsatisfied-gate case has teeth: switching IsPodReady from corev1.PodReady
to corev1.ContainersReady fails it.

$ go test ./pkg/epp/util/pod/...      # with that regression introduced
--- FAIL: TestIsPodReady/Pod_with_an_unsatisfied_readiness_gate
FAIL

Verification (OpenShift 4.21 / k8s v1.32, live EPP against an InferencePool):

Two pods labelled for the pool, one with readinessGates: [custom.orchestrator.io/serving]:

$ oc get pod vllm-gated -o jsonpath='...'      $ oc get pod vllm-ungated -o jsonpath='...'
Ready=False                                     Ready=True
ContainersReady=True                            ContainersReady=True

The EPP admitted only the ungated pod:

{"msg":"Pod added","name":"vllm-ungated"}

Patching the gate condition to True flipped Ready=True, and the EPP picked the
pod up on the next reconcile:

{"msg":"Pod added","name":"vllm-gated"}

This also covers the use cases in the issue -- checkpoint restorers, out-of-band
warm-up agents, dynamic weight loaders -- and the llm-d/llm-d#2365
Snapshot Orchestrator integration it references.

If maintainers would rather also see this asserted end-to-end against a live pool,
I'm happy to add an integration test; I kept the PR to docs plus a unit-level pin
since the behaviour itself needs no change.

Which issue(s) this PR fixes:

Fixes #2541

Release note:

NONE

The EPP admits a pod into the routing pool only when the pod's aggregate Ready
condition is True. The kubelet computes Ready as ContainersReady AND every
condition named in spec.readinessGates, so custom readiness gates already gate
routing fail-closed, with no EPP configuration required. That was not written
down anywhere, so it was not discoverable.

Document the contract in docs/discovery.md, including the point that a gated pod
still shows 1/1 in kubectl get pods because that column counts ready containers,
not the Ready condition.

Add IsPodReady cases for a satisfied and an unsatisfied readiness gate so the
behaviour is pinned. The unsatisfied case fails if IsPodReady is ever switched
from PodReady to ContainersReady.

Signed-off-by: Almog Tavor <almogtavor@gmail.com>
Copilot AI lite review requested due to automatic review settings August 28, 2026 11:09
@almogtavor
almogtavor requested a review from a team as a code owner August 28, 2026 11:09
@github-actions github-actions Bot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. area/epp area/docs labels Aug 28, 2026
@github-actions github-actions Bot added the kind/documentation Categorizes issue or PR as related to documentation. label Aug 28, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Documents how the EPP’s Kubernetes pod discovery determines readiness (by reading the pod’s PodReady condition) and adds unit tests that pin readiness-gate behavior via that contract.

Changes:

  • Document that Kubernetes discovery admits pods only when the aggregate Ready (PodReady) condition is True, which implicitly honors spec.readinessGates.
  • Add IsPodReady unit tests covering both satisfied and unsatisfied readiness-gate scenarios.

Reviewed changes

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

File Description
pkg/epp/util/pod/pod_test.go Adds unit test cases that ensure readiness-gated pods are excluded unless PodReady is True.
docs/discovery.md Adds a Kubernetes discovery readiness section explaining how PodReady (and thus readiness gates) controls routing eligibility.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@omerap12 omerap12 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

overall lgtm
PTAL @vMaroon

Comment thread pkg/epp/util/pod/pod_test.go Outdated
Comment on lines +129 to +131
// The kubelet ANDs every readiness gate into PodReady, so an
// unsatisfied gate holds PodReady at False even though the
// containers themselves are ready.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: not sure if those comments are needed.

Comment thread docs/discovery.md Outdated
Comment on lines +86 to +91
This is a **fail-closed** contract, which is what makes readiness gates useful
for out-of-band lifecycle managers -- checkpoint restorers, warm-up agents, and
dynamic weight loaders -- that need to hold traffic back until work that the
container probes cannot observe has finished. Note that a gated pod still shows
`1/1` in `kubectl get pods`, because that column counts ready *containers*; the
`Ready` **condition** is the one the EPP reads.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: not sure if those comments are needed.

Drop the inline kubelet explanation from the test case and condense the
closing paragraph in docs/discovery.md, keeping the 1/1 vs Ready-condition
note that is the non-obvious part.

Signed-off-by: Almog Tavor <almogtavor@gmail.com>
@github-actions github-actions Bot added size/M Denotes a PR that changes 30-99 lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Aug 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/docs area/epp kind/documentation Categorizes issue or PR as related to documentation. size/M Denotes a PR that changes 30-99 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: Support custom pod readinessGates in router endpoint discovery

3 participants