🎉 Welcome to the v2.5.0-beta.1 release of the kgateway project!
Release Notes
Changes since v2.4.0-rc.1
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)
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 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
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)
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)
- 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)
- 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) - 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)
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) - 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)
Dependency Updates
- Toolchain and dependencies bumped. (#14588)
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-beta.1
- cr.kgateway.dev/kgateway-dev/sds:v2.5.0-beta.1
- cr.kgateway.dev/kgateway-dev/envoy-wrapper:v2.5.0-beta.1
Quickstart
Try installing this release:
helm install kgateway-crds oci://cr.kgateway.dev/kgateway-dev/charts/kgateway-crds --version v2.5.0-beta.1 --namespace kgateway-system --create-namespace
helm install kgateway oci://cr.kgateway.dev/kgateway-dev/charts/kgateway --version v2.5.0-beta.1 --namespace kgateway-system --create-namespace
For detailed installation instructions and next steps, please visit our quickstart guide.






















