Skip to content

feat: WithOrderedADS is possible but off by default#14372

Merged
davidjumani merged 4 commits into
kgateway-dev:mainfrom
chandler-solo:chandler/14184ordered-ads
Jul 15, 2026
Merged

feat: WithOrderedADS is possible but off by default#14372
davidjumani merged 4 commits into
kgateway-dev:mainfrom
chandler-solo:chandler/14184ordered-ads

Conversation

@chandler-solo

@chandler-solo chandler-solo commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Description

Adopts ordered ADS response delivery behind the default-off KGW_ENABLE_ORDERED_ADS setting.

When enabled, kgateway passes sotwv3.WithOrderedADS() to go-control-plane. kgateway’s ADS snapshot cache already produces responses in dependency-oriented type order:

CDS -> EDS -> LDS -> RDS

The default SotW server does not always preserve that order on the wire. It drains separate per-type response channels with reflect.Select, so when several responses are ready at once on a busy stream, an RDS update can be sent before the CDS update containing the cluster it references. Envoy can then briefly hold a valid route whose cluster has not arrived yet, producing a transient 503 NC.

WithOrderedADS() switches ADS streams to a single multiplexed response path. This preserves the snapshot cache response order on the wire and closes the same-snapshot busy-stream addition reordering window.

Busy streams are common in kgateway: backend changes can update CDS and EDS together, route or listener changes can update LDS and RDS together, and proxy startup can answer all ADS watches from one initial snapshot. Making this ordering deterministic removes a rare but user-visible and difficult-to-debug class of transient configuration failure.

This is deliberately a small, reversible change:

  • No CRD, API, proxy-bootstrap, or snapshot-construction changes.
  • The callback and authentication wiring are unchanged.
  • KGW_ENABLE_ORDERED_ADS remains an escape hatch while the new server path soaks.

What this does not solve

Ordered ADS preserves the cache’s existing type order; it does not make every multi-snapshot xDS transition safe.

If Envoy has not ACKed a prior CDS response, the CDS watch is closed. A later snapshot can still send an RDS update through its open watch before the later CDS update can be sent. Ordered ADS cannot order a CDS response that is not ready.

Similarly, the fixed type order is wrong for combined removals: if a snapshot removes a cluster and de-references it from a route, CDS removal is sent before the RDS de-reference. Ordered ADS makes this deterministic; the default path merely made it nondeterministic.

Follow-up work in EP #13586 referenced-only cluster discovery should add reference-ahead and de-reference grace behavior so kgateway avoids publishing those risky combinations in the same vulnerable window.

This is also not a Delta xDS migration. kgateway continues to use SotW ADS.

Trade-offs and rollout

The ordered path is a less-traveled go-control-plane server path. It funnels response types through one buffered multiplexed channel instead of preserving independent per-type response channels and backpressure. A response can be superseded while a resource type is re-subscribed; SotW version handling is expected to re-answer from the new watch, but this changed recovery behavior warrants a soak.

The setting is default-off initially. This PR enables KGW_ENABLE_ORDERED_ADS=true in one e2e matrix leg, including xds_warming coverage, and in one Gateway API conformance leg. We should watch for NACKs, clusters stuck warming, xds_warming flakes, and snapshot-to-ACK latency before considering a default flip.

Tests

This adds stream-level regression coverage for the important boundaries:

  • Quiet-stream additions deliver CDS before RDS.
  • ACK skew can still deliver RDS before a later CDS update, even with ordered ADS.
  • Combined removals still deliver cluster removal before route de-reference in ordered mode.

The tests cover both default and ordered modes so the intended behavioral difference remains explicit.

Change Type

/kind feature

Changelog

Added default-off support for ordered ADS delivery via KGW_ENABLE_ORDERED_ADS=true, preserving CDS, EDS, LDS, and RDS response order for same-snapshot busy-stream additions.

# Description

Adopts ordered ADS response delivery behind the default-off `KGW_ENABLE_ORDERED_ADS` setting.

When enabled, kgateway passes `sotwv3.WithOrderedADS()` to
go-control-plane so ADS responses are sent in snapshot cache type
order: CDS, EDS, LDS, then RDS. This closes the busy-stream addition
reordering window where a route can otherwise reach Envoy before the
cluster from the same snapshot.

This also adds stream-level regression coverage for the important boundaries:
- quiet-stream additions deliver CDS before RDS
- ACK skew can still deliver RDS before a later CDS update, even with ordered ADS
- combined removals still deliver cluster removal before route de-reference in ordered mode

# Change Type

/kind feature

# Changelog

```release-note
Added default-off support for ordered ADS delivery via KGW_ENABLE_ORDERED_ADS=true, causing ADS responses within one snapshot to be delivered in CDS, EDS, LDS, RDS order.
```

# Additional Notes

Next steps are to soak `KGW_ENABLE_ORDERED_ADS=true` in one
e2e/conformance CI leg, especially coverage that exercises xDS warming
paths, then consider flipping the default after the soak is clean.

The new tests also document two delivery-order cases that this PR does
not solve. If a CDS response is still awaiting ACK, Envoy can receive
an RDS update before the later CDS update that makes its cluster
available. If one snapshot removes a cluster and removes the route
reference to it, ordered ADS makes the CDS removal arrive before the
RDS de-reference. Follow-up work should add reference-ahead and
de-reference grace behavior so kgateway avoids publishing those risky
combinations in the same vulnerable window (see EP [kgateway-dev#13586
referenced-only cluster
discovery](kgateway-dev#14341).)

Signed-off-by: David L. Chandler <[email protected]>

ci: soak ordered ADS in e2e and conformance

Enable KGW_ENABLE_ORDERED_ADS for one PR e2e matrix leg and one
Gateway API conformance leg so the default-off ordered ADS path gets
regular CI coverage before any default flip.

The e2e soak is scoped to cluster-six, which includes rollout/xDS-heavy
coverage. The conformance action now accepts an ordered-ads input and
passes it through to Helm as controller.extraEnv.KGW_ENABLE_ORDERED_ADS.

Signed-off-by: David L. Chandler <[email protected]>
Copilot AI review requested due to automatic review settings July 9, 2026 05:10
@chandler-solo
chandler-solo requested a review from a team as a code owner July 9, 2026 05:10
@chandler-solo chandler-solo added the work in progress Indicates that a PR should not merge because it is a work in progress label Jul 9, 2026
@gateway-bot gateway-bot added kind/feature Categorizes issue or PR as related to a new feature. release-note labels Jul 9, 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

Adds an opt-in “ordered ADS” mode to kgateway’s xDS control-plane wiring so that, when enabled via KGW_ENABLE_ORDERED_ADS=true, ADS responses are delivered in snapshot cache type order (CDS, EDS, LDS, RDS). This aims to reduce same-snapshot reordering windows where an RDS update can arrive before its dependent CDS addition.

Changes:

  • Plumbs a new EnableOrderedAds setting from api/settings into the control plane and passes sotwv3.WithOrderedADS() to go-control-plane when enabled.
  • Adds unit-level ADS stream regression tests covering ordering behavior for additions, ACK skew, and combined removals.
  • Introduces a CI “soak” leg for ordered ADS in e2e and conformance workflows.

Reviewed changes

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

Show a summary per file
File Description
pkg/kgateway/setup/setup.go Passes the ordered ADS setting into control plane initialization.
pkg/kgateway/setup/controlplane.go Conditionally enables go-control-plane ordered ADS via an XDS option.
pkg/kgateway/setup/ads_delivery_order_test.go Adds ADS delivery-order regression tests using an in-process ADS stream harness.
api/settings/settings.go Introduces EnableOrderedAds setting and documents its behavior.
api/settings/settings_test.go Extends env-var parsing/coverage tests to include KGW_ENABLE_ORDERED_ADS.
.github/workflows/e2e.yaml Enables an ordered ADS soak in a single e2e matrix leg by patching Helm env values.
.github/workflows/conformance.yaml Enables ordered ADS soak for experimental/amd64 conformance runs.
.github/actions/kube-conformance-tests/action.yaml Adds ordered-ads input and passes it through to Helm installs.

Comment thread pkg/kgateway/setup/ads_delivery_order_test.go
Comment thread .github/actions/kube-conformance-tests/action.yaml
Comment thread .github/actions/kube-conformance-tests/action.yaml
Comment thread api/settings/settings.go Outdated
Signed-off-by: David L. Chandler <[email protected]>
Signed-off-by: David L. Chandler <[email protected]>
@chandler-solo chandler-solo changed the title [WIP] WithOrderedADS is possible but off by default chore: WithOrderedADS is possible but off by default Jul 14, 2026
@chandler-solo chandler-solo changed the title chore: WithOrderedADS is possible but off by default feat: WithOrderedADS is possible but off by default Jul 14, 2026
@chandler-solo chandler-solo removed the work in progress Indicates that a PR should not merge because it is a work in progress label Jul 14, 2026
var cache envoycache.SnapshotCache
if s.globalSettings.EnableEnvoy {
cache = NewControlPlane(ctx, s.xdsListener, uniqueClientCallbacks, authenticators, s.globalSettings.XdsAuth, certWatcher)
cache = NewControlPlane(ctx, s.xdsListener, uniqueClientCallbacks, authenticators, s.globalSettings.XdsAuth, certWatcher, s.globalSettings.EnableOrderedAds)

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.

Why not just pass the entire global settings field ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Coupling. I could image splitting out a small control-plane-specific struct that we pass, but I don't want people to have to think about the other things in settings besides xds auth and ordered ADS.

@chandler-solo
chandler-solo added this pull request to the merge queue Jul 14, 2026
@davidjumani
davidjumani removed this pull request from the merge queue due to a manual request Jul 14, 2026
@davidjumani
davidjumani added this pull request to the merge queue Jul 14, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 14, 2026
@chandler-solo
chandler-solo added this pull request to the merge queue Jul 15, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 15, 2026
@davidjumani
davidjumani added this pull request to the merge queue Jul 15, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jul 15, 2026
@davidjumani
davidjumani added this pull request to the merge queue Jul 15, 2026
Merged via the queue into kgateway-dev:main with commit 1a87cfb Jul 15, 2026
37 of 41 checks passed
sheidkamp pushed a commit to sheidkamp/kgateway that referenced this pull request Jul 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/feature Categorizes issue or PR as related to a new feature. release-note

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants