How to Use Kubernetes Gateway API
Implement the Gateway API for advanced traffic routing in Kubernetes. Learn HTTPRoute, TLSRoute, and traffic splitting with the next-generation Ingress replacement.
The Problem
Kubernetes Ingress has limitations: vendor-specific annotations, no support for TCP/UDP routing, and limited traffic splitting capabilities. You need a more expressive, portable, and role-oriented API for traffic management.
The Solution
Use the Gateway API, the next-generation Kubernetes networking standard that provides expressive, extensible, and role-oriented routing for HTTP, HTTPS, TCP, and gRPC traffic.
Gateway API vs Ingress
flowchart TB
subgraph model["π― ROLE-BASED RESOURCE MODEL"]
GatewayClass["ποΈ GatewayClass<br/>(nginx, envoy)"]
Gateway["πͺ Gateway<br/>(listeners, addresses)"]
Routes["π HTTPRoute<br/>π TCPRoute<br/>π TLSRoute<br/>π GRPCRoute"]
GatewayClass --> Gateway --> Routes
GatewayClass -.- admin["π€ Infrastructure Provider<br/>(cluster-admin)"]
Gateway -.- platform["π₯ Cluster Operator<br/>(platform team)"]
Routes -.- dev["π» Application Developer<br/>(dev team)"]
endStep 1: Install Gateway API CRDs
# Install the standard channel CRDs
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.0.0/standard-install.yaml
# For experimental features (TCPRoute, TLSRoute, etc.)
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.0.0/experimental-install.yaml
# Verify installation
kubectl get crds | grep gatewayStep 2: Install a Gateway Controller
Option A: NGINX Gateway Fabric
# Install NGINX Gateway Fabric
kubectl apply -f https://github.com/nginxinc/nginx-gateway-fabric/releases/download/v1.1.0/crds.yaml
kubectl apply -f https://github.com/nginxinc/nginx-gateway-fabric/releases/download/v1.1.0/nginx-gateway.yaml
# Verify deployment
kubectl get pods -n nginx-gatewayOption B: Envoy Gateway
# Install Envoy Gateway
helm install eg oci://docker.io/envoyproxy/gateway-helm \
--version v0.6.0 \
-n envoy-gateway-system --create-namespace
# Verify
kubectl get pods -n envoy-gateway-systemOption C: Istio Gateway
# If Istio is installed, enable Gateway API support
istioctl install --set values.pilot.env.PILOT_ENABLE_GATEWAY_API=trueStep 3: Create GatewayClass and Gateway
GatewayClass (Infrastructure Provider)
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: nginx
spec:
controllerName: gateway.nginx.org/nginx-gateway-controllerGateway (Platform Team)
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: main-gateway
namespace: default
spec:
gatewayClassName: nginx
listeners:
# HTTP listener
- name: http
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: All
# HTTPS listener
- name: https
protocol: HTTPS
port: 443
tls:
mode: Terminate
certificateRefs:
- name: wildcard-tls
kind: Secret
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
gateway-access: "true"
# Specific hostname listener
- name: api
protocol: HTTPS
port: 443
hostname: "api.example.com"
tls:
mode: Terminate
certificateRefs:
- name: api-tls
allowedRoutes:
namespaces:
from: SameStep 4: Configure HTTPRoute
Basic HTTPRoute
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: web-app-route
namespace: production
spec:
parentRefs:
- name: main-gateway
namespace: default
hostnames:
- "app.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: web-app
port: 80Path-Based Routing
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: microservices-route
namespace: production
spec:
parentRefs:
- name: main-gateway
hostnames:
- "api.example.com"
rules:
# Route /users to users service
- matches:
- path:
type: PathPrefix
value: /users
backendRefs:
- name: users-service
port: 8080
# Route /orders to orders service
- matches:
- path:
type: PathPrefix
value: /orders
backendRefs:
- name: orders-service
port: 8080
# Route /products to products service
- matches:
- path:
type: PathPrefix
value: /products
backendRefs:
- name: products-service
port: 8080
# Default backend
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: frontend
port: 80Header-Based Routing
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: header-routing
namespace: production
spec:
parentRefs:
- name: main-gateway
hostnames:
- "api.example.com"
rules:
# Route mobile traffic to mobile backend
- matches:
- headers:
- name: X-Client-Type
value: mobile
backendRefs:
- name: mobile-backend
port: 8080
# Route based on API version header
- matches:
- headers:
- name: X-API-Version
value: v2
backendRefs:
- name: api-v2
port: 8080
# Default to v1
- backendRefs:
- name: api-v1
port: 8080Query Parameter Routing
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: query-routing
spec:
parentRefs:
- name: main-gateway
hostnames:
- "api.example.com"
rules:
# Route debug requests
- matches:
- queryParams:
- name: debug
value: "true"
backendRefs:
- name: debug-service
port: 8080
# Default route
- backendRefs:
- name: production-service
port: 8080Traffic Splitting (Canary/Blue-Green)
Weighted Traffic Split
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: canary-deployment
namespace: production
spec:
parentRefs:
- name: main-gateway
hostnames:
- "app.example.com"
rules:
- backendRefs:
# 90% to stable
- name: app-stable
port: 8080
weight: 90
# 10% to canary
- name: app-canary
port: 8080
weight: 10Header-Based Canary
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: header-canary
spec:
parentRefs:
- name: main-gateway
hostnames:
- "app.example.com"
rules:
# Canary for specific users
- matches:
- headers:
- name: X-Canary
value: "true"
backendRefs:
- name: app-canary
port: 8080
# Production for everyone else
- backendRefs:
- name: app-stable
port: 8080Request/Response Modification
URL Rewriting
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: url-rewrite
spec:
parentRefs:
- name: main-gateway
hostnames:
- "api.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /api/v1
filters:
- type: URLRewrite
urlRewrite:
path:
type: ReplacePrefixMatch
replacePrefixMatch: /v1
backendRefs:
- name: backend
port: 8080Header Modification
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: header-modification
spec:
parentRefs:
- name: main-gateway
rules:
- matches:
- path:
type: PathPrefix
value: /
filters:
# Add request headers
- type: RequestHeaderModifier
requestHeaderModifier:
add:
- name: X-Request-ID
value: "generated-id"
- name: X-Forwarded-Proto
value: https
set:
- name: Host
value: backend.internal
remove:
- X-Debug-Header
# Add response headers
- type: ResponseHeaderModifier
responseHeaderModifier:
add:
- name: X-Response-Time
value: "100ms"
set:
- name: Cache-Control
value: "max-age=3600"
backendRefs:
- name: backend
port: 8080Redirects
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: redirects
spec:
parentRefs:
- name: main-gateway
hostnames:
- "old.example.com"
rules:
# Redirect to new domain
- filters:
- type: RequestRedirect
requestRedirect:
hostname: new.example.com
statusCode: 301
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: https-redirect
spec:
parentRefs:
- name: main-gateway
sectionName: http # Reference HTTP listener
rules:
# Redirect HTTP to HTTPS
- filters:
- type: RequestRedirect
requestRedirect:
scheme: https
statusCode: 301TLS Configuration
TLS Termination
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: tls-gateway
spec:
gatewayClassName: nginx
listeners:
- name: https
protocol: HTTPS
port: 443
hostname: "secure.example.com"
tls:
mode: Terminate
certificateRefs:
- name: secure-tls-cert
kind: Secret
allowedRoutes:
namespaces:
from: SameTLS Passthrough
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: passthrough-gateway
spec:
gatewayClassName: nginx
listeners:
- name: tls-passthrough
protocol: TLS
port: 443
hostname: "backend.example.com"
tls:
mode: Passthrough
allowedRoutes:
kinds:
- kind: TLSRoute
---
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TLSRoute
metadata:
name: backend-tls-route
spec:
parentRefs:
- name: passthrough-gateway
hostnames:
- "backend.example.com"
rules:
- backendRefs:
- name: backend-service
port: 443GRPCRoute
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: GRPCRoute
metadata:
name: grpc-route
spec:
parentRefs:
- name: main-gateway
hostnames:
- "grpc.example.com"
rules:
# Route by service name
- matches:
- method:
service: myapp.UserService
backendRefs:
- name: user-grpc-service
port: 50051
# Route by method
- matches:
- method:
service: myapp.OrderService
method: CreateOrder
backendRefs:
- name: order-grpc-service
port: 50051TCPRoute
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
name: database-route
spec:
parentRefs:
- name: tcp-gateway
sectionName: postgres
rules:
- backendRefs:
- name: postgres-service
port: 5432
---
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: tcp-gateway
spec:
gatewayClassName: nginx
listeners:
- name: postgres
protocol: TCP
port: 5432
allowedRoutes:
kinds:
- kind: TCPRouteCross-Namespace Routing
Allow Routes from Specific Namespaces
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: shared-gateway
namespace: gateway-system
spec:
gatewayClassName: nginx
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
shared-gateway-access: "true"Reference Gateway from Another Namespace
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: app-route
namespace: team-a # Must have label: shared-gateway-access: "true"
spec:
parentRefs:
- name: shared-gateway
namespace: gateway-system
hostnames:
- "team-a.example.com"
rules:
- backendRefs:
- name: team-a-app
port: 8080ReferenceGrant (Cross-Namespace Backend)
# Allow HTTPRoute in 'frontend' namespace to reference
# Service in 'backend' namespace
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: allow-frontend-to-backend
namespace: backend
spec:
from:
- group: gateway.networking.k8s.io
kind: HTTPRoute
namespace: frontend
to:
- group: ""
kind: ServiceVerification Commands
# Check Gateway status
kubectl get gateway main-gateway -o yaml
# Check HTTPRoute status
kubectl get httproute web-app-route -o yaml
# View attached routes
kubectl describe gateway main-gateway
# Check GatewayClass
kubectl get gatewayclass
# Debug routing
kubectl get httproutes -A -o wide
# Test routing
curl -H "Host: app.example.com" http://<gateway-ip>/Migration from Ingress
Before (Ingress)
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: web-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: app.example.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080After (Gateway API)
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: web-route
spec:
parentRefs:
- name: main-gateway
hostnames:
- "app.example.com"
rules:
- matches:
- path:
type: PathPrefix
value: /api
filters:
- type: URLRewrite
urlRewrite:
path:
type: ReplacePrefixMatch
replacePrefixMatch: /
backendRefs:
- name: api-service
port: 8080Summary
The Gateway API provides a more expressive, role-oriented approach to Kubernetes traffic management. It separates concerns between infrastructure providers, platform teams, and developers while offering powerful routing capabilities beyond traditional Ingress.
π Go Further with Kubernetes Recipes
Love this recipe? Thereβs so much more! This is just one of 100+ hands-on recipes in our comprehensive Kubernetes Recipes book.
Inside the book, youβll master:
- β Production-ready deployment strategies
- β Advanced networking and security patterns
- β Observability, monitoring, and troubleshooting
- β Real-world best practices from industry experts
βThe practical, recipe-based approach made complex Kubernetes concepts finally click for me.β
π Get Your Copy Now β Start building production-grade Kubernetes skills today!
π Get All 100+ Recipes in One Book
Stop searching β get every production-ready pattern with detailed explanations, best practices, and copy-paste YAML.
Want More Kubernetes Recipes?
This recipe is from Kubernetes Recipes, our 750-page practical guide with hundreds of production-ready patterns.