<img alt="Using Kubernetes Gateway API in Traefik" src="https://statedai.com/wp-content/uploads/2025/02/6fdbb7d0-d162-4a00-bbd2-7284d2967ba3.png"/>Gateway API
(formerly known as Service API) is an open-source project managed by the SIG-NETWORK community, with the project address: https://gateway-api.sigs.k8s.io/. The primary reason for its development is that the Ingress resource object does not adequately meet network requirements. In many scenarios, Ingress controllers need to extend functionality through annotations or CRDs, which is detrimental to standardization and support. The newly introduced Gateway API aims to enhance service networking through extensible role-oriented interfaces.
The Gateway API is a collection of API resources in Kubernetes, including GatewayClass, Gateway, HTTPRoute, TCPRoute, Service, etc. These resources collectively build models for various network use cases.

The improvements of the Gateway API over the current Ingress resource objects include many better designs:
-
Role-oriented – Gateways consist of various API resources modeled according to the roles of using and configuring the Kubernetes service network. -
Generality – Like Ingress, it is a general specification with many implementations. The Gateway API is designed to be a standard specification supported by many implementations. -
More expressive – Gateway API resources support core functionalities such as header-based matching and traffic weighting, which can only be achieved in Ingress through custom annotations. -
Extensibility – The Gateway API allows custom resources to be linked to various layers of the API, enabling finer customization at appropriate points in the API structure.
There are also some other noteworthy features:
-
GatewayClasses – GatewayClasses
formalize the types of load balancer implementations, making it easy for users to understand what capabilities can be obtained through Kubernetes resources. -
Shared gateways and cross-namespace support – They allow sharing of load balancers and VIPs, enabling independent routing resources to bind to the same gateway, allowing teams to securely share infrastructure (including cross-namespace) without the need for direct coordination. -
Normalized routing and backends – The Gateway API supports typed routing resources and different types of backends, allowing the API to flexibly support various protocols (such as HTTP and gRPC) and various backend services (such as Kubernetes Services, buckets, or functions).
Role-Oriented Design
Infrastructure, whether roads, power, data centers, or Kubernetes clusters, is built for sharing. However, shared infrastructure presents a common challenge of how to provide flexibility to infrastructure users while still being controlled by owners.
The Gateway API achieves this goal through a role-oriented design of the Kubernetes service network, balancing flexibility and centralized control. It allows shared network infrastructure (hardware load balancers, cloud networks, cluster-managed proxies, etc.) to be used by many different teams, all subject to various policies and constraints set by cluster operations. The following example shows how this works in practice.

A cluster operator creates a Gateway resource based on GatewayClass, which deploys or configures the underlying network resources it represents. Cluster operations and specific teams must communicate what can be attached to this Gateway to expose their applications. Centralized policies, such as TLS, can be enforced by cluster operations on the Gateway, while Store and Site applications run in their own namespaces but attach their routes to the same shared gateway, allowing them to independently control their routing logic.
This separation of concerns design enables different teams to manage their own traffic while leaving centralized policies and control to cluster operations.
Concepts
There are three roles involved in the Gateway API: infrastructure providers, cluster administrators, and application developers, and in some scenarios, application administrators may also be involved. The Gateway API defines three main resource models: GatewayClass
, Gateway
, and Route
.
GatewayClass
GatewayClass
defines a set of gateways that share the same configuration and actions. Each GatewayClass
is handled by a controller and is a cluster-scoped resource, requiring at least one GatewayClass
to be defined.
This is similar to Ingress’s IngressClass; in Ingress v1beta1, the ingress-class
annotation is similar to GatewayClass, while in Ingress v1, the closest equivalent is the IngressClass
resource object.
Gateway
The Gateway describes how to transform traffic into services within the cluster, meaning it defines a request to convert traffic from places that do not understand Kubernetes into services within the cluster. For example, traffic sent to Kubernetes services by cloud load balancers, cluster proxies, or external hardware load balancers.
It defines a request for specific load balancer configurations that implement the specifications and behaviors of GatewayClass, which can be directly created by administrators or created by controllers handling GatewayClass
.
Gateways can be attached to one or more route references, which serve to direct a subset of traffic to specific services.
Route Resources
Route resources define specific rules for mapping requests from the gateway to Kubernetes services.
Starting from v1alpha2
, the API contains four types of Route resources, and for other undefined protocols, custom route types of specific implementations are encouraged. New route types may also be added in the future.
HTTPRoute
HTTPRoute
is suitable for HTTP or HTTPS connections, applicable in scenarios where we want to inspect HTTP requests and route or modify them using HTTP requests, such as routing based on HTTP headers or modifying them during the request process.
TLSRoute
TLSRoute is used for TLS connections, distinguished by SNI, suitable for places that want to use SNI as the primary routing method and are not interested in the properties of higher-level protocols like HTTP, where the byte stream of the connection is proxied to the backend without any inspection.
TCPRoute and UDPRoute
TCPRoute (and UDPRoute) are designed to map one or more ports to a single backend. In this case, there are no discriminators to select different backends for the same port, so each TCPRoute requires a different port on the listener. You can use TLS, in which case the unencrypted byte stream will be passed to the backend, or you can opt not to use TLS, in which case the encrypted byte stream will be passed to the backend.
Combination
The combination of GatewayClass
, Gateway
, xRoute
, and Service
defines an implementable load balancer. The diagram below illustrates the relationships between different resources:

The typical client/gateway API request flow using a reverse proxy implemented gateway is as follows:
-
1. The client makes a request to http://foo.example.com
. -
2. DNS resolves the domain name to the Gateway
gateway address. -
3. The reverse proxy receives the request on the listener and uses the Host Header to match the HTTPRoute. -
4. (Optional) The reverse proxy can route based on the matching rules of the HTTPRoute. -
5. (Optional) The reverse proxy can modify the request according to the filtering rules of the HTTPRoute, i.e., adding or removing headers. -
6. Finally, the reverse proxy forwards the request to one or more objects within the cluster, i.e., services, based on the forwardTo
rules of the HTTPRoute.
Implementation
Currently, there are many implementations of Gateway API controllers, such as Contour, Google Kubernetes Engine, Istio, Traefik, etc. Next, we will take Traefik as an example for testing. However, it should be noted that Traefik is currently implemented based on the v1alpha1
specification, which may differ slightly from the concepts mentioned above.
To use the Gateway API in Traefik, we first need to manually install the CRDs for the Gateway API. Use the following command to install them, which will include GatewayClass, Gateway, HTTPRoute, TCPRoute, etc.:
➜ kubectl kustomize "github.com/kubernetes-sigs/gateway-api/config/crd?ref=v0.3.0" \
| kubectl apply -f -
Then, we need to enable the kubernetesgateway
provider in Traefik, also based on the Helm Chart package defined in the previous Traefik chapter, setting experimental.kubernetesGateway.enabled=true
. The complete Values file is as follows:
# ci/deployment-prod.yaml
# Enable experimental features
experimental:
kubernetesGateway: # Enable gateway API support
enabled: true
providers:
kubernetesCRD:
enabled: true
allowCrossNamespace: true # Allow cross-namespace
allowExternalNameServices: true # Allow using ExternalName services
kubernetesIngress:
enabled: true
allowExternalNameServices: true
# ......
# Other ignored
Then use the following command to update Traefik:
➜ helm upgrade --install traefik ./traefik -f ./traefik/ci/deployment-prod.yaml --namespace kube-system
After the update is complete, you can go to Traefik’s Dashboard to check if the KubernetesGateway
provider has been enabled:

Under normal circumstances, after successful enabling, Traefik will also create a default GatewayClass
resource object and a Gateway
instance:
➜ kubectl get gatewayclass
NAME CONTROLLER AGE
traefik traefik.io/gateway-controller 4m13s
➜ kubectl get gatewayclass traefik -o yaml
apiVersion: networking.x-k8s.io/v1alpha1
kind: GatewayClass
metadata:
name: traefik
spec:
controller: traefik.io/gateway-controller
......
➜ kubectl get gateway -n kube-system
NAME CLASS AGE
traefik-gateway traefik 5m55s
➜ kubectl get gateway -n kube-system traefik-gateway -o yaml
apiVersion: networking.x-k8s.io/v1alpha1
kind: Gateway
metadata:
name: traefik-gateway
namespace: kube-system
spec:
gatewayClassName: traefik
listeners:
- port: 8000
protocol: HTTP
routes:
group: networking.x-k8s.io
kind: HTTPRoute
namespaces:
from: Same
selector:
matchLabels:
app: traefik
......
It can be seen that the default created Gateway
instance references the traefik
GatewayClass
, where the listeners
section defines the listener entry associated with this gateway. At least one listener must be specified, and the HTTPRoute
below defines the routing rules. The namespaces
field indicates in which namespaces the routes should be selected for this gateway. By default, this is limited to the namespace of the gateway, and the Selector
specifies a set of route labels. If this selector is defined, only routes matching the selector associated with the gateway will be routed. An empty selector matches all objects, and here it will match objects with the app: traefik
label.
To be able to handle routing rules from other namespaces, we can change the
namespaces.from
here toAll
, but testing has shown that it did not take effect?
Next, we will install a simple whoami
service for testing. Simply use the following resource manifest to deploy the corresponding service:
# 01-whoami.yaml
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: whoami
namespace: kube-system
spec:
replicas: 2
selector:
matchLabels:
app: whoami
template:
metadata:
labels:
app: whoami
spec:
containers:
- name: whoami
image: containous/whoami
ports:
- containerPort: 80
name: http
---
apiVersion: v1
kind: Service
metadata:
name: whoami
namespace: kube-system
spec:
ports:
- protocol: TCP
port: 80
targetPort: http
selector:
app: whoami
Once the test service deployment is complete, we can use the Gateway API to configure traffic.
Deploying a Simple Host
In previous methods, we would create an Ingress or IngressRoute resource object; here we will deploy a simple HTTPRoute
object.
# 02-whoami-httproute.yaml
apiVersion: networking.x-k8s.io/v1alpha1
kind: HTTPRoute
metadata:
name: http-app-1
namespace: kube-system
labels:
app: traefik
spec:
hostnames:
- "whoami"
rules:
- matches:
- path:
type: Exact
value: /
forwardTo:
- serviceName: whoami
port: 80
weight: 1
The above HTTPRoute resource will capture requests directed to the whoami hostname and forward them to the deployed whoami service. If you now make a request to this hostname, you will see the typical whoami output:
➜ kubectl apply -f 02-whoami-httproute.yaml
➜ kubectl get httproute -n kube-system
NAME HOSTNAMES AGE
http-app-1 ["whoami"] 25s
# Testing access using the whoami hostname
➜ curl -H "Host: whoami" http://192.168.31.108
Hostname: whoami-6b465b89d6-lcg4k
IP: 127.0.0.1
IP: ::1
IP: 10.244.1.87
IP: fe80::cccc:6aff:fef8:eca9
RemoteAddr: 10.244.1.85:60384
GET / HTTP/1.1
Host: whoami
User-Agent: curl/7.64.1
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 192.168.31.9
X-Forwarded-Host: whoami
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: traefik-84d4cccf9c-2pl5r
X-Real-Ip: 192.168.31.9
Additionally, note that the app: traefik
label must be defined in the above HTTPRoute object; otherwise, the created Gateway
instance cannot be associated.
Host with Path
The previous example can easily restrict traffic to route only on a given subpath.
# 03-whoami-httproute-paths.yaml
---
apiVersion: networking.x-k8s.io/v1alpha1
kind: HTTPRoute
metadata:
name: http-app-1
namespace: kube-system
labels:
app: traefik
spec:
hostnames:
- whoami
rules:
- forwardTo:
- port: 80
serviceName: whoami
weight: 1
matches:
- path:
type: Exact # Match path /foo
value: /foo
After creating the modified HTTPRoute above, you will find that previous requests now return a 404 error, while requests to the /foo path return success.
➜ curl -H "Host: whoami" http://192.168.31.108
404 page not found
➜ curl -H "Host: whoami" http://192.168.31.108/foo
Hostname: whoami-6b465b89d6-p5vwz
IP: 127.0.0.1
IP: ::1
IP: 10.244.2.154
IP: fe80::7045:53ff:fef9:fadc
RemoteAddr: 10.244.1.85:51686
GET /foo HTTP/1.1
Host: whoami
User-Agent: curl/7.64.1
Accept: */*
Accept-Encoding: gzip
X-Forwarded-For: 192.168.31.9
X-Forwarded-Host: whoami
X-Forwarded-Port: 80
X-Forwarded-Proto: http
X-Forwarded-Server: traefik-84d4cccf9c-2pl5r
X-Real-Ip: 192.168.31.9
More information about which parts of the request can be matched can be found in the official Gateway APIs documentation (https://gateway-api.sigs.k8s.io/v1alpha1/api-types/httproute/#rules).
Canary Release
Another feature supported by the Gateway APIs specification is the canary release. Suppose you want to run two different services (or two versions of the same service) on one endpoint and route a portion of requests to each endpoint; this can be achieved by modifying your HTTPRoute.
First, we need to run a second service, and here we will quickly generate an Nginx instance for testing.
# 03-nginx.yaml
kind: Deployment
apiVersion: apps/v1
metadata:
name: nginx
namespace: kube-system
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
name: http
---
apiVersion: v1
kind: Service
metadata:
name: nginx
namespace: kube-system
spec:
ports:
- protocol: TCP
port: 80
targetPort: http
selector:
app: nginx
Next, we modify the previous HTTPRoute resource object, where there is a weight option that can allocate different weights to the two services, as shown below:
# 04-whoami-nginx-canary.yaml
---
apiVersion: networking.x-k8s.io/v1alpha1
kind: HTTPRoute
metadata:
labels:
app: traefik
name: http-app-1
namespace: kube-system
spec:
hostnames:
- whoami
rules:
- forwardTo:
- port: 80
serviceName: whoami
weight: 3 # 3/4 of requests to whoami
- port: 80
serviceName: nginx
weight: 1 # 1/4 of requests to nginx
After creating the above HTTPRoute, we can access the whoami service again. Normally, we can see that about 25%
of requests will see the response from Nginx instead of whoami.
At this point, we have tested the use of Kubernetes Gateway APIs with Traefik. Currently, Traefik’s implementation of Gateway APIs is based on the v1alpha1
version of the specification, while the latest specification is v1alpha2
, so there may be some discrepancies with the latest specification.