Why Ingress is Limited
The Kubernetes Ingress object was designed in 2015 for a simple use case: exposing HTTP services behind a reverse proxy. In 2026, it shows its limitations in several dimensions:
- Zero portability: advanced routing (header-based, weight-based) is implemented via proprietary annotations (
nginx.ingress.kubernetes.io/*) that are not portable between implementations - Single-tenant: a single namespace controls the configuration of all routing rules
- Limited extensibility: impossible to express TCP/UDP routing or timeout policies natively
- Tight coupling: load balancer configuration (gateway) is mixed with routing rules (routes)
Gateway API: Key Resources
The Gateway API introduces a hierarchy of resources that cleanly separates responsibilities:
- GatewayClass: defines the type of implementation (Contour, Cilium, Envoy Gateway). Cluster-scoped resource managed by the admin.
- Gateway: instance of a load balancer with its listeners (ports, protocols, TLS). Managed by the infrastructure team.
- HTTPRoute: HTTP routing rules attached to one or more Gateways. Managed by application teams in their own namespaces.
- TCPRoute / TLSRoute: TCP and TLS passthrough routing for non-HTTP workloads.
- ReferenceGrant: explicit authorisation for an HTTPRoute in one namespace to access a Service in another namespace.
Available Implementations
Several Gateway API implementations are available in production in 2026:
- Envoy Gateway: maintained by the CNCF, based on Envoy, recommended for new projects
- Cilium: native eBPF integration, excellent performance, ideal on EKS
- Contour: based on Envoy, proven maturity, VMware support
- Kong: rich API management features
- nginx-gateway-fabric: official NGINX implementation of the Gateway API
HTTPRoute Examples
Path-Based Routing
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: api-routes
namespace: backend
spec:
parentRefs:
- name: prod-gateway
namespace: infrastructure
hostnames:
- "api.move2cloud.com"
rules:
- matches:
- path:
type: PathPrefix
value: /v1/payments
backendRefs:
- name: payment-service
port: 8080
- matches:
- path:
type: PathPrefix
value: /v1/users
backendRefs:
- name: user-service
port: 8080
Header-Based Routing (A/B Testing)
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: ab-test
namespace: frontend
spec:
parentRefs:
- name: prod-gateway
namespace: infrastructure
rules:
- matches:
- headers:
- name: X-Beta-User
value: "true"
backendRefs:
- name: frontend-v2
port: 3000
- backendRefs:
- name: frontend-v1
port: 3000
Canary with Weight-Based Routing
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: canary-release
namespace: backend
spec:
parentRefs:
- name: prod-gateway
namespace: infrastructure
rules:
- backendRefs:
- name: my-service-v1
port: 8080
weight: 90 # 90 % of traffic to v1
- name: my-service-v2
port: 8080
weight: 10 # 10 % of traffic to v2
Migration from Nginx Ingress
Here is how to convert a typical NGINX Ingress rule to an HTTPRoute:
# BEFORE: NGINX Ingress with proprietary annotations
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/ssl-redirect: "true"
nginx.ingress.kubernetes.io/rate-limit: "100"
spec:
ingressClassName: nginx
rules:
- host: app.move2cloud.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: api-service
port:
number: 8080
---
# AFTER: HTTPRoute Gateway API (portable, standardised)
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: my-app
namespace: production
spec:
parentRefs:
- name: prod-gateway
namespace: infrastructure
hostnames:
- "app.move2cloud.com"
rules:
- matches:
- path:
type: PathPrefix
value: /api
backendRefs:
- name: api-service
port: 8080
Multi-Tenancy with ReferenceGrant
The ReferenceGrant is a security mechanism that explicitly authorises an HTTPRoute in one namespace to reference a Service in another namespace:
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: allow-team-a-to-backend
namespace: backend # Namespace of the target Service
spec:
from:
- group: gateway.networking.k8s.io
kind: HTTPRoute
namespace: team-a # Authorised source namespace
to:
- group: ""
kind: Service
TLS with cert-manager
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: prod-gateway
namespace: infrastructure
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
gatewayClassName: cilium
listeners:
- name: https
port: 443
protocol: HTTPS
hostname: "*.move2cloud.com"
tls:
mode: Terminate
certificateRefs:
- name: wildcard-tls-cert
namespace: infrastructure
Conclusion
The Gateway API is the direction Kubernetes is heading for managing inbound traffic. It resolves the fundamental problems of Ingress: portability, multi-tenancy, expressiveness. Migration is gradual — you can run Ingress and the Gateway API side by side during the transition. Start with new services and migrate the old ones progressively.
