The Kubernetes Gateway API reached GA in October 2023, and a year later it's clear that it's the future of traffic management in Kubernetes. If you're still using Ingress resources, here's why you should start planning a migration — and what the path looks like.
What Was Wrong with Ingress
The Ingress resource was designed for a simpler era. Its core problems:
Vendor-specific annotations: Every feature beyond path-based routing required controller-specific annotations. An Nginx-specific rate limiting annotation doesn't work on Traefik, and vice versa. Your Ingress manifests became tightly coupled to your controller choice.
No role separation: A single Ingress resource conflates infrastructure concerns (TLS cert, load balancer class) with application concerns (path routing, headers). There's no way to let application teams edit routing rules without also granting access to infrastructure configuration.
Limited traffic manipulation: Ingress has no native concept of request mirroring, traffic splitting, or header-based routing. All of these required non-portable annotations.
Gateway API's Three-Resource Model
Gateway API splits the concerns across three resources, mapped to three roles:
GatewayClass (infra admin) → defines the controller implementation
↓
Gateway (platform team) → defines listener config, TLS, load balancer
↓
HTTPRoute (app team) → defines routing rules for one service
# Platform team: defines the gateway
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: prod-gateway
namespace: infra
spec:
gatewayClassName: cilium
listeners:
- name: https
port: 443
protocol: HTTPS
tls:
certificateRefs:
- name: wildcard-tls
namespace: infra
allowedRoutes:
namespaces:
from: All
---
# App team: defines routing (no access to the Gateway object needed)
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: payments-route
namespace: payments
spec:
parentRefs:
- name: prod-gateway
namespace: infra
hostnames:
- payments.example.com
rules:
- matches:
- path:
type: PathPrefix
value: /api
backendRefs:
- name: payments-api
port: 8080
The application team never touches the Gateway or the TLS cert — they only write HTTPRoute. The platform team controls the gateway configuration without needing to understand each application's routing.
Traffic Splitting (Canary Deployments)
This is where Gateway API shines compared to Ingress:
rules:
- backendRefs:
- name: payments-api-stable
port: 8080
weight: 90
- name: payments-api-canary
port: 8080
weight: 10
Native weight-based traffic splitting without annotations, without service mesh, without any controller-specific features. This works with any Gateway API-compatible implementation.
Migration from Nginx Ingress
The migration is mechanical for simple Ingress resources:
| Ingress | HTTPRoute equivalent |
|---|---|
host: + path: |
hostnames: + matches[].path |
tls: block |
Moved to Gateway listener |
nginx.ingress.kubernetes.io/rewrite-target |
filters[].urlRewrite.path |
nginx.ingress.kubernetes.io/rate-limit |
Controller-specific — check your Gateway implementation |
Cilium, Envoy Gateway, and Traefik all have mature Gateway API implementations. Run both Ingress and HTTPRoute objects in parallel during migration — they coexist cleanly on any properly configured controller.