The previous lesson showed Traefik's simpler approach—IngressRoute CRDs that replace Ingress annotations with structured YAML. You could route traffic in minutes.
But Traefik's CRDs are Traefik-only. Switch to Envoy Gateway, and you rewrite everything. Switch to Istio, rewrite again. The Kubernetes community recognized this problem in 2020 and began designing a solution: Gateway API.
Gateway API is not another proprietary alternative. It's the official Kubernetes standard for traffic routing, designed to replace Ingress entirely. In October 2023, Gateway API reached General Availability (GA). Major implementations—Envoy Gateway, Istio, Traefik, Kong—all support it. Your Gateway API configurations work across any of them.
This lesson teaches the specification first. You'll understand the conceptual model before writing YAML. When you see the resources, you'll know why they exist.
Ingress created two problems that couldn't be fixed with patches:
Problem 1: Annotation chaos. Every feature beyond basic routing required vendor-specific annotations. Rate limiting in NGINX Ingress used different syntax than Traefik Ingress, which differed from Kong Ingress. Switching vendors meant rewriting every configuration.
Problem 2: No role separation. In production, different teams own different responsibilities. The platform team manages infrastructure. The security team manages TLS policies. Application developers define routes. Ingress forced everyone to edit the same resource. A developer adding a route could accidentally modify TLS configuration.
Gateway API solves both problems with a new architecture: three tiers of resources, each owned by different personas.
Gateway API organizes traffic configuration into three resource types, each at a different scope and owned by different personas.
This separation enables RBAC at the resource level. Cluster administrators create GatewayClasses. Platform teams create Gateways. Application developers create Routes. Each team has permissions for their tier only.
GatewayClass is the top of the hierarchy. It defines which controller handles Gateways that reference it.
Think of GatewayClass like StorageClass for persistent volumes:
GatewayClass is cluster-scoped—it applies to the entire cluster, not a single namespace.
Output:
The key field is controllerName. This string tells Kubernetes which controller should reconcile Gateways using this class. Envoy Gateway uses gateway.envoyproxy.io/gatewayclass-controller. Traefik uses traefik.io/gateway-controller. Istio uses istio.io/gateway-controller.
Usually, you don't create GatewayClasses. The controller's Helm chart creates them automatically when you install it.
Check existing GatewayClasses in your cluster:
Output:
If you installed Envoy Gateway, the eg class exists. If you installed Traefik with Gateway API support, the traefik class exists. You choose which class to use when creating Gateways.
A cluster can have multiple GatewayClasses. This enables scenarios like:
Application teams choose the appropriate class for their workload by referencing it in their Gateway.
Gateway defines where traffic enters the cluster. It's the specification for an actual load balancer or proxy.
Gateway is namespace-scoped—it lives in a specific namespace and can be managed by the team owning that namespace.
Output:
Listeners define what the Gateway accepts:
A single Gateway can have multiple listeners:
Output:
This Gateway accepts HTTP on port 80 and HTTPS on port 443, terminating TLS with the certificate from tls-secret.
Unlike Ingress, Gateway API provides rich status reporting:
Output:
The status tells you:
Compare this to Ingress, where status was often empty or inconsistent across controllers.
HTTPRoute defines how HTTP requests are routed to backend Services. This is the resource application developers create.
HTTPRoute is namespace-scoped—developers create routes in their application's namespace.
Output:
Gateway API supports multiple path match types:
Output:
(Manifest only—matches exactly /api/v1/tasks)
Output:
(Matches /api/v1, /api/v1/tasks, /api/v1/tasks/123)
Output:
(Matches /api/v1/tasks, /api/v2/tasks, etc.)
Route based on HTTP headers—something Ingress couldn't do without annotations:
Output:
Requests with X-API-Version: 2 header go to the v2 backend. All other requests go to v1. No annotations. No vendor lock-in.
Route based on URL query parameters:
Output:
(Matches /api/tasks?version=beta)
Requests with ?version=beta go to the beta backend.
Output:
The status shows whether the route was accepted and whether its backend references were resolved.
The three-tier model enables clear ownership boundaries:
Platform team RBAC allowing Gateway creation but not GatewayClass:
Output:
Application developer RBAC allowing HTTPRoute but not Gateway:
Output:
Developers with route-admin can modify routing for their services but cannot touch the Gateway configuration.
Gateway API includes features that Ingress could only achieve through vendor-specific annotations.
Send a percentage of traffic to different backends:
Output:
90% of traffic goes to stable, 10% to canary. No annotations. Native in the specification.
Copy traffic to another backend for testing without affecting responses:
Output:
(Manifest only—mirrors all requests to shadow environment)
Production traffic goes to task-api. Copies go to task-api-shadow for testing. Shadow responses are discarded.
Modify the URL before forwarding:
Output:
(Requests to /old-api/tasks become /api/v1/tasks)
Add or remove headers:
Output:
(Adds X-Forwarded-By header, removes X-Internal-Header)
By default, HTTPRoute can only reference Services in the same namespace. To reference Services in other namespaces, you need a ReferenceGrant.
Imagine a shared database service in the databases namespace. Application teams in task-api namespace want to route to it. Without ReferenceGrant, this fails—the route cannot cross namespace boundaries.
ReferenceGrant allows the databases namespace to grant access:
Output:
Now HTTPRoutes in task-api namespace can reference Services in databases namespace.
ReferenceGrant implements the "trust on the server side" pattern:
Gateway API is a specification. Multiple controllers implement it:
We use Envoy Gateway for this chapter because:
The next lesson covers Envoy Gateway installation and architecture.
Visit the official Gateway API documentation at gateway-api.sigs.k8s.io.
Find answers to:
Expected findings:
Create a GatewayClass for Envoy Gateway controller:
Questions:
Answers:
Create a Gateway with HTTP listener on port 80:
Validate syntax (if you have a cluster):
Output:
Create an HTTPRoute for Task API:
Validate syntax:
Output:
For each resource, identify which team should own it:
Answers:
You built a traffic-engineer skill in Lesson 0. Based on what you learned about Gateway API:
Your skill should now include templates for:
What's the minimum valid configuration your skill should generate?
How should your skill handle the role separation model when generating resources?
Decision logic to encode:
Your skill should ask about the deployment context before generating resources.
This lesson marks the transition from manual learning to AI collaboration. Use your traffic-engineer skill to explore Gateway API concepts.
Ask your traffic-engineer skill to generate Gateway API configuration:
What you're learning: AI generates complete Gateway API configurations. Review the output—does it include the correct GatewayClass reference? Is the HTTPRoute properly attached to the Gateway via parentRefs?
Check AI's output against what you learned:
If something is missing or incorrect, provide feedback:
Ask about multi-team scenarios:
What you're learning: AI adapts configurations to different organizational models. Verify the ReferenceGrant correctly allows the task-api namespace to reference the Gateway in gateway-system.
When generating Gateway API resources, verify the GatewayClass exists in your cluster before applying. Different Gateway controllers (Envoy Gateway, Istio, Traefik) use different GatewayClass names. Always run kubectl get gatewayclass first to see what's available.