Kubernetes Gateway API
Introduction
The classic Kubernetes Ingress API has served the community well, but it was never designed for everything we now need from HTTP routing: traffic splitting, header-based routing, gRPC, TLS passthrough, cross-namespace references, or multi-team access controls. Gateway API (gateway.networking.k8s.io) was designed from scratch to solve all of that, and as of v1.5.0 it is the standard way to expose services in Kubernetes.
I made the switch from Ingress to Gateway API about a year ago and I have not looked back. This article covers everything I use day-to-day: GatewayClass, Gateway, HTTPRoute, GRPCRoute, TLSRoute, ReferenceGrant, and policy attachments β all with the Go microservice from the previous article as the backend.
Why Replace Ingress?
Role separation (infra vs dev)
No
Yes
Traffic splitting (weight-based)
Annotation hack
Native
Header/method-based routing
Annotation hack
Native
gRPC support
No
GRPCRoute (standard)
TLS termination vs passthrough
Annotation hack
TLSRoute
Cross-namespace routing
No
ReferenceGrant
Multi-protocol (TCP/UDP)
No
TCPRoute/UDPRoute (experimental)
Portable YAML across controllers
No (annotations differ)
Yes
Ingress annotations are implementation-specific. Gateway API is portable across Nginx, Istio, Envoy Gateway, HAProxy, and Cilium.
Installing Gateway API CRDs (v1.5.0)
Gateway API CRDs are not included in Kubernetes core β install them separately.
Standard Channel (production-ready)
Standard channel includes: GatewayClass, Gateway, HTTPRoute, GRPCRoute, TLSRoute, ReferenceGrant, BackendTLSPolicy.
Expected output:
Experimental Channel (additional resources)
Experimental channel adds TCPRoute, UDPRoute, BackendTrafficPolicy.
Install a Gateway Controller
The CRDs define the API. You still need a controller. I use Envoy Gateway for standalone clusters:
For Istio environments, the Istio istiod controller handles Gateway API natively since Istio 1.18.
The Role Model
Gateway API is designed around three personas β this maps directly to real team structures:
Ian (Infrastructure Provider)
Platform SRE
GatewayClass β defines which controller handles traffic
Chihiro (Cluster Operator)
Cluster Admin
Gateway β defines listeners (port, protocol, TLS certs)
Ana (Developer)
Service Owner
HTTPRoute / GRPCRoute β attaches routes to a Gateway
This separation means developers can configure their own routing without cluster admin access β they just create HTTPRoutes in their namespace.
GatewayClass
GatewayClass is a cluster-scoped resource defining the controller type. One per controller implementation.
Gateway
Gateway describes a traffic entry point. Cluster operators create Gateways. Each Gateway has one or more Listeners.
Label the production namespace so routes can attach:
Create the TLS secret:
HTTPRoute
HTTPRoute is the core routing resource for L7 HTTP traffic. Developers create HTTPRoutes in their own namespace.
Basic Path Routing
Header and Method Matching
Traffic Splitting (Canary Deployment)
Gradually shift weight from 90/10 β 50/50 β 0/100 as you gain confidence.
HTTP Redirect
Request/Response Header Manipulation
GRPCRoute
GRPCRoute handles gRPC traffic (stable since Gateway API v1.1). Here I extend the Go microservice with a gRPC server.
main.go additions for gRPC:
GRPCRoute YAML:
TLSRoute
TLSRoute handles TLS passthrough β the Gateway does not terminate TLS, it forwards the TCP stream based on SNI (Server Name Indication).
Cross-Namespace References with ReferenceGrant
By default, a Route in namespace production cannot reference a Service in namespace shared-services. ReferenceGrant explicitly allows it.
BackendTLSPolicy
BackendTLSPolicy configures TLS from the Gateway to the backend service (not to be confused with TLSRoute which is client-facing).
Inspecting Gateway API Resources
The .status.parents[].conditions field tells you whether the route attached successfully β this is the first place to look when traffic is not flowing.
Complete Example: Deploying the Go Microservice
Putting it all together with namespace, Deployment, Service, HTTPRoute:
Migration from Ingress
If you have existing Ingress resources, migrate iteratively:
Install Gateway API CRDs and a controller
Create a GatewayClass and Gateway
Create equivalent HTTPRoutes alongside existing Ingress
Switch DNS to the new Gateway's IP
Remove the Ingress resources
There is no automated migration tool β the mapping is straightforward but manual.
Example Ingress β HTTPRoute mapping:
What I Learned
GatewayClass/Gateway belongs to the platform team; routes belong to app teams β this role separation is the most practical benefit of Gateway API
Traffic splitting replaces most blue/green tooling β weight: 90/10 on canary is cleaner than maintaining two Ingress resources
GRPCRoute is zero-config compared to Ingress annotations for gRPC
Always check
.status.parents[].conditions. When routes do not attach, the reason is always thereReferenceGrant is explicit security β cross-namespace access requires deliberate consent from the target namespace owner
Next
Kubernetes Cluster API β manage entire cluster lifecycles declaratively from a management cluster
Last updated