Kubernetes Gateway API 101
The Kubernetes Gateway API is the next-generation traffic management API for Kubernetes, designed to be a more expressive, extensible, and role-oriented successor to the Ingress API. It is a standard part of the Kubernetes ecosystem (maintained by the SIG-Network community) and is now the recommended way to expose HTTP, HTTPS, and TCP services in Kubernetes.
What You Will Learn
- What the Gateway API is and how it differs from Ingress
- Core resources:
GatewayClass,Gateway, andHTTPRoute - How to install a Gateway API-compatible controller
- How to expose a service using the Gateway API
- Advanced routing: path-based, header-based, and traffic splitting
Why Gateway API Over Ingress?
| Feature | Ingress | Gateway API |
|---|---|---|
| Role separation | Single resource | GatewayClass (infra), Gateway (operator), HTTPRoute (developer) |
| Multiple protocols | HTTP/HTTPS only | HTTP, HTTPS, TCP, TLS, UDP |
| Traffic splitting | Vendor annotation | Native weight-based routing |
| Header/path matching | Limited | Rich, expressive matching |
| Cross-namespace routing | Not supported | Supported via ReferenceGrant |
| Extensibility | Vendor annotations | Typed extension points |
Core Resources
1. GatewayClass
A GatewayClass defines the type of load balancer infrastructure to provision. It is cluster-scoped and managed by infrastructure providers (similar to StorageClass).
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: nginx
spec:
controllerName: gateway.nginx.org/nginx-gateway-controller
2. Gateway
A Gateway represents an instance of a load balancer. It is managed by cluster operators and specifies listeners (ports and protocols).
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: my-gateway
namespace: default
spec:
gatewayClassName: nginx
listeners:
- name: http
port: 80
protocol: HTTP
3. HTTPRoute
An HTTPRoute defines how HTTP traffic reaching the Gateway is routed to backend services. Developers manage this resource to define application-level routing rules.
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: my-app-route
namespace: default
spec:
parentRefs:
- name: my-gateway
hostnames:
- "myapp.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: my-service
port: 8080
Lab 1: Installing the Gateway API CRDs
The Gateway API CRDs must be installed before any controller. Run the following to install the latest stable CRDs:
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.1.0/standard-install.yaml
Verify the CRDs are installed:
kubectl get crd gateways.gateway.networking.k8s.io \
gatewayclasses.gateway.networking.k8s.io \
httproutes.gateway.networking.k8s.io
Expected output:
NAME CREATED AT
gateways.gateway.networking.k8s.io 2024-01-01T00:00:00Z
gatewayclasses.gateway.networking.k8s.io 2024-01-01T00:00:00Z
httproutes.gateway.networking.k8s.io 2024-01-01T00:00:00Z
Lab 2: Installing NGINX Gateway Fabric (Controller)
We will use NGINX Gateway Fabric as our Gateway API controller. It is a CNCF-certified implementation.
# Install NGINX Gateway Fabric
kubectl apply -f https://raw.githubusercontent.com/nginxinc/nginx-gateway-fabric/v1.3.0/deploy/crds.yaml
kubectl apply -f https://raw.githubusercontent.com/nginxinc/nginx-gateway-fabric/v1.3.0/deploy/default/deploy.yaml
Verify the controller is running:
kubectl get pods -n nginx-gateway
Expected output:
NAME READY STATUS RESTARTS AGE
nginx-gateway-5d4f7b9c8d-xklt2 2/2 Running 0 30s
Lab 3: Deploy a Sample Application
Apply the sample Deployment and Service:
kubectl apply -f https://raw.githubusercontent.com/collabnix/kubelabs/master/Gateway101/demo-app.yaml
Or create them manually:
kubectl create deployment demo --image=httpd:alpine --port=80
kubectl expose deployment demo --port=80
Lab 4: Create the GatewayClass and Gateway
Apply the GatewayClass and Gateway manifests:
kubectl apply -f https://raw.githubusercontent.com/collabnix/kubelabs/master/Gateway101/gateway.yaml
Check the Gateway status:
kubectl get gateway my-gateway
Expected output:
NAME CLASS ADDRESS PROGRAMMED AGE
my-gateway nginx 192.168.1.10 True 60s
The PROGRAMMED: True status means the Gateway is ready to route traffic.
Lab 5: Create an HTTPRoute
Apply the HTTPRoute manifest:
kubectl apply -f https://raw.githubusercontent.com/collabnix/kubelabs/master/Gateway101/http-route.yaml
Check the HTTPRoute status:
kubectl get httproute demo-route
Test the route using the Gateway address:
GATEWAY_IP=$(kubectl get gateway my-gateway -o jsonpath='{.status.addresses[0].value}')
curl http://$GATEWAY_IP/ -H "Host: demo.example.com"
Expected output:
<html><body><h1>It works!</h1></body></html>
Lab 6: Advanced Routing — Path-Based Routing
The Gateway API supports rich routing rules. This example routes /api to one service and /web to another:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: path-based-route
namespace: default
spec:
parentRefs:
- name: my-gateway
hostnames:
- "myapp.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /api
backendRefs:
- name: api-service
port: 8080
- matches:
- path:
type: PathPrefix
value: /web
backendRefs:
- name: web-service
port: 80
Lab 7: Traffic Splitting (Canary / Blue-Green)
The Gateway API natively supports weight-based traffic splitting, making canary deployments easy without any vendor annotations:
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: canary-route
namespace: default
spec:
parentRefs:
- name: my-gateway
hostnames:
- "myapp.example.com"
rules:
- backendRefs:
- name: my-app-stable
port: 80
weight: 90
- name: my-app-canary
port: 80
weight: 10
This sends 90% of traffic to the stable version and 10% to the canary.
Lab 8: Header-Based Routing
Route requests to a specific backend based on request headers (useful for A/B testing):
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: header-route
namespace: default
spec:
parentRefs:
- name: my-gateway
hostnames:
- "myapp.example.com"
rules:
- matches:
- headers:
- name: X-User-Group
value: beta-testers
backendRefs:
- name: my-app-beta
port: 80
- backendRefs:
- name: my-app-stable
port: 80
Cleaning Up
Remove all Gateway API resources created in this tutorial:
kubectl delete httproute demo-route path-based-route canary-route header-route --ignore-not-found
kubectl delete gateway my-gateway --ignore-not-found
kubectl delete gatewayclass nginx --ignore-not-found
kubectl delete deployment demo --ignore-not-found
kubectl delete service demo --ignore-not-found
