🎉 Welcome to the v2.5.0-rc.1 release of the kgateway project!
Release Notes
Changes since v2.4.0
Breaking Changes
-
Route source metadata now uses exactly the original xRoute's rule name for the
rulefield if available. Otherwise, a generated value that reflects the rule's index in the list of rules is used. Additionally, the originating match's index is added as thematchfield. (#14522) -
The deprecated
HTTPListenerPolicyCRD has been removed. Migrate toListenerPolicyby moving the policy spec underspec.default.httpSettings; no fields were renamed or dropped. Migrate before upgrading — the chart upgrade deletes the CRD and Kubernetes garbage-collects any remainingHTTPListenerPolicyobjects. See the migration guide: https://github.com/kgateway-dev/kgateway/blob/main/docs/guides/migrating-httplistenerpolicy-to-listenerpolicy.md (#14542) -
Envoy HTTP connection manager and TCP proxy stats are now reported per listener.
stat_prefixfollows a stable format:http_<port>for HTTP listeners,https_<port>_<listener>for HTTPS listeners (https_<port>_<namespace>_<listenerset>_<listener>for ListenerSet listeners), andtcp_<port>_<namespace>_<route>/tls_<port>_<namespace>_<route>for TCPRoutes and TLSRoutes. Previously every HTTP and HTTPS listener sharedstat_prefix: http, and TCPRoute/TLSRoute prefixes contained dots that split them across metric names.Action required if you consume Envoy stats: queries that match
envoy_http_conn_manager_prefix="http"or the old per-routeenvoy_tcp_*metric names, andGatewayParametersstats.matcherentries that match raw stat names such ashttp.http., must be updated. Aggregations that ignore these labels are unaffected. Gateways with many HTTPS listeners or ListenerSets will expose more HCM series, one set per listener.
(#14753) -
Removed the
kgateway_translator_translations_runningandkgateway_controller_reconciliations_runninggauges, and thetranslator="TranslateHTTPRoute"series ofkgateway_translator_translations_totalandkgateway_translator_translation_duration_seconds. Recording these series on every route of every Gateway translation cost significant CPU at scale. (#14812) -
Removed the
kgateway_status_syncer_status_syncs_totalandkgateway_status_syncer_status_sync_duration_secondsmetrics. Usekgateway_resources_status_sync_duration_secondsfor status latency andkgateway_resources_status_syncs_started_totalminuskgateway_resources_status_syncs_completed_totalfor resources whose status is out of sync. For code built on kgateway:statussync.RecordStatusSync,statussync.RecordStatusSyncOutcome,statussync.SyncMetricLabels,statussync.ConditionErrorandpluginutils.ConditionErrorMetricwere removed,RegisterPolicyStatusWithBuilderno longer takes aConditionErrorMetricargument, andstatussync.Writer.OnSyncno longer receives atime.Duration. Callstatussync.EndResourceStatusSyncOnWriteSuccessfromOnSyncinstead ofRecordStatusSyncOutcome. (#14829) -
Removed the deprecated support for running kgateway as an Istio ambient waypoint:
- the
kgateway-waypointGatewayClass - Istio AuthorizationPolicy translation
- the
KGW_WAYPOINT_LOCAL_BINDINGsetting
To move existing kgateway waypoints to Istio waypoints, see the migration guide.
Sending ingress traffic through an Istio waypoint with the
istio.io/ingress-use-waypointlabel is still supported:- With Helm, it is still enabled by the value
waypoint.enabled. - Without Helm, set
KGW_INGRESS_USE_WAYPOINTS=true. Its default changed fromtruetofalse. KGW_ENABLE_WAYPOINTis deprecated. It still enables this feature whenKGW_INGRESS_USE_WAYPOINTSis unset, and will be removed in a future release.
RBAC: the controller ClusterRole still grants get/list/watch on
authorizationpolicies.security.istio.ioin this release so that upgrades are safe, but kgateway no longer uses it. It will be removed in the next minor release. If you maintain a custom ClusterRole, or rely on this rule for anything else, plan for its removal.
(#14831) - the
-
Removed the
kgateway_resources_status_syncs_started_total,kgateway_resources_status_syncs_completed_totalandkgateway_resources_status_sync_duration_secondsmetrics. Addedkgateway_status_writes_total{kind, result}, which counts status writes by result (written,unchanged,conflict,not_found,error); alert onresult="error"to catch status writes that failed after every retry. For code built on kgateway:statussync.Writer.OnSync,statussync.EndResourceStatusSyncOnWriteSuccess,metrics.StartResourceStatusSyncandmetrics.EndResourceStatusSyncwere removed. (#14838) -
The gateway proxy now defaults to a drain time of 60s with drain strategy immediate instead of Envoy's defaults (600s, gradual). When a listener is changed or removed, its old connections are now asked to close right away and are force-closed after 60 seconds, instead of being phased out over 10 minutes. This frees the memory held by old listener configuration much sooner. Long-lived connections may now be closed after 60s if the listener was modified. To restore the previous behavior, set
--drain-time-s 600 --drain-strategy gradualin GatewayParametersspec.kube.envoyContainer.extraArgs. (#14855) -
Changing a Gateway or ListenerSet listener port no longer restarts the proxy pods.
Listener ports are no longer listed as container ports on the proxy Deployment.
If you reference the proxy pods' named ports (listener-<port>) from your own Services, switch to port numbers before upgrading. If you run the proxy with hostNetwork, add the ports back with a deploymentOverlay.
(#14866) -
Bump Gateway API to v1.7.0-rc.3.
- Route
sessionPersistencenow usescookie.name,cookieandheader.name;sessionNameandcookieConfigare removed. Migrate them before upgrading the CRDs. - With
cookie.lifetimeTypeunset, the cookie is now a Session cookie andabsoluteTimeouthas no effect. SetlifetimeType: Permanentto keep the Max-Age. - HTTPRoute
retryapplies even with experimental Gateway API features disabled. - Backends with a BackendTLSPolicy and no appProtocol now negotiate HTTP/2 or HTTP/1.1 via ALPN. Set
appProtocol: httpto keep HTTP/1.1. - Terminate and Passthrough TLS listeners can share a port with experimental Gateway API features disabled.
- Waypoint AuthorizationPolicy HTTP method matches are now case-insensitive.
- The minimum supported Kubernetes version is now 1.33.
(#14882)
- Route
New Features
-
Added
spec.requestMirrortoTrafficPolicy. This field allows users to control theHost/:authorityheader of mirrored requests.disableShadowHostSuffixAppenddisables appending-shadowto the end of theHost/:authorityheader value, andhostRewriteLiteralreplaces the mirroredHost/:authorityheader value with a literal value. (#14441) -
Add grpcStats to HTTPListenerPolicy to expose Envoy's grpc_stats filter for per-service/method gRPC metrics. (#14452)
-
Added a
proxy100Continuefield toHTTPSettingson theListenerPolicyCRD to enable end-to-end proxying of HTTP 1xx informational responses. (#14485) -
Add BackendConfigPolicy support for separating local-origin outlier detection failures from externally generated errors. (#14486)
-
Added an optional
timeoutfield toRemoteJWKSin the JWT TrafficPolicy to allow users to configure the fetch timeout for remote JWKS servers. (#14501) -
Add
controller.goMemLimitPercentto setGOMEMLIMITas a percentage of the controller memory limit, disabled by default. (#14537) -
Add
stripTrailingHostDotto ListenerPolicyhttpSettings, exposing Envoy'sstrip_trailing_host_dotso requests with a trailing dot in the Host/authority header can match routes. (#14547) -
Expose
envoy'smax_connection_durationviaListenerPolicyandBackendConfigPolicy. (#14559) -
Add
percentEnabled/percentEnforcedfields to theRateLimitProviderGatewayExtension, enabling shadow mode for global rate limiting (call the rate limit service without enforcing its decision) via Envoy'sfilter_enabled/filter_enforcedruntime settings. (#14583) -
Add httpUpgrade to TrafficPolicy for configuring HTTP protocol upgrades, including CONNECT termination. (#14587)
-
Added
normalizePathandmergeSlashesfields toListenerPolicy'shttpSettingsto control whether the HTTP Connection Manager normalizes request paths and merges adjacent slashes. Both default totrue, matching prior (hardcoded) behavior. (#14619) -
Add
buffer.filterStageto TrafficPolicy, which moves the buffer filter earlier in the filter chain so thatmaxRequestSizeenforces ahead of filters that read the request body, such as ext_proc. The default placement is unchanged. (#14641) -
Make
controller.goMemLimitPercenttrack the live container cgroup memory limit, including in-place memory resizes. (#14648) -
Add experimental IPv6 and dual-stack support.
GatewayParameters.spec.kube.serviceacceptsipFamiliesandipFamilyPolicy, andBackendConfigPolicy.spec.dns.lookupFamilyoverrides the cluster-wide DNS lookup family for a single backend. These fields are experimental and may change in future releases. The proxy's readiness and stats listeners now follow the configured bind family rather than being pinned to IPv4.This listener change is not experimental and applies to every install: because KGW_LISTENER_BIND_IPV6 defaults to true, the readiness and stats listeners now bind [::] with IPv4 compatibility, so IPv4 clients are unaffected. On a node whose kernel has IPv6 disabled entirely (ipv6.disable=1), the proxy now fails to start instead of reporting Ready with no working listeners; set KGW_LISTENER_BIND_IPV6=false to keep an IPv4-only bootstrap, which the data-plane listeners already required on such nodes.
(#14651) -
Add
validationMode: AllowMissingOrFailedto the JWT GatewayExtension, which verifies JWTs but never rejects a request. Intended for evaluating a JWT policy against live traffic before enforcing it. JWT providers now also record verification failures in theenvoy.filters.http.jwt_authn:failed_statusdynamic metadata, available to access logs in all validation modes. (#14667) -
TrafficPolicy
rateLimit.localgains an optionalshareAcrossGatewayfield. When true, the token bucket applies to the Gateway as a whole and is divided evenly across its proxy replicas (Envoylocal_cluster_rate_limit), so the configured rate no longer scales with the replica count. (#14684) -
Added
clockSkewtoGatewayExtension's JWT providers, which sets Envoy'sclock_skew_secondstolerance for theexpandnbfclaims. Defaults to Envoy's 60s when unset. (#14686) -
Added an optional
cachefield toJWTProviderthat enables Envoy's JWT cache for verified tokens. (#14697) -
Add experimental xDS scoping (#14717, #14718, #14719, #14720, #14721, #14877, #14910, #14913). With KGW_XDS_SCOPING_MODE=REFERENCED (Helm controller.xds.scoping.mode; default ALL), each gateway's proxies receive only the clusters and endpoints that gateway's configuration references, along with the listeners and secrets those backends generate, instead of a cluster for every discovered backend.
- KGW_XDS_SCOPING_REFERENCE_AHEAD (controller.xds.scoping.referenceAhead, default 2s) delivers a newly referenced cluster before the route that targets it.
- KGW_XDS_SCOPING_DEREFERENCE_GRACE (controller.xds.scoping.dereferenceGrace, default 5s) keeps a de-referenced cluster briefly so the route update lands first. A deleted backend's cluster is removed at once.
- A gateway whose routes choose a destination at request time falls back to all clusters, unless the plugin responsible declares its destinations with ClusterEmissionClaim.
- The kgateway_xds_scoping metrics report how many clusters were kept out, transition windows, and gateways that fell back to all clusters.
- The v2.5.0 betas named these settings KGW_CLUSTER_DISCOVERY_MODE, KGW_CLUSTER_REFERENCE_AHEAD and KGW_CLUSTER_DEREFERENCE_GRACE. The controller refuses to start while an old name is set.
(#14717)
-
BackendTLSPolicy now supports the kgateway.dev/* TLS extension options (cipher-suites, ecdh-curves, signature-algorithms, min-tls-version, max-tls-version, verify-subject-alt-names, verify-certificate-hash) through its options field, matching what is already supported on Gateway listener TLS config. (#14731)
-
Support HTTP CONNECT proxy tunneling configuration (#14794)
-
Add
pathWithEscapedSlashesActionto ListenerPolicyhttpSettingsto configure how Envoy handles escaped slashes in request paths (KeepUnchanged,RejectRequest,UnescapeAndRedirect,UnescapeAndForward). (#14803) -
Route changes are now batched before Gateway translation, so a burst of route updates rebuilds each affected Gateway once per batch instead of once per route. This sharply reduces controller CPU and memory churn at route scale, and delays each route change by tens of milliseconds. Tune with
KGW_TRANSLATION_DEBOUNCE(default10ms) andKGW_TRANSLATION_DEBOUNCE_MAX(default100ms), or setKGW_TRANSLATION_DEBOUNCE=0to disable batching. (#14813) -
GatewayExtension ext-auth filters now set emit_filter_state_stats, exposing per-request ext-auth latency (latency_us) via FILTER_STATE access logging. (#14824)
-
Add
KGW_LEADER_ELECTION_LEASE_DURATION,KGW_LEADER_ELECTION_RENEW_DEADLINE, andKGW_LEADER_ELECTION_RETRY_PERIODsettings andcontroller.leaderElection.*Helm values to configure the controller leader election timings. (#14828) -
Added the
kgateway_build_infometric, which reports the controller's version, git revision, Go version, OS and architecture as labels on a gauge with value 1. (#14851) -
ListenerPolicy now supports
tcpSettings.accessLogfor per-connection access logging on TCP and TLS (Terminate and Passthrough) listeners. gRPC sinks use Envoy's TCP gRPC access logger. (#14859) -
Session Persistence can be configured on the BackendConfigPolicy (#14875)
-
BackendConfigPolicy outlier detection can now eject hosts after consecutive gateway failures (502, 503, 504) via consecutiveGatewayFailure. (#14880)
-
Support the Gateway API GatewayRouteHostnameIntersectionPrecedence feature: routes whose hostnames intersect with a listener hostname to the same hostname are ordered by the specificity of their own hostnames. (#14887)
Bug Fixes
- Fixed policy merging writing merged config back into the source policy's IR on delegated routes. Policies attached to a route delegated by more than one parent could leak config between delegation trees - including ext_authz/ext_proc providers and ACL rules a route never referenced - accumulate config across translation cycles, and produce different data-plane behavior before and after a control-plane restart with no change to the CRs. (#14227)
- Fix route validation after RouteConfiguration plugins and extend strict validation to include final virtual-host and shared route-configuration settings, isolating invalid configuration with scoped fallbacks. (#14324)
- Fixed TrafficPolicy (and other route/listener-attached policy) status incorrectly reporting the wrong Gateway or ListenerSet as ancestor when multiple Gateways/ListenerSets share the same port. (#14448)
- Fixed a control-plane/data-plane incompatibility during rolling upgrades where proxies still on an older version could have their entire endpoint (EDS) updates withheld, freezing them on stale/deleted backend IPs. (#14472)
- Honor configured request buffer limits when body transformations are enabled. (#14479)
- Reduced control-plane memory and GC pressure for endpoint translation at scale by omitting the per-endpoint load-balancing-weight wrapper (Envoy defaults an unset weight to 1) and eliminating dead metadata and re-marshaling allocations on endpoint recomputation. (#14490)
- fix: Unknown TLS option key and verify_subject_alt_name-without-CA errors now report the actual error in
Programmed/Acceptedlistener conditions instead of misleading "Invalid certificate ref(s)" (#14494) - Fixed an issue where a backend whose translation failed (for example, a BackendConfigPolicy
rejected by strict validation) caused endpoint updates for all other clusters on the same
gateway to stop flowing until the proxy reconnected. The invalid backend still fails closed;
unrelated clusters now continue to receive endpoint updates, and the backend's endpoints are
delivered again once the policy is fixed.
(#14500) - Custom labels set via the Helm chart's
commonLabelsvalue now propagate to the kgateway controller's pod template, in addition to the Deployment's own metadata. (#14507) - Fixed an issue where a TrafficPolicy using OAuth2 would stay permanently broken if the OpenID provider was unreachable the first time kgateway discovered its configuration, for example when both were restarting together. The discovery failure was latched until the control plane was restarted. kgateway now retries discovery in the background and re-translates affected policies once the provider becomes reachable. Retries start 30 seconds after a failure and back off exponentially, so recovery from a prolonged provider outage can take up to a few minutes. (#14508)
- Fixed a bug where backends with more than one label produced a different endpoint hash on every recomputation, causing kgateway to publish a new EDS version and push endpoint updates to every connected proxy even when the endpoints had not changed. (#14516)
- Use the KRT informer cache and keyed status contributions for consistent, resource-local status reconciliation with substantially lower control-plane work at scale. (#14519)
- Reject unknown KGW_VALIDATOR_MODE values instead of silently falling back to uncached validation. (#14543)
- xDS client identity (labels/locality/role) is now re-derived on every stream request instead of being frozen at connect time, so proxies that connect during control-plane startup no longer get stuck with an identity computed from stale pod data. (#14582)
- Fixed an apiKeyAuth TrafficPolicy selecting two Secrets that hold the same api-key value emitting a duplicate credential, which Envoy rejects, freezing xDS delivery for the entire listener while the policy still reported Accepted. Identical credentials are now collapsed, and two clients sharing one key value fail translation with the policy reporting Accepted=False. (#14592)
- Fixes spurious CDS updates and Envoy cluster re-warming for inline endpoint backends spanning multiple localities. (#14599)
- Reject ListenerSet attachment when a Gateway's allowedListeners selector cannot be parsed instead of crashing the control plane. (#14626)
- Fixed AWS Lambda Backends with
spec.aws.auth.type: AssumeRolesilently ignoring the configured role. The proxy now callssts:AssumeRoleusing its ambient credentials (IRSA / EKS Pod Identity / environment) and signs Lambda requests with the returned temporary credentials, instead of signing with the ambient credentials directly. (#14632) - The SDS sidecar now binds to 127.0.0.1:8234 by default instead of 0.0.0.0:8234, preventing other pods on the cluster network from reaching the endpoint. Override by setting SDS_SERVER_ADDRESS if the previous behavior is required. (#14638)
- OIDC provider configuration discovery now validates the issuer using the CA certificates of the BackendTLSPolicy attached to the OAuth2 backendRef, so an issuer served under a private or self-signed CA no longer fails discovery and no longer causes the referencing TrafficPolicy and HTTPRoute to be rejected. (#14650)
- Update go-control-plane to fix two xDS delivery bugs: a superseded response could be sent to a proxy after it had unsubscribed from those resources (with ordered ADS, the default), and an endpoint watch the control plane could not answer yet was discarded rather than retained, which could leave a proxy on stale endpoints until it reconnected. (#14654)
- BackendTLSPolicy status now reports an ancestor entry for each target (Service or kgateway Backend) when no route reaches that policy, so policies on unrouted targets — such as a Backend used only by a GatewayExtension — no longer have an empty status. Policies a route reaches are unchanged and continue to report only their Gateway ancestors. (#14659)
- Fixed GatewayParameters merging so that securityContext.windowsOptions.gmsaCredentialSpecName is preserved instead of being overwritten with the value of gmsaCredentialSpec. (#14660)
- Bump Envoy to v1.39.1. Fixes Lambda
Backends withauth.type: AssumeRolehanging every request when the gateway's base AWS identity is asynchronous (IRSA, EKS Pod Identity). (#14663) - Per-client xDS publication is bounded and holds up under proxy and controller churn (#14698, #14699, #14701, #14702, #14703, #14816, #14878).
- New gateway proxies receive configuration within KGW_PER_CLIENT_PUBLISH_BUDGET (default 15s) instead of waiting indefinitely for every referenced cluster. A route change onto a cluster that never becomes ready is published after the same budget.
- A proxy that reconnects after a controller restart is withheld for at most KGW_PER_CLIENT_WARM_WITHHOLD_BOUND (default 10m) while clusters it routes to are missing.
- Route updates to a Backend tunneled through an HTTP CONNECT proxy also wait for the proxy Backend's cluster and endpoints.
- Reconnecting proxies are answered at the endpoint, route and secret versions they already hold, and an update to a cluster a proxy already has no longer waits for Envoy's 15s endpoint fetch timeout. Unchanged endpoints no longer trigger endpoint updates.
- A response Envoy rejects is retried with backoff, at most once a minute, instead of being resent in a loop.
- The controller reclaims the snapshot cache entries of disconnected proxies, so its memory no longer grows with proxy churn, and a reconnecting proxy is never rolled back to its previous connection's configuration.
- New metrics report deferred, held, bounded and withheld publications, and xDS rejection metrics have bounded labels.
(#14698)
- fix: a backendRef naming an existing resource with a port it does not define now reports "found, but port N not defined" on ResolvedRefs, instead of claiming the resource was not found (#14706)
- Policies whose targetRefs name a Gateway, ListenerSet, HTTPRoute, GRPCRoute, Service, or Backend that does not exist now report
Accepted: Falsewith reasonTargetNotFoundon a syntheticStatusSummaryancestor entry, listing the unresolved targets. (#14709) - AWS Lambda backends now send the Lambda endpoint as the Host header, matching the AWS SDKs, instead of forwarding the client's authority. This takes precedence over route-level URLRewrite hostname and TrafficPolicy.autoHostRewrite settings. (#14712)
- Fix the gateway deployer dropping the
appArmorProfile,seLinuxChangePolicyandsupplementalGroupsPolicysecurity context fields when merging GatewayParameters overrides. (#14725) - Add opt-in
spec.kube.envoyContainer.bootstrap.maxDownstreamConnectionson GatewayParameters to configure Envoy's global downstream connection limit. No limit is set by default. (#14727) - A TCPRoute or TLSRoute whose backendRef names a Backend that only works on HTTP routes (dynamicForwardProxy, aws.lambda, gcp) now reports ResolvedRefs=False with reason InvalidKind and routes to the blackhole cluster, instead of programming a cluster that can never carry traffic while reporting success. Backend plugins can declare the route kinds a backend supports via BackendObjectIR.SupportedRouteKinds. (#14734)
- An AWS Backend whose referenced Secret has an empty
accessKeyorsecretKeyis now rejected at translation time and reported on the Backend'sAcceptedcondition, instead of producing an inline credential provider that Envoy rejects (which in the default validation mode discarded the whole CDS update). Error messages now reference the actual Secret data keys (accessKey,secretKey,sessionToken). (#14741) - Fixed delegated child HTTPRoutes getting no status when their HTTPRoute parentRef omits the namespace. (#14758)
- fix: The status of a TrafficPolicy now names the failing GatewayExtension, and OpenID discovery failures name the discovery URL with any password masked (#14769)
- Fixed endpoints without a locality receiving no traffic when other endpoints of the same backend have a locality. (#14775)
- Gateway listener TLS options and BackendTLSPolicy options now ignore keys outside the kgateway.dev/ prefix instead of rejecting them. Unknown kgateway.dev/* keys are still reported as errors. (#14782)
- fix: redirect path now accept query strings and other targets that Envoy itself permits, instead of being validated against the stricter rules meant for match paths only (#14791)
- Fixed strict validation rejecting local rate limits with
shareAcrossGateway: true. (#14793) - Fixed
PreferNetworkand other network-aware traffic distribution splitting traffic across networks when the gateway or backend pods have notopology.istio.io/networklabel. A pod or WorkloadEntry without a network now inherits thetopology.istio.io/networklabel of the Istio system namespace. (#14796) - AWS Backend Secrets whose accessKey, secretKey or sessionToken have leading or trailing whitespace are now rejected at translation and reported on the Backend's Accepted condition, instead of producing a malformed SigV4 Authorization header and a 403 from AWS. (#14804)
- Fixed frontend TLS client certificate validation rejecting
caCertificateRefsthat setgroup: core; these are now treated the same asgroup: "". (#14807) - Fixed redundant route and policy status writes when other controllers report status on the same resource and reorder
status.parentsorstatus.ancestors. (#14810) - Populate message on Gateway Programmed condition when no valid listeners exist. (#14841)
- Callbacks set with
WithExtraXDSCallbacksnow receive every xDS server hook, including stream open, responses, and delta hooks; before, only stream requests, stream close, and fetch requests reached them.krtcollections.NewUniquelyConnectedClientsno longer takes extra callbacks: chain them with the newsetup.ChainCallbacks. (#14856) - Fixed a controller panic when a TrafficPolicy with a buffer was compared with one without, such as after a policy weight change. (#14860)
- Fixed endpoint and route updates stopping for every gateway proxy that received a cluster or listener Envoy rejected. The updates stayed stopped after the resource was removed, and proxies started meanwhile served 503 with empty clusters. (#14865)
- Fixed BackendConfigPolicy
tls.filesclient certificates, which were always rejected, and strict validation rejecting TLS files that exist only on the proxy. (#14905)
Cleanup
- Route matchers using regular expressions no longer set the deprecated
google_re2engine type on the generated EnvoyRegexMatcher. RE2 remains the engine Envoy uses, so matching behavior is unchanged. (#14539) - Per-client ClusterLoadAssignments that resolve identically are now shared in memory across clients. Every EDS resource version string changes once when the upgraded control plane starts, so each connected Envoy receives one EDS push with identical content on upgrade. (#14604)
- Changes default to ordered ADS delivery (the old behavior is achievable with KGW_ENABLE_ORDERED_ADS=false), preserving CDS, EDS, LDS, and RDS response order for same-snapshot busy-stream additions. (#14644)
- Reduce per-client CDS memory and fleet-churn work by sharing immutable backend clusters. (#14692)
- Share inline endpoint assignments across clients when locality and endpoint policies cannot change them. (#14693)
- Avoid per-client inline endpoint rebuilding for backends whose hosts have no DestinationRule. (#14694)
- Reduce repeated strict-mode backend validation work by caching verdicts by cluster content. (#14695)
Dependency Updates
- Toolchain and dependencies bumped. (#14588)
- Upgrade OpenTelemetry Go dependencies to address CVE-2026-81870. (#14764)
- bump envoy to v1.39.4 (#14827)
Contributors
Thanks to all the contributors who made this release possible:
Installation
The kgateway project is available as a Helm chart and docker images.
Helm Charts
The Helm charts are available at:
- oci://cr.kgateway.dev/kgateway-dev/charts/kgateway
- oci://cr.kgateway.dev/kgateway-dev/charts/kgateway-crds
Docker Images
The docker images are available at:
- cr.kgateway.dev/kgateway-dev/kgateway:v2.5.0-rc.1
- cr.kgateway.dev/kgateway-dev/sds:v2.5.0-rc.1
- cr.kgateway.dev/kgateway-dev/envoy-wrapper:v2.5.0-rc.1
Quickstart
Try installing this release:
helm install kgateway-crds oci://cr.kgateway.dev/kgateway-dev/charts/kgateway-crds --version v2.5.0-rc.1 --namespace kgateway-system --create-namespace
helm install kgateway oci://cr.kgateway.dev/kgateway-dev/charts/kgateway --version v2.5.0-rc.1 --namespace kgateway-system --create-namespace
For detailed installation instructions and next steps, please visit our quickstart guide.



































