Gateway API v1.3.0: Advancements in Request Mirroring, CORS, Gateway Merging, and Retry Budgets
https://kubernetes.io/blog/2025/06/02/gateway-api-v1-3/
Join us in the Kubernetes SIG Network community in celebrating the general availability of Gateway API v1.3.0! We are also pleased to announce that there are already a number of conformant implementations to try, made possible by postponing this blog announcement. Version 1.3.0 of the API was released about a month ago on April 24, 2025.
Gateway API v1.3.0 brings a new feature to the Standard channel (Gateway API's GA release channel): percentage-based request mirroring, and introduces three new experimental features: cross-origin resource sharing (CORS) filters, a standardized mechanism for listener and gateway merging, and retry budgets.
Also see the full release notes and applaud the v1.3.0 release team next time you see them.
Graduation to Standard channel
Graduation to the Standard channel is a notable achievement for Gateway API features, as inclusion in the Standard release channel denotes a high level of confidence in the API surface and provides guarantees of backward compatibility. Of course, as with any other Kubernetes API, Standard channel features can continue to evolve with backward-compatible additions over time, and we (SIG Network) certainly expect further refinements and improvements in the future. For more information on how all of this works, refer to the Gateway API Versioning Policy.
Percentage-based request mirroring
Leads: Lior Lieberman,Jake Bennert
GEP-3171: Percentage-Based Request Mirroring
Percentage-based request mirroring is an enhancement to the existing support for HTTP request mirroring, which allows HTTP requests to be duplicated to another backend using the RequestMirror filter type. Request mirroring is particularly useful in blue-green deployment. It can be used to assess the impact of request scaling on application performance without impacting responses to clients.
The previous mirroring capability worked on all the requests to a backendRef.
Percentage-based request mirroring allows users to specify a subset of requests they want to be mirrored, either by percentage or fraction. This can be particularly useful when services are receiving a large volume of requests. Instead of mirroring all of those requests, this new feature can be used to mirror a smaller subset of them.
Here's an example with 42% of the requests to "foo-v1" being mirrored to "foo-v2":
apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: http-filter-mirror labels: gateway: mirror-gateway spec: parentRefs:
- name: mirror-gateway hostnames:
- mirror.example rules:
- backendRefs:
- name: foo-v1 port: 8080 filters:
- type: RequestMirror requestMirror: backendRef: name: foo-v2 port: 8080 percent: 42 # This value must be an integer.
You can also configure the partial mirroring using a fraction. Here is an example with 5 out of every 1000 requests to "foo-v1" being mirrored to "foo-v2".
rules:
- backendRefs:
- name: foo-v1 port: 8080 filters:
- type: RequestMirror requestMirror: backendRef: name: foo-v2 port: 8080 fraction: numerator: 5 denominator: 1000
Additions to Experimental channel
The Experimental channel is Gateway API's channel for experimenting with new features and gaining confidence with them before allowing them to graduate to standard. Please note: the experimental channel may include features that are changed or removed later.
Starting in release v1.3.0, in an effort to distinguish Experimental channel resources from Standard channel resources, any new experimental API kinds have the prefix "X". For the same reason, experimental resources are now added to the API group gateway.networking.x-k8s.io instead of gateway.networking.k8s.io. Bear in mind that using new experimental channel resources means they can coexist with standard channel resources, but migrating these resources to the standard channel will require recreating them with the standard channel names and API group (both of which lack the "x-k8s" designator or "X" prefix).
The v1.3 release introduces two new experimental API kinds: XBackendTrafficPolicy and XListenerSet. To be able to use experimental API kinds, you need to install the Experimental channel Gateway API YAMLs from the locations listed below.
CORS filtering
Leads: Liang Li, Eyal Pazz, Rob Scott
GEP-1767: CORS Filter
Cross-origin resource sharing (CORS) is an HTTP-header based mechanism that allows a web page to access restricted resources from a server on an origin (domain, scheme, or port) different from the domain that served the web page. This feature adds a new HTTPRoute filter type, called "CORS", to configure the handling of cross-origin requests before the response is sent back to the client.
To be able to use experimental CORS filtering, you need to install the Experimental channel Gateway API HTTPRoute yaml.
Here's an example of a simple cross-origin configuration:
apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: http-route-cors spec: parentRefs:
- name: http-gateway rules:
- matches:
- path: type: PathPrefix value: /resource/foo filters:
- cors:
- type: CORS allowOrigins:
- * allowMethods:
- GET
- HEAD
- POST allowHeaders:
- Accept
- Accept-Language
- Content-Language
- Content-Type
- Range backendRefs:
- kind: Service name: http-route-cors port: 80
In this case, the Gateway returns an origin header of "*", which means that the requested resource can be referenced from any origin, a methods header (Access-Control-Allow-Methods) that permits the GET, HEAD, and POST verbs, and a headers header allowing Accept, Accept-Language, Content-Language, Content-Type, and Range.
HTTP/1.1 200 OK Access-Control-Allow-Origin: * Access-Control-Allow-Methods: GET, HEAD, POST Access-Control-Allow-Headers: Accept,Accept-Language,Content-Language,Content-Type,Range
The complete list of fields in the new CORS filter:
allowOrigins
allowMethods
allowHeaders
allowCredentials
exposeHeaders
maxAge
See CORS protocol for details.
XListenerSets (standardized mechanism for Listener and Gateway merging)
Lead: Dave Protasowski
GEP-1713: ListenerSets - Standard Mechanism to Merge Multiple Gateways
This release adds a new experimental API kind, XListenerSet, that allows a shared list of listeners to be attached to one or more parent Gateway(s). In addition, it expands upon the existing suggestion that Gateway API implementations may merge configuration from multiple Gateway objects. It also:
adds a new field allowedListeners to the .spec of a Gateway. The allowedListeners field defines from which Namespaces to select XListenerSets that are allowed to attach to that Gateway: Same, All, None, or Selector based.
increases the previous maximum number (64) of listeners with the addition of XListenerSets.
allows the delegation of listener configuration, such as TLS, to applications in other namespaces.
To be able to use experimental XListenerSet, you need to install the Experimental channel Gateway API XListenerSet yaml.
The following example shows a Gateway with an HTTP listener and two child HTTPS XListenerSets with unique hostnames and certificates. The combined set of listeners attached to the Gateway includes the two additional HTTPS listeners in the XListenerSets that attach to the Gateway. This example illustrates the delegation of listener TLS config to application owners in different namespaces ("store" and "app"). The HTTPRoute has both the Gateway listener named "foo" and one XListenerSet listener named "second" as parentRefs.
apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: prod-external namespace: infra spec: gatewayClassName: example allowedListeners:
- from: All listeners:
- name: foo hostname: foo.com protocol: HTTP port: 80 --- apiVersion: gateway.networking.x-k8s.io/v1alpha1 kind: XListenerSet metadata: name: store namespace: store spec: parentRef: name: prod-external listeners:
- name: first hostname: first.foo.com protocol: HTTPS port: 443 tls: mode: Terminate certificateRefs:
- kind: Secret group: "" name: first-workload-cert --- apiVersion: gateway.networking.x-k8s.io/v1alpha1 kind: XListenerSet metadata: name: app namespace: app spec: parentRef: name: prod-external listeners:
- name: second hostname: second.foo.com protocol: HTTPS port: 443 tls: mode: Terminate certificateRefs:
- kind: Secret group: "" name: second-workload-cert --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: httproute-example spec: parentRefs:
- name: app kind: XListenerSet sectionName: second
- name: parent-gateway kind: Gateway sectionName: foo ...
Each listener in a Gateway must have a unique combination of port, protocol, (and hostname if supported by the protocol) in order for all listeners to be compatible and not conflicted over which traffic they should receive.
Furthermore, implementations can merge separate Gateways into a single set of listener addresses if all listeners across those Gateways are compatible. The management of merged listeners was under-specified in releases prior to v1.3.0.
With the new feature, the specification on merging is expanded. Implementations must treat the parent Gateways as having the merged list of all listeners from itself and from attached XListenerSets, and validation of this list of listeners must behave the same as if the list were part of a single Gateway. Within a single Gateway, listeners are ordered using the following precedence:
Single Listeners (not a part of an XListenerSet) first,
Remaining listeners ordered by:
object creation time (oldest first), and if two listeners are defined in objects that have the same timestamp, then
alphabetically based on "{namespace}/{name of listener}"
Retry budgets (XBackendTrafficPolicy)
Leads: Eric Bishop, Mike Morris
GEP