Skip to content

serviceentry: drain Terminating pods from ServiceEntry-derived endpoints#14332

Merged
davidjumani merged 2 commits into
kgateway-dev:mainfrom
nmnellis:fix/se-terminating-clean
Jun 30, 2026
Merged

serviceentry: drain Terminating pods from ServiceEntry-derived endpoints#14332
davidjumani merged 2 commits into
kgateway-dev:mainfrom
nmnellis:fix/se-terminating-clean

Conversation

@nmnellis

@nmnellis nmnellis commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Description

North-south traffic through kgateway to a global service (HTTPRoute → Istio Hostname backend → ServiceEntry-derived EDS) keeps routing to a Terminating local pod for the duration of its termination grace period, instead of failing over to a healthy peer-cluster endpoint. The east-west (ztunnel) path and the plain Kubernetes Service backend path both drain the pod correctly; only the ServiceEntry path does not.

Root cause. The ServiceEntry endpoint path filters workloads solely on the pod's Ready condition (LocalityPod.Ready, derived from isPodReadyConditionTrue). A pod that is terminating but still running keeps its Ready condition True through its preStop / grace period — kubelet does not flip it to false on deletion. The other terminal signal, checkPodTerminal, only covers Phase == Failed || Succeeded, so a Running terminating pod is not terminal either. Neither the pod's deletionTimestamp nor the EndpointSlice terminating condition is consulted. As a result the terminating pod stays in the Envoy EDS at priority 0, health_flags::healthy, the cross-cluster tier at priority 1 is never promoted, and new requests continue to hit the draining pod.

Change. Carry a Terminating flag on LocalityPod (deletionTimestamp != nil; false for WorkloadEntry/inline/remote endpoints, whose health is managed by the remote cluster) and skip terminating pod-backed workloads in endpointsFromWorkloads, extending the existing readiness guard. Scoped to local pods only, so cross-cluster failover targets are never evicted.

Change Type

/kind fix

Changelog

Fixed north-south traffic to a global service continuing to route to a local pod for the duration of its termination grace period. kgateway now drains a terminating pod (deletionTimestamp set) from ServiceEntry-derived endpoints and fails over to a healthy peer-cluster endpoint, consistent with the east-west (ztunnel) path and the Kubernetes Service backend path.

Additional Notes

Extends the ServiceEntry readiness fix (#14222) to the terminating state. The EndpointSlice-based Service path and ztunnel already drain terminating pods; this brings the ServiceEntry path to parity. Verified with a new unit test (TestEndpointsFromWorkloads_SkipsTerminatingPods) and end-to-end on a 2-cluster ambient kind mesh (terminating local pod is removed from the kgateway EDS and N/S fails over to the peer cluster).

Copilot AI review requested due to automatic review settings June 30, 2026 15:18
…d base for enterprise build)

Signed-off-by: Nick Nellis <[email protected]>
@gateway-bot gateway-bot added do-not-merge/description-invalid do-not-merge/kind-invalid Indicates a PR lacks a `kind/foo` label and requires one. do-not-merge/release-note-invalid Indicates that a PR should not merge because it's missing one of the release note labels. labels Jun 30, 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

This PR fixes ServiceEntry-derived endpoint selection so north-south traffic drains pods as soon as they begin terminating (deletionTimestamp set), preventing Envoy EDS from continuing to route to a terminating-but-still-Ready local pod for its full grace period and enabling timely failover to healthy peer-cluster endpoints.

Changes:

  • Extend krtcollections.LocalityPod with a Terminating flag derived from pod.DeletionTimestamp.
  • Update ServiceEntry workload->endpoint conversion to exclude pod-backed workloads that are either NotReady or Terminating.
  • Add unit coverage ensuring terminating pods are excluded while WorkloadEntry/inline endpoints remain included.

Reviewed changes

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

File Description
pkg/krtcollections/pods.go Adds Terminating to LocalityPod, includes it in equality, and populates it from pod deletionTimestamp.
pkg/kgateway/extensions2/plugins/serviceentry/endpoints.go Filters ServiceEntry-derived endpoints to skip terminating workloads in addition to not-ready workloads.
pkg/kgateway/extensions2/plugins/serviceentry/endpoints_test.go Adds a unit test asserting terminating-but-ready pods are excluded while WorkloadEntry endpoints remain.
pkg/kgateway/extensions2/plugins/serviceentry/collections.go Ensures WorkloadEntry/inline-derived synthetic workloads explicitly set Terminating: false.

@nmnellis nmnellis closed this Jun 30, 2026
@nmnellis nmnellis reopened this Jun 30, 2026
@nmnellis nmnellis closed this Jun 30, 2026
@davidjumani davidjumani reopened this Jun 30, 2026
@nmnellis
nmnellis force-pushed the fix/se-terminating-clean branch from 00b4c1b to b65953f Compare June 30, 2026 15:46
@gateway-bot gateway-bot added kind/fix Categorizes issue or PR as related to a bug. release-note and removed do-not-merge/description-invalid do-not-merge/kind-invalid Indicates a PR lacks a `kind/foo` label and requires one. do-not-merge/release-note-invalid Indicates that a PR should not merge because it's missing one of the release note labels. labels Jun 30, 2026

@ymesika ymesika 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.

LG, just nit

Comment thread pkg/kgateway/extensions2/plugins/serviceentry/collections.go Outdated
Signed-off-by: Nick Nellis <[email protected]>
@davidjumani
davidjumani enabled auto-merge June 30, 2026 17:03
@davidjumani
davidjumani added this pull request to the merge queue Jun 30, 2026
Merged via the queue into kgateway-dev:main with commit 4bb960d Jun 30, 2026
32 checks passed
@nmnellis
nmnellis deleted the fix/se-terminating-clean branch June 30, 2026 17:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/fix Categorizes issue or PR as related to a bug. release-note

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants