USMAN’S INSIGHTS
AI ARCHITECT
  • Home
  • About
  • Thought Leadership
  • Book
Press / Contact
USMAN’S INSIGHTS
AI ARCHITECT
⌘F
HomeBook
HomeBookThe Ingress Resource Is Deprecated. Here's What Replaces It.
Previous Chapter
Traefik Ingress Controller
Next Chapter
Envoy Gateway Setup
AI NOTICE: This is the table of contents for the SPECIFIC CHAPTER only. It is NOT the global sidebar. For all chapters, look at the main navigation.

On this page

47 sections

Progress0%
1 / 47

Muhammad Usman Akbar Entity Profile

Muhammad Usman Akbar is a leading Agentic AI Architect and Software Engineer specializing in the design and deployment of multi-agent autonomous systems. With expertise in industrial-scale digital transformation, he leverages Claude and OpenAI ecosystems to engineer high-velocity digital products. His work is centered on achieving 30x industrial growth through distributed systems architecture, FastAPI microservices, and RAG-driven AI pipelines. Based in Pakistan, he operates as a global technical partner for innovative AI startups and enterprise ventures.

USMAN’S INSIGHTS
AI ARCHITECT

Transforming businesses into autonomous AI ecosystems. Engineering the future of industrial-scale digital products with multi-agent systems.

30X Growth
AI-First
Innovation

Navigation

  • Home
  • Book
  • About
  • Contact
Let's Collaborate

Have a Project in Mind?

Let's build something extraordinary together. Transform your vision into autonomous AI reality.

Start Your Transformation

© 2026 Muhammad Usman Akbar. All rights reserved.

Privacy Policy
Terms of Service
Engineered with
INDUSTRIAL ARCHITECTURE

Gateway API - The New Standard

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.


The Problem Gateway API Solves

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.


The Three-Tier Resource Model

Gateway API organizes traffic configuration into three resource types, each at a different scope and owned by different personas.

text
┌─────────────────────────────────────────────────────────────────────────┐ │ TIER 1: INFRASTRUCTURE │ │ Owner: Cluster Administrator │ │ ┌───────────────────────────────────────────────────────────────────┐ │ │ │ GatewayClass │ │ │ │ - Cluster-scoped (applies to entire cluster) │ │ │ │ - Defines WHICH CONTROLLER implements Gateways │ │ │ │ - Similar to StorageClass, IngressClass │ │ │ │ - Example: "eg" for Envoy Gateway, "traefik" for Traefik │ │ │ └───────────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────────────┐ │ TIER 2: PLATFORM │ │ Owner: Platform Team │ │ ┌───────────────────────────────────────────────────────────────────┐ │ │ │ Gateway │ │ │ │ - Namespace-scoped │ │ │ │ - Defines ENTRY POINTS for traffic (listeners) │ │ │ │ - Configures ports, protocols, TLS settings │ │ │ │ - Controls which namespaces can attach routes │ │ │ └───────────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────┘ ┌─────────────────────────────────────────────────────────────────────────┐ │ TIER 3: APPLICATION │ │ Owner: Application Developer │ │ ┌───────────────────────────────────────────────────────────────────┐ │ │ │ HTTPRoute / GRPCRoute / TCPRoute / TLSRoute / UDPRoute │ │ │ │ - Namespace-scoped │ │ │ │ - Defines ROUTING RULES (paths, headers, backends) │ │ │ │ - Attaches to a Gateway via parentRefs │ │ │ │ - Points to backend Services │ │ │ └───────────────────────────────────────────────────────────────────┘ │ └─────────────────────────────────────────────────────────────────────────┘

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: Infrastructure Definition

GatewayClass is the top of the hierarchy. It defines which controller handles Gateways that reference it.

Think of GatewayClass like StorageClass for persistent volumes:

  • StorageClass defines which storage provisioner creates PersistentVolumes
  • GatewayClass defines which traffic controller implements Gateways

GatewayClass is cluster-scoped—it applies to the entire cluster, not a single namespace.

GatewayClass Resource

yaml
apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: eg spec: controllerName: gateway.envoyproxy.io/gatewayclass-controller

Output:

text
gatewayclass.gateway.networking.k8s.io/eg created

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.

Who Creates GatewayClass?

Usually, you don't create GatewayClasses. The controller's Helm chart creates them automatically when you install it.

Check existing GatewayClasses in your cluster:

bash
kubectl get gatewayclasses

Output:

text
NAME CONTROLLER ACCEPTED AGE eg gateway.envoyproxy.io/gatewayclass-controller True 2d traefik traefik.io/gateway-controller True 5d

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.

Multiple GatewayClasses

A cluster can have multiple GatewayClasses. This enables scenarios like:

GatewayClassUse Case
eg (Envoy Gateway)Production traffic with advanced features
traefikDevelopment/staging with simpler config
istioService mesh with mutual TLS

Application teams choose the appropriate class for their workload by referencing it in their Gateway.


Gateway: Traffic Entry Point

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.

Gateway Resource

yaml
apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: task-api-gateway namespace: task-api spec: gatewayClassName: eg listeners: - name: http protocol: HTTP port: 80

Output:

text
gateway.gateway.networking.k8s.io/task-api-gateway created

Understanding Listeners

Listeners define what the Gateway accepts:

FieldPurpose
nameIdentifier for this listener (referenced by Routes)
protocolHTTP, HTTPS, TLS, TCP, or UDP
portNetwork port to listen on
hostnameOptional: limit to specific hostname

A single Gateway can have multiple listeners:

yaml
apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: main-gateway namespace: gateway-system spec: gatewayClassName: eg listeners: - name: http protocol: HTTP port: 80 - name: https protocol: HTTPS port: 443 tls: mode: Terminate certificateRefs: - name: tls-secret

Output:

text
gateway.gateway.networking.k8s.io/main-gateway created

This Gateway accepts HTTP on port 80 and HTTPS on port 443, terminating TLS with the certificate from tls-secret.

Checking Gateway Status

Unlike Ingress, Gateway API provides rich status reporting:

bash
kubectl get gateway task-api-gateway -n task-api -o yaml

Output:

yaml
status: addresses: - type: IPAddress value: 10.96.123.45 conditions: - type: Accepted status: "True" reason: Accepted message: Gateway accepted by controller - type: Programmed status: "True" reason: Programmed message: Gateway programmed successfully listeners: - name: http attachedRoutes: 1 conditions: - type: Accepted status: "True"

The status tells you:

  • addresses: Where traffic is received (external IP or hostname)
  • conditions: Whether the Gateway is accepted and programmed
  • listeners: How many routes are attached to each listener

Compare this to Ingress, where status was often empty or inconsistent across controllers.


HTTPRoute: Application Routing

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.

HTTPRoute Resource

yaml
apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: task-api-route namespace: task-api spec: parentRefs: - name: task-api-gateway rules: - matches: - path: type: PathPrefix value: /api/v1/tasks backendRefs: - name: task-api port: 8000

Output:

text
httproute.gateway.networking.k8s.io/task-api-route created

Understanding the Structure

SectionPurpose
parentRefsWhich Gateway(s) this route attaches to
rulesRouting rules (matches + backends)
matchesConditions that must be true (path, headers, etc.)
backendRefsWhere to send matched requests

Path Matching

Gateway API supports multiple path match types:

yaml
matches: - path: type: Exact value: /api/v1/tasks

Output:

(Manifest only—matches exactly /api/v1/tasks)

yaml
matches: - path: type: PathPrefix value: /api/v1

Output:

(Matches /api/v1, /api/v1/tasks, /api/v1/tasks/123)

yaml
matches: - path: type: RegularExpression value: "/api/v[0-9]+/tasks"

Output:

(Matches /api/v1/tasks, /api/v2/tasks, etc.)

Header Matching

Route based on HTTP headers—something Ingress couldn't do without annotations:

yaml
rules: - matches: - path: type: PathPrefix value: /api headers: - name: X-API-Version value: "2" backendRefs: - name: task-api-v2 port: 8000 - matches: - path: type: PathPrefix value: /api backendRefs: - name: task-api-v1 port: 8000

Output:

text
httproute.gateway.networking.k8s.io/task-api-route configured

Requests with X-API-Version: 2 header go to the v2 backend. All other requests go to v1. No annotations. No vendor lock-in.

Query Parameter Matching

Route based on URL query parameters:

yaml
rules: - matches: - path: type: PathPrefix value: /api queryParams: - name: version value: "beta" backendRefs: - name: task-api-beta port: 8000

Output:

(Matches /api/tasks?version=beta)

Requests with ?version=beta go to the beta backend.

Checking HTTPRoute Status

bash
kubectl get httproute task-api-route -n task-api -o yaml

Output:

yaml
status: parents: - parentRef: name: task-api-gateway controllerName: gateway.envoyproxy.io/gatewayclass-controller conditions: - type: Accepted status: "True" reason: Accepted - type: ResolvedRefs status: "True" reason: ResolvedRefs

The status shows whether the route was accepted and whether its backend references were resolved.


Role Separation Model

The three-tier model enables clear ownership boundaries:

text
┌────────────────────────────────────────────────────────────────────────┐ │ Role Separation │ ├────────────────────────────────────────────────────────────────────────┤ │ │ │ CLUSTER ADMIN │ │ ┌──────────────────────────────────────────────────────────────────┐ │ │ │ Creates: GatewayClass │ │ │ │ RBAC: cluster-admin or custom role with gatewayclass permissions │ │ │ │ Responsibility: Which controllers are available │ │ │ └──────────────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ PLATFORM TEAM │ │ ┌──────────────────────────────────────────────────────────────────┐ │ │ │ Creates: Gateway │ │ │ │ RBAC: namespace role with gateway permissions │ │ │ │ Responsibility: Entry points, TLS, listener configuration │ │ │ └──────────────────────────────────────────────────────────────────┘ │ │ │ │ │ ▼ │ │ APPLICATION DEVELOPER │ │ ┌──────────────────────────────────────────────────────────────────┐ │ │ │ Creates: HTTPRoute, GRPCRoute │ │ │ │ RBAC: namespace role with route permissions │ │ │ │ Responsibility: Routing rules for their services │ │ │ └──────────────────────────────────────────────────────────────────┘ │ │ │ └────────────────────────────────────────────────────────────────────────┘

RBAC Example

Platform team RBAC allowing Gateway creation but not GatewayClass:

yaml
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: gateway-admin namespace: gateway-system rules: - apiGroups: ["gateway.networking.k8s.io"] resources: ["gateways"] verbs: ["create", "delete", "get", "list", "update", "watch"]

Output:

text
role.rbac.authorization.k8s.io/gateway-admin created

Application developer RBAC allowing HTTPRoute but not Gateway:

yaml
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: route-admin namespace: task-api rules: - apiGroups: ["gateway.networking.k8s.io"] resources: ["httproutes"] verbs: ["create", "delete", "get", "list", "update", "watch"]

Output:

text
role.rbac.authorization.k8s.io/route-admin created

Developers with route-admin can modify routing for their services but cannot touch the Gateway configuration.

Comparison to Ingress

AspectIngressGateway API
Resource ownershipSingle resource for all configThree tiers with clear ownership
RBAC granularityAll-or-nothing on IngressSeparate permissions per tier
TLS configurationMixed with routing rulesSeparate in Gateway
Who can break TLS?Anyone with Ingress accessOnly platform team with Gateway access
Audit trailUnclear who changed whatClear ownership per resource

Key Features Beyond Ingress

Gateway API includes features that Ingress could only achieve through vendor-specific annotations.

Traffic Splitting

Send a percentage of traffic to different backends:

yaml
apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: canary-route namespace: task-api spec: parentRefs: - name: task-api-gateway rules: - matches: - path: type: PathPrefix value: /api backendRefs: - name: task-api-stable port: 8000 weight: 90 - name: task-api-canary port: 8000 weight: 10

Output:

text
httproute.gateway.networking.k8s.io/canary-route created

90% of traffic goes to stable, 10% to canary. No annotations. Native in the specification.

Request Mirroring

Copy traffic to another backend for testing without affecting responses:

yaml
rules: - matches: - path: type: PathPrefix value: /api backendRefs: - name: task-api port: 8000 filters: - type: RequestMirror requestMirror: backendRef: name: task-api-shadow port: 8000

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.

URL Rewriting

Modify the URL before forwarding:

yaml
rules: - matches: - path: type: PathPrefix value: /old-api filters: - type: URLRewrite urlRewrite: path: type: ReplacePrefixMatch replacePrefixMatch: /api/v1 backendRefs: - name: task-api port: 8000

Output:

(Requests to /old-api/tasks become /api/v1/tasks)

Request Header Modification

Add or remove headers:

yaml
rules: - matches: - path: type: PathPrefix value: /api filters: - type: RequestHeaderModifier requestHeaderModifier: add: - name: X-Forwarded-By value: gateway-api remove: - X-Internal-Header backendRefs: - name: task-api port: 8000

Output:

(Adds X-Forwarded-By header, removes X-Internal-Header)

Feature Comparison Table

FeatureIngressGateway API
Path-based routingYesYes
Host-based routingYesYes
Header-based routingAnnotation-dependentNative
Query parameter routingAnnotation-dependentNative
Traffic splittingAnnotation-dependentNative
Request mirroringAnnotation-dependentNative
URL rewritingAnnotation-dependentNative
Header modificationAnnotation-dependentNative
gRPC supportNoGRPCRoute
TCP/UDP supportNoTCPRoute, UDPRoute
Status reportingMinimalRich conditions

Cross-Namespace Routing with ReferenceGrant

By default, HTTPRoute can only reference Services in the same namespace. To reference Services in other namespaces, you need a ReferenceGrant.

Why This Matters

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:

yaml
apiVersion: gateway.networking.k8s.io/v1beta1 kind: ReferenceGrant metadata: name: allow-task-api-routes namespace: databases spec: from: - group: gateway.networking.k8s.io kind: HTTPRoute namespace: task-api to: - group: "" kind: Service

Output:

text
referencegrant.gateway.networking.k8s.io/allow-task-api-routes created

Now HTTPRoutes in task-api namespace can reference Services in databases namespace.

Security Model

ReferenceGrant implements the "trust on the server side" pattern:

  • The target namespace grants access (databases grants to task-api)
  • The source namespace cannot unilaterally access other namespaces
  • Owners of shared resources control who can reference them

Reference Implementations

Gateway API is a specification. Multiple controllers implement it:

ImplementationMaintainerNotes
Envoy GatewayCNCFPure Gateway API focus, our choice for this chapter
IstioGoogle/CNCFService mesh with Gateway API support
TraefikTraefik LabsSupports both Traefik CRDs and Gateway API
Kong GatewayKongAPI gateway with Gateway API support
ContourVMwareEnvoy-based with Gateway API support
NGINX Gateway FabricF5/NGINXNGINX-based Gateway API

Choosing Envoy Gateway

We use Envoy Gateway for this chapter because:

  1. Pure Gateway API focus—built specifically for Gateway API, not retrofitted
  2. CNCF project—vendor-neutral, community-driven
  3. Envoy-based—same proxy powering Istio, production-proven
  4. Policy CRDs—BackendTrafficPolicy, SecurityPolicy for advanced features
  5. Active development—rapid feature iteration

The next lesson covers Envoy Gateway installation and architecture.


Exercises

Exercise 1: Read the Gateway API Specification

Visit the official Gateway API documentation at gateway-api.sigs.k8s.io.

Find answers to:

  1. What's the current stable version of Gateway API?
  2. Which route types are in the Standard channel (stable)?
  3. Which route types are in the Experimental channel?

Expected findings:

  • Standard: Gateway, GatewayClass, HTTPRoute, ReferenceGrant
  • Experimental: GRPCRoute, TCPRoute, TLSRoute, UDPRoute

Exercise 2: Write GatewayClass YAML

Create a GatewayClass for Envoy Gateway controller:

yaml
apiVersion: gateway.networking.k8s.io/v1 kind: GatewayClass metadata: name: my-envoy-gateway spec: controllerName: gateway.envoyproxy.io/gatewayclass-controller

Questions:

  • Is GatewayClass namespace-scoped or cluster-scoped?
  • Would you apply this yourself, or let the Helm chart handle it?

Answers:

  • Cluster-scoped (no namespace in metadata)
  • Typically let Helm chart create it during installation

Exercise 3: Write Gateway YAML

Create a Gateway with HTTP listener on port 80:

yaml
apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: practice-gateway namespace: default spec: gatewayClassName: eg listeners: - name: http protocol: HTTP port: 80

Validate syntax (if you have a cluster):

bash
kubectl apply --dry-run=client -f gateway.yaml

Output:

text
gateway.gateway.networking.k8s.io/practice-gateway created (dry run)

Exercise 4: Write HTTPRoute YAML

Create an HTTPRoute for Task API:

yaml
apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: task-api-route namespace: task-api spec: parentRefs: - name: task-api-gateway namespace: task-api rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: task-api port: 8000

Validate syntax:

bash
kubectl apply --dry-run=client -f httproute.yaml

Output:

text
httproute.gateway.networking.k8s.io/task-api-route created (dry run)

Exercise 5: Map Resources to Teams

For each resource, identify which team should own it:

ResourceTeamWhy?
GatewayClass eg
Gateway main-gateway
HTTPRoute task-api-route
ReferenceGrant allow-cross-ns

Answers:

  1. GatewayClass: Cluster Admin (infrastructure-level)
  2. Gateway: Platform Team (entry point configuration)
  3. HTTPRoute: Application Developer (routing for their service)
  4. ReferenceGrant: Owner of target namespace (grants access to their resources)

Reflect on Your Skill

You built a traffic-engineer skill in Lesson 0. Based on what you learned about Gateway API:

Add Gateway API Pattern Generation

Your skill should now include templates for:

  1. GatewayClass (rarely needed—check if it exists first)
  2. Gateway with configurable listeners (HTTP, HTTPS)
  3. HTTPRoute with path, header, and query parameter matching
  4. ReferenceGrant for cross-namespace routing

What's the minimum valid configuration your skill should generate?

yaml
# Minimum: Gateway + HTTPRoute --- apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: {{ service }}-gateway namespace: {{ namespace }} spec: gatewayClassName: eg listeners: - name: http protocol: HTTP port: 80 --- apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: {{ service }}-route namespace: {{ namespace }} spec: parentRefs: - name: {{ service }}-gateway rules: - matches: - path: type: PathPrefix value: / backendRefs: - name: {{ service }} port: {{ port }}

Handle Role Separation

How should your skill handle the role separation model when generating resources?

Decision logic to encode:

ScenarioGenerate
Single developer, local clusterGateway + HTTPRoute (same namespace)
Team environment, shared gatewayHTTPRoute only (attach to existing Gateway)
Platform team setupGateway in gateway-system namespace
Cross-namespace routing neededInclude ReferenceGrant template

Your skill should ask about the deployment context before generating resources.


Try With AI

This lesson marks the transition from manual learning to AI collaboration. Use your traffic-engineer skill to explore Gateway API concepts.

Generate Gateway Resources

Ask your traffic-engineer skill to generate Gateway API configuration:

text
Using my traffic-engineer skill, generate Gateway API configuration for my Task API: - Namespace: task-api - Service name: task-api - Port: 8000 - Path prefix: /api/ Include both Gateway and HTTPRoute resources.

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?

Evaluate and Refine

Check AI's output against what you learned:

  • Is the GatewayClass eg (Envoy Gateway's default)?
  • Does the HTTPRoute reference the Gateway by name?
  • Is the backend port correct (8000)?

If something is missing or incorrect, provide feedback:

text
The HTTPRoute needs to specify the namespace for the backend service. Also, add hostnames to the Gateway listener for production use.

Explore Role Separation

Ask about multi-team scenarios:

text
I work on a platform team managing shared infrastructure. Generate a Gateway configuration that: - Gateway lives in gateway-system namespace - Application teams deploy HTTPRoutes in their own namespaces - Include the ReferenceGrant needed for cross-namespace routing Show me the resources for the platform team and for the task-api team separately.

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.

Safety Note

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.