feat: WithOrderedADS is possible but off by default#14372
Conversation
# 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]>
There was a problem hiding this comment.
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
EnableOrderedAdssetting fromapi/settingsinto the control plane and passessotwv3.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. |
Signed-off-by: David L. Chandler <[email protected]>
Signed-off-by: David L. Chandler <[email protected]>
Signed-off-by: David L. Chandler <[email protected]>
| 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) |
There was a problem hiding this comment.
Why not just pass the entire global settings field ?
There was a problem hiding this comment.
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.
Signed-off-by: David L. Chandler <[email protected]>
Description
Adopts ordered ADS response delivery behind the default-off
KGW_ENABLE_ORDERED_ADSsetting.When enabled, kgateway passes
sotwv3.WithOrderedADS()to go-control-plane. kgateway’s ADS snapshot cache already produces responses in dependency-oriented type order: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 transient503 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:
KGW_ENABLE_ORDERED_ADSremains 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=truein one e2e matrix leg, includingxds_warmingcoverage, and in one Gateway API conformance leg. We should watch for NACKs, clusters stuck warming,xds_warmingflakes, and snapshot-to-ACK latency before considering a default flip.Tests
This adds stream-level regression coverage for the important boundaries:
The tests cover both default and ordered modes so the intended behavioral difference remains explicit.
Change Type
/kind feature
Changelog