MinhVo

Minh Vo

rss feed

Slaying code & making it lit fr fr πŸ”₯ tagline

Hey there πŸ‘‹ I'm an AI Engineer with 7 years of experience building scalable web and mobile applications. Currently at Neurond AI (May 2025 β€” present), architecting an Enterprise AI Assistant Platform with multi-tenant RAG on pgvector, multi-provider LLM orchestration, and Azure-native infrastructure. Previously spent 5+ years at SNAPTEC (Sep 2019 β€” Apr 2025), leading SaaS themes, admin dashboards, and e-commerce platforms β€” earned the Hero of the Year award in 2021. I specialize in TypeScript, React, Next.js, and AI-Native engineering with Claude Code and Cursor.bio

Back to blogs

Kubernetes Gateway API: The Future of Ingress

Migrate to Gateway API: HTTPRoute, GatewayClass, and traffic splitting.

KubernetesGateway APIIngressDevOps

By MinhVo

Introduction

The Kubernetes Ingress resource has served the community well since its introduction in Kubernetes 1.2, but its limitations have become increasingly apparent as applications grow more complex. Ingress is intentionally simpleβ€”it supports basic HTTP routing with host and path matching, TLS termination, and little else. Features like header-based routing, traffic splitting, request mirroring, and cross-namespace routing require vendor-specific annotations that vary between implementations and are difficult to standardize.

The Gateway API is the official successor to Ingress, designed from the ground up to address these limitations. It introduces a richer, more expressive routing model with role-based design that separates infrastructure concerns (GatewayClass) from cluster operations (Gateway) and application routing (HTTPRoute). This separation of concerns enables platform teams to define shared infrastructure while application teams independently manage their routing rules.

Gateway API reached GA (General Availability) with v1.0 in October 2023 and is now supported by all major ingress controller implementations including NGINX, Envoy, Istio, Traefik, HAProxy, and Kong. If you are starting a new project or planning to modernize your ingress layer, Gateway API is the path forward. This guide covers everything you need to know to migrate from Ingress to Gateway API.

Kubernetes networking

Understanding Gateway API: Core Concepts

The Role-Based Model

Gateway API introduces three distinct resource types that map to different roles in an organization:

GatewayClass β€” Defined by infrastructure providers. A GatewayClass describes a type of gateway implementation (similar to a StorageClass for storage). Cluster administrators choose which GatewayClass to use based on the underlying implementation (NGINX, Envoy, etc.).

Gateway β€” Defined by cluster operators. A Gateway resource requests a load balancer or proxy from a GatewayClass. It defines listeners (ports, protocols, TLS configuration) and controls which namespaces can attach routes.

HTTPRoute / GRPCRoute / TCPRoute / TLSRoute / UDPRoute β€” Defined by application developers. Route resources define the actual routing rulesβ€”how traffic matching specific criteria is forwarded to backend Services.

This separation means that a platform team can provision a Gateway once, and multiple application teams can independently attach their routing rules without coordinating with each other or needing cluster-level permissions.

Key Differences from Ingress

FeatureIngressGateway API
Resource modelSingle resourceGatewayClass + Gateway + Route
Role separationNone (all-in-one)Infrastructure, operations, application
Cross-namespace routingNot supportedNative support via parentRefs
Traffic splittingAnnotations onlyFirst-class weighted routing
Header matchingLimited annotationsNative header/query param matching
Request mirroringAnnotations onlyNative filter support
Protocol supportHTTP/HTTPS onlyHTTP, gRPC, TCP, TLS, UDP
Status reportingMinimalRich status conditions

The Resource Hierarchy

GatewayClass (infrastructure provider)
  └── Gateway (cluster operator)
        β”œβ”€β”€ HTTPRoute (app team A)
        β”œβ”€β”€ HTTPRoute (app team B)
        └── GRPCRoute (app team C)

A GatewayClass is cluster-scoped. A Gateway is namespace-scoped but can reference routes from other namespaces (if allowed). HTTPRoutes are namespace-scoped and can attach to Gateways in the same or different namespaces.

Network architecture

Architecture and Design Patterns

GatewayClass: The Foundation

A GatewayClass defines the implementation that backs the Gateway. Most ingress controller vendors provide a GatewayClass resource as part of their installation:

# Provided by your ingress controller vendor
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: envoy-gateway
spec:
  controllerName: gateway.envoyproxy.io/gatewayclass-controller

Gateway: The Infrastructure Layer

A Gateway resource requests a load balancer and defines the entry points for traffic:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: main-gateway
  namespace: infra
spec:
  gatewayClassName: envoy-gateway
  listeners:
  - name: http
    protocol: HTTP
    port: 80
    allowedRoutes:
      namespaces:
        from: All  # Allow routes from any namespace
  - name: https
    protocol: HTTPS
    port: 443
    tls:
      mode: Terminate
      certificateRefs:
      - kind: Secret
        name: wildcard-tls
        namespace: infra
    allowedRoutes:
      namespaces:
        from: Selector
        selector:
          matchLabels:
            gateway-access: "true"

The allowedRoutes field controls which namespaces can attach routes to this Gateway. This is a critical security feature that prevents unauthorized teams from hijacking traffic.

HTTPRoute: The Application Layer

HTTPRoutes define how traffic matching specific criteria is routed to backend Services:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: app-route
  namespace: app-team-a
spec:
  parentRefs:
  - name: main-gateway
    namespace: infra
  hostnames:
  - "app.example.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /api
    backendRefs:
    - name: api-service
      port: 8080
      weight: 90
    - name: api-service-canary
      port: 8080
      weight: 10
  - matches:
    - path:
        type: PathPrefix
        value: /static
    filters:
    - type: RequestHeaderModifier
      requestHeaderModifier:
        add:
        - name: X-Cache-Enabled
          value: "true"
    backendRefs:
    - name: static-files
      port: 80

Step-by-Step Implementation

Installing a Gateway API-Compatible Controller

Most major ingress controllers now support Gateway API. Here is how to install Envoy Gateway:

# Install Envoy Gateway
helm install eg oci://docker.io/envoyproxy/gateway-helm \
  --version v1.1.0 \
  -n envoy-gateway-system \
  --create-namespace
 
# Verify installation
kubectl get pods -n envoy-gateway-system

Or NGINX Gateway Fabric:

helm install ngf oci://ghcr.io/nginx/charts/nginx-gateway-fabric \
  --create-namespace -n nginx-gateway

Creating Your First Gateway

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: my-gateway
  namespace: default
spec:
  gatewayClassName: eg  # Envoy Gateway class name
  listeners:
  - name: http
    protocol: HTTP
    port: 80
    allowedRoutes:
      namespaces:
        from: Same
kubectl apply -f gateway.yaml
 
# Check Gateway status
kubectl get gateway my-gateway
kubectl describe gateway my-gateway

Migrating from Ingress to HTTPRoute

Before (Ingress):

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-app
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "10"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - app.example.com
    secretName: app-tls
  rules:
  - host: app.example.com
    http:
      paths:
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8080
      - path: /web
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80

After (Gateway API):

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: my-app-route
spec:
  parentRefs:
  - name: my-gateway
  hostnames:
  - "app.example.com"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /api
    backendRefs:
    - name: api-service
      port: 8080
      weight: 90
    - name: api-service-canary
      port: 8080
      weight: 10
  - matches:
    - path:
        type: PathPrefix
        value: /web
    backendRefs:
    - name: web-service
      port: 80

Notice how traffic splitting (canary deployment) is expressed as weighted backendRefs rather than vendor-specific annotations.

Migration workflow

Real-World Use Cases

Canary Deployments with Traffic Splitting

Gateway API's weighted routing makes canary deployments straightforward:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: api-canary
spec:
  parentRefs:
  - name: main-gateway
  hostnames:
  - "api.example.com"
  rules:
  - backendRefs:
    - name: api-stable
      port: 8080
      weight: 95
    - name: api-canary
      port: 8080
      weight: 5

Increase the canary weight gradually as confidence grows, then promote by updating the stable service and removing the canary.

Header-Based Routing for A/B Testing

Route users to different versions based on request headers:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: ab-test-route
spec:
  parentRefs:
  - name: main-gateway
  hostnames:
  - "app.example.com"
  rules:
  - matches:
    - headers:
      - name: X-User-Group
        value: beta
    backendRefs:
    - name: app-beta
      port: 8080
  - backendRefs:
    - name: app-stable
      port: 8080

Cross-Namespace Routing

Application teams can route traffic to services in different namespaces:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: frontend-route
  namespace: frontend-team
spec:
  parentRefs:
  - name: shared-gateway
    namespace: platform
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: frontend-service
      port: 80
      namespace: frontend-team
  - matches:
    - path:
        type: PathPrefix
        value: /api/users
    backendRefs:
    - name: user-service
      port: 8080
      namespace: backend-team

gRPC Routing

Gateway API has first-class support for gRPC through GRPCRoute:

apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
  name: grpc-route
spec:
  parentRefs:
  - name: main-gateway
  hostnames:
  - "grpc.example.com"
  rules:
  - matches:
    - method:
        service: myapp.UserService
        method: GetUser
    backendRefs:
    - name: user-grpc-service
      port: 50051

Best Practices for Production

  1. Start with a single Gateway β€” Use one Gateway per cluster or environment. Multiple Gateways create multiple load balancers, which increase cost and complexity.

  2. Use namespace selectors for security β€” Configure allowedRoutes.namespaces to restrict which teams can attach routes. Use label selectors for fine-grained control.

  3. Implement ReferenceGrants for cross-namespace access β€” When a route in namespace A needs to reference a service in namespace B, create a ReferenceGrant in namespace B to allow the cross-namespace reference.

  4. Use Gateway infrastructure annotations β€” Annotate your Gateway with cloud-provider-specific annotations to configure load balancer type, IP address allocation, and other infrastructure details.

  5. Monitor Gateway API status conditions β€” Check kubectl get httproute -o yaml to see status conditions that indicate whether routes are accepted and programmed.

  6. Version your route configurations β€” Use Git to manage HTTPRoute configurations and deploy them through CI/CD. Treat routing rules as code.

  7. Test with Gateway API conformance tests β€” The Gateway API project provides conformance tests that verify your implementation behaves correctly.

  8. Plan your TLS strategy β€” Decide whether TLS termination happens at the Gateway or at the backend Service. Use backendTLS for end-to-end encryption when needed.

Common Pitfalls and Solutions

PitfallImpactSolution
Route not attached to Gateway404 errorsCheck parentRefs and allowedRoutes namespace configuration
Cross-namespace reference rejectedRoute shows "RefNotPermitted" statusCreate a ReferenceGrant in the target namespace
Gateway stuck in "Pending"No load balancer provisionedVerify GatewayClass controller is running
TLS certificate not foundGateway listener not programmedEnsure Secret exists in the correct namespace
Traffic not splitting evenlyWeighted routing not workingVerify backend service ports match route port definitions
Status not updatingCannot debug route issuesCheck controller logs for reconciliation errors

Performance Optimization

Gateway API implementations are optimized for performance, but there are configuration choices that affect throughput:

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: high-perf-gateway
  annotations:
    # Envoy Gateway specific tuning
    gateway.envoyproxy.io/connection-buffer-limit: "32768"
spec:
  gatewayClassName: eg
  listeners:
  - name: http
    protocol: HTTP
    port: 80
    allowedRoutes:
      namespaces:
        from: All

For high-traffic deployments, consider:

  • Using connection draining during deployments
  • Configuring appropriate timeouts on HTTPRoutes
  • Enabling HTTP/2 or HTTP/3 for improved multiplexing
  • Using backend connection pooling through Gateway infrastructure annotations

Comparison with Alternatives

FeatureGateway APIIngressService Mesh (Istio)Traefik CRD
StandardYes (K8s SIG)Yes (K8s)No (vendor-specific)No (vendor-specific)
Role-based designYesNoPartialNo
Traffic splittingNativeAnnotationsNativeNative
Cross-namespaceNativeNoYesYes
gRPC supportNativeNoNativeNative
TCP/UDPNativeNoYesYes
mTLSBackend TLSNoNativePlugin
ComplexityMediumLowHighMedium
Vendor lock-inNoneNoneHighMedium

Gateway API is the right choice for most teams. Service meshes like Istio are appropriate when you need advanced features like mTLS between services, circuit breaking, and distributed tracing at the network level.

Advanced Patterns

Traffic Mirroring

Mirror production traffic to a canary deployment for testing without affecting users:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: mirror-route
spec:
  parentRefs:
  - name: main-gateway
  rules:
  - backendRefs:
    - name: api-stable
      port: 8080
    filters:
    - type: RequestMirror
      requestMirror:
        backendRef:
          name: api-canary
          port: 8080

URL Rewriting

Transform request URLs before forwarding to backends:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: rewrite-route
spec:
  parentRefs:
  - name: main-gateway
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /old-api
    filters:
    - type: URLRewrite
      urlRewrite:
        path:
          type: ReplacePrefixMatch
          replacePrefixMatch: /v2
    backendRefs:
    - name: api-v2
      port: 8080

Request Redirects

Redirect HTTP to HTTPS or redirect old paths to new paths:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: https-redirect
spec:
  parentRefs:
  - name: main-gateway
    sectionName: http
  rules:
  - filters:
    - type: RequestRedirect
      requestRedirect:
        scheme: https
        statusCode: 301

Testing Strategies

Validate Gateway API resources before deploying to production:

# Install Gateway API conformance tests
go test ./conformance/... -args \
  -gateway-class=envoy-gateway \
  -supported-features=HTTPRoute,HTTPRoutePathRedirect
 
# Test route matching
kubectl apply -f test-routes.yaml
kubectl get httproute -o yaml
 
# Verify traffic routing with curl
curl -H "Host: app.example.com" http://GATEWAY_IP/api/v1/users
curl -H "Host: app.example.com" -H "X-User-Group: beta" http://GATEWAY_IP/

Use the Gateway API status conditions to debug route attachment issues:

kubectl describe httproute app-route
# Check "RouteStatus" section for "Accepted" conditions

Future Outlook

Gateway API is actively evolving with new features and protocol support. Recent additions include:

  • GRPCRoute (GA) β€” First-class gRPC routing
  • TCPRoute / TLSRoute / UDPRoute β€” Support for non-HTTP protocols
  • Backend TLS Policy β€” End-to-end encryption between Gateway and backends
  • Gateway API Mesh β€” Extending Gateway API concepts to service mesh (GAMMA initiative)

The GAMMA (Gateway API for Mesh Management and Administration) initiative aims to unify ingress and service mesh routing under the Gateway API. This means the same HTTPRoute resources you use for ingress will work for east-west traffic within the mesh.

The long-term vision is that Gateway API becomes the single, standard API for all Kubernetes networkingβ€”north-south (ingress), east-west (mesh), and cross-cluster (multi-cluster). Investing in Gateway API today positions your infrastructure for this future.

Gateway API Adoption Strategy

Migrate from Ingress to Gateway API incrementally. Start by installing the Gateway API CRDs and a compatible controller in your cluster. Create a Gateway resource for your ingress class and convert one Ingress resource at a time to an HTTPRoute. Use the Gateway API's parentRefs to control which routes attach to which gateways, enabling multi-team gateway sharing. Monitor the transition by running both Ingress and Gateway API resources in parallel during migration. Once all routes are converted, remove the Ingress resources and the legacy ingress controller.

Gateway API Multi-tenancy

Implement multi-tenancy with Gateway API using Gateway resources per team or namespace. Each team can create their own HTTPRoute resources that reference shared Gateway infrastructure. Use ReferenceGrants to allow cross-namespace references securely. Implement rate limiting and traffic policies at the Gateway level to prevent one tenant from monopolizing resources. Use parentRefs with namespace selectors to control which routes attach to which gateways. Monitor per-tenant traffic using metrics labels derived from Gateway API metadata.

Conclusion

Gateway API is the official successor to Kubernetes Ingress, offering a richer, more expressive, and role-based approach to traffic routing. Its separation of concerns between infrastructure providers, cluster operators, and application developers makes it ideal for multi-team environments.

Key takeaways:

  1. Gateway API replaces Ingress with three resource types: GatewayClass, Gateway, and HTTPRoute
  2. Role-based design separates infrastructure (GatewayClass), operations (Gateway), and routing (HTTPRoute)
  3. First-class support for traffic splitting, header matching, request mirroring, and cross-namespace routing
  4. Supported by all major ingress controller implementations (NGINX, Envoy, Istio, Traefik, Kong)
  5. HTTPRoute supports weighted backendRefs for canary deployments without vendor annotations
  6. ReferenceGrant resources control cross-namespace service references
  7. GRPCRoute provides native gRPC routing support
  8. Status conditions on resources provide clear feedback on configuration errors

Start by installing a Gateway API-compatible controller, creating a Gateway resource, and migrating one Ingress resource at a time to HTTPRoute. The migration is straightforward, and the benefits in routing expressiveness and role separation are substantial.

For deeper exploration, see the Gateway API specification, the Gateway API conformance tests, and the Envoy Gateway documentation.