Post 5/10 — From Ingress to Gateway API: Safer, Smarter Traffic Control

The question of why traffic should be controlled using additional means when Kubernetes offers in-built traffic management capabilities. Many Cloud Service Providers also have offerings around the same but having a set of defined policies to execute traffic management is necessary. This helps the application distribute the load in the system strategically. It also ensures lower latency in fulfilling request. Moreover, these policies make application secure my allowing limited access of resources both in and out of the Kubernetes cluster.

1) Executive Summary

When I first learned Kubernetes networking, Ingress felt like the magic front-door. But as clusters, tenants, and compliance needs grew, that door started to creak. Enter Gateway API — the modern, role-aware evolution that finally decouples platform and app teams safely.

This post walks through what changes (and why), shows a Before → After migration, and ends with a mini-lab you can run on any cluster.

2) Prereqs

  • A working cluster (minikube/kind/EKS/GKE).
  • kubectl ≥ 1.28 + gateway-api CRDs installed (kubectl apply k https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.0.0/standard-install.yaml).
  • Basic understanding of Ingress objects, Services, and TLS secrets.

3) Concepts

Ingress vs Gateway mental model

Aspect Ingress Gateway API
Scope Cluster-wide front door Namespaced, multi-tenant gateways
Roles One YAML = shared config Split into Gateway (ops) + HTTPRoute (dev)
Extensibility Annotations galore Typed fields + policies
Status Controller-specific Standardized conditions

Think of Ingress as a flat router file. Gateway API adds layers:

  • GatewayClass – defines the implementation (e.g., Istio, NGINX).
  • Gateway – deployed by platform teams (where traffic enters).
  • HTTPRoute – attached by app teams (what traffic does).

Gateway + HTTPRoute basics

Gateway: specifies listeners, ports, and TLS termination.
HTTPRoute: defines matches (hosts, paths, headers) and forwards traffic to services.

# gateway.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: web-gw
  namespace: platform
spec:
  gatewayClassName: nginx
  listeners:
  - name: https
    port: 443
    protocol: HTTPS
    tls:
      mode: Terminate
      certificateRefs:
      - name: my-cert
    allowedRoutes:
      namespaces:
        from: All
# route.yaml
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: shop-route
  namespace: shop
spec:
  parentRefs:
  - name: web-gw
    namespace: platform
  hostnames: ["shop.example.com"]
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: shop-svc
      port: 80

TLS, Retries, Timeouts, Header Matching

Gateway API formalizes what used to be annotation chaos:

  rules:
  - matches:
    - headers:
      - name: x-region
        value: eu
    backendRefs:
    - name: shop-svc-eu
      port: 80
  filters:
  - type: RequestTimeout
    requestTimeout:
      duration: 5s
  - type: Retry
    retry:
      count: 3
      statusCodes: ["5xx"]

Canary / Mirroring / Multi-tenant Gateways

Weighted traffic splits and mirrored routes are first-class now:

  backendRefs:
  - name: shop-svc
    port: 80
    weight: 80
  - name: shop-svc-canary
    port: 80
    weight: 20

Multiple HTTPRoutes can attach to one Gateway, safely namespaced.
Ops maintain TLS + exposure policies; devs just ship routes.

4) Mini-Lab — Replace Ingress with Gateway/HTTPRoute + Canary + TLS

Before (legacy Ingress):

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: shop
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  tls:
  - hosts: [shop.example.com]
    secretName: my-cert
  rules:
  - host: shop.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: shop-svc
            port:
              number: 80

After (Gateway API):
Apply gateway.yaml and route.yaml from above.

Verify:

kubectl get gateways -A
kubectl get httproutes -A
kubectl describe httproute shop-route

Add a canary service and observe:

kubectl get endpoints shop-svc-canary -o wide
curl -H "x-canary:true" https://shop.example.com

You’ll see controlled traffic flow, better observability, and cleaner ownership.

5) Cheatsheet

Task Command
List GatewayClasses kubectl get gatewayclass
Inspect listeners kubectl describe gateway <name>
List routes per gateway kubectl get httproute -A --field-selector spec.parentRefs.name=<gw>
Apply TLS secret kubectl create secret tls my-cert --cert cert.pem --key key.pem -n platform
Test connectivity curl -k https://host

Key fields:

  • listeners.protocol, tls.mode, allowedRoutes
  • rules.matches, filters, backendRefs.weight

6) Pitfalls

  • Policy attachment order: Gateway policies apply before Route policies → watch precedence.
  • Overlapping routes: Multiple HTTPRoutes with same host/path → controller decides priority.
  • Cross-namespace refs: If allowedRoutes.from=Same, dev teams can’t attach externally.
  • Controller support: Check status.conditions for accepted listeners.

7) Wrap-Up

With Gateway API, Kubernetes finally gives us policy-aware traffic control that scales across teams and environments — safer, cleaner, and built for automation.

Next up in the series: Helm Fundamentals (Post 6) — we’ll templatize these Gateway objects and parameterize routes the right way.

Similar Posts