Replacing Ingress with Gateway API (Kubernetes)
A practical migration from Ingress to Gateway API: CRDs, GatewayClass, Gateway, HTTPRoute and a checklist.
The Kubernetes Gateway API replaces the older Ingress model with a more expressive, role-oriented API. In practice it improves routing semantics, clarifies ownership, and enables controlled cross-namespace relationships.
This guide keeps the migration incremental: run in parallel with existing Ingress first, then convert host/path rules in small batches.
Gateway API CRD relationships
In short:
GatewayClassdefines which controller implements Gateways.Gatewayis your entry point: listeners, (TLS) termination and policy.HTTPRoutereplaces Ingress host/path rules and attaches to aGatewayviaparentRefs.ReferenceGrantis required for cross-namespace references.
1) Install Gateway API CRDs
This is non-destructive: existing Ingress traffic continues to work.
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.1.0/standard-install.yaml
kubectl get crd | grep gateway.networking.k8s.io
Expected CRDs:
gatewayclasses.gateway.networking.k8s.io
gateways.gateway.networking.k8s.io
httproutes.gateway.networking.k8s.io
referencegrants.gateway.networking.k8s.io
2) Define a GatewayClass
GatewayClass is conceptually the successor of IngressClass. Keep it explicit.
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
name: nginx-gateway
spec:
controllerName: k8s.nginx.org/nginx-gateway-controller
If you use a different controller (Envoy, HAProxy, cloud LB controller), only controllerName changes.
3) Create a Gateway (listeners, TLS later)
Start with HTTP. Add TLS once routes are attached and verified.
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: edge-gateway
namespace: edge
spec:
gatewayClassName: nginx-gateway
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: All
4) Convert an Ingress to an HTTPRoute
The host/path logic remains familiar, but the attachment to the Gateway is via parentRefs.
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: app-route
namespace: app
spec:
parentRefs:
- name: edge-gateway
namespace: edge
hostnames:
- app.example.com
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: app-service
port: 80
5) Validate status and traffic
Confirm the Gateway is ready and the route is attached. Only then switch DNS or edge/LB config.
kubectl get gateway -n edge
kubectl get httproute -n app
Example output:
NAME CLASS ADDRESS PROGRAMMED AGE
edge-gateway nginx-gateway 203.0.113.10 True 2m
NAME HOSTNAMES AGE
app-route app.example.com 2m
Migration checklist
- Install Gateway API CRDs and your controller in parallel with Ingress.
- Create a
GatewayClassand aGatewayper environment. - Convert Ingress rules into
HTTPRoutein small batches (per host/path). - Shift DNS/traffic incrementally (canary if possible).
- Remove legacy Ingress only after traffic is stable and observability stays green.