Skip to content

fix: reconcile EC2 endpoints promptly after backend changes#14228

Merged
puertomontt merged 4 commits into
kgateway-dev:mainfrom
puertomontt:ec2-endpoint-refresh
Jun 25, 2026
Merged

fix: reconcile EC2 endpoints promptly after backend changes#14228
puertomontt merged 4 commits into
kgateway-dev:mainfrom
puertomontt:ec2-endpoint-refresh

Conversation

@puertomontt

Copy link
Copy Markdown
Contributor

Description

EC2 endpoint discovery resolves instances on a periodic refresh tick (default 30s) and caches the result per backend. Three eventual-consistency gaps follow from the cached state only updating on that tick:

  1. Spec changes served stale endpoints. When a backend's ec2 config changed (port, address type, filters, region), KRT recomputed the endpoints immediately but served the addresses and port resolved under the old config until the next tick — a port change routed traffic to the wrong port for up to a full refresh interval.
  2. New backends served nothing for up to a tick. A newly created EC2 backend had no cached state and waited out the refresh interval before getting endpoints.
  3. Credential rotation + transient AWS failure wiped endpoints. The carry-forward that preserves endpoints across a failed listing required full config equality, including the secret resourceVersion and role ARN. Any secret update (even a no-op annotation change) reset the carried state, so a concurrent listing failure dropped healthy endpoints.

Changes

  • ec2BackendStateKey gains endpointSemanticsEqual, comparing only the fields that determine which endpoints a listing yields (region, port, address type, filters) and deliberately excluding credential fields (role ARN, secret), which only affect authorization to list.
  • endpointsForBackend now compares the cached state's config key against the backend's current config:
    • cached state resolved under different endpoint semantics is discarded rather than served (fixes 1);
    • a credential-only mismatch keeps serving the cached endpoints — they are still the right targets — while discovery re-lists under the new credentials.
  • A single-slot refreshCh lets the KRT transform request an immediate on-demand refresh whenever state is missing (fixes 2) or stale (shrinks the staleness window in 1 from the refresh interval to roughly one DescribeInstances round-trip). Requests coalesce in the buffer; there is no re-trigger loop because every refresh — including a failed one — rewrites the state key to the current config.
  • The carry-forward in computeState now uses endpointSemanticsEqual, so a credential-only change followed by a failed re-list keeps the previously resolved endpoints (fixes 3). Semantic changes still clear them.

Behavior note

For a semantic spec change, this trades "briefly wrong endpoints" for "briefly no endpoints" until the on-demand refresh lands. For a port change, serving the old port was actively wrong; the no-endpoint window is now typically a single AWS API round-trip rather than the refresh interval.

Change Type

/kind fix

Changelog

Fixed EC2 backend discovery serving endpoints resolved under an outdated config (e.g. the old port) for up to a refresh interval after a Backend spec change. Spec changes and newly created EC2 backends now trigger an immediate discovery refresh, and a credential rotation combined with a transient AWS API failure no longer drops healthy endpoints.

Additional Notes

Unit-test coverage: refresh requested when state is missing, stale state discarded after a port change, cached endpoints served across a credential-only change, and carry-forward preserved across a credential-only change with a failing lister. The existing test asserting that a full config change clears endpoints on failure is unchanged.

Three eventual-consistency gaps in EC2 discovery, all stemming from the
endpoint state only updating on the periodic refresh tick:

- A spec change (port, address type, filters, region) served endpoints
  resolved under the old config for up to a full refresh interval; a port
  change routed traffic to the wrong port. The cached state now carries
  its config key, and endpoints resolved under different endpoint
  semantics are discarded instead of served.
- A newly created backend served no endpoints until the next tick. The
  KRT transform now requests an immediate on-demand refresh (coalesced
  via a single-slot channel) when state is missing or stale.
- A credential rotation (secret resourceVersion bump or role change)
  combined with a transient AWS listing failure wiped healthy endpoints,
  because the carry-forward required full config equality. Carry-forward
  and serving now tolerate credential-only changes: credentials affect
  authorization to list instances, not which endpoints a listing yields.

Signed-off-by: omar <[email protected]>
Copilot AI review requested due to automatic review settings June 10, 2026 22:57
@gateway-bot gateway-bot added kind/fix Categorizes issue or PR as related to a bug. release-note labels Jun 10, 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 improves EC2 backend endpoint discovery by eliminating stale endpoint serving after Backend spec changes and by triggering on-demand refreshes to reduce time-to-correctness for new or changed backends, while also preserving previously-resolved endpoints across credential-only changes when AWS listing fails.

Changes:

  • Added endpointSemanticsEqual to distinguish endpoint-affecting config changes from credential-only changes.
  • Introduced a single-slot refreshCh and on-demand refresh requests to reconcile missing/stale state promptly.
  • Updated state carry-forward logic to preserve endpoints across credential-only changes during refresh failures, and updated endpointsForBackend to discard cached endpoints resolved under outdated endpoint semantics.

Reviewed changes

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

File Description
pkg/kgateway/extensions2/plugins/backend/ec2.go Adds endpoint-semantics comparison, on-demand refresh signaling, and updated caching/serve logic to avoid stale endpoints and preserve endpoints across credential-only changes.
pkg/kgateway/extensions2/plugins/backend/ec2_test.go Adds unit tests covering on-demand refresh requests, stale-state discard on semantic changes, and endpoint preservation across credential-only changes with refresh failures.

@davidjumani
davidjumani added this pull request to the merge queue Jun 25, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 25, 2026
@puertomontt
puertomontt added this pull request to the merge queue Jun 25, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to failed status checks Jun 25, 2026
@puertomontt
puertomontt added this pull request to the merge queue Jun 25, 2026
Merged via the queue into kgateway-dev:main with commit a0d1fd7 Jun 25, 2026
32 checks passed
@puertomontt
puertomontt deleted the ec2-endpoint-refresh branch June 25, 2026 16:50
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.

4 participants