backend / kubernetes / 08_gateway_api.md

Gateway API

6 interview angles 4 min read source

Gateway API

The successor to Ingress. GA and the recommended path for new work, while Ingress remains supported but effectively frozen. Answering a Kubernetes traffic question with only Ingress dates you.

Why Ingress needed replacing

Ingress solved HTTP routing in 2016 and then stopped evolving. Its problems compounded:

  • Annotation sprawl. Anything beyond host and path routing — timeouts, rewrites, rate limits, canary weights — lived in vendor-specific annotations. An nginx-ingress manifest doesn’t work on Traefik or an AWS ALB controller.
  • No portability. The spec covered so little that every controller invented its own extensions, so “we use Ingress” told you almost nothing.
  • One role. A single resource mixed infrastructure concerns (which load balancer, which certificate) with application concerns (which path goes where), so platform teams and application teams contended over the same object.
  • HTTP only. No first-class TCP, UDP or gRPC.

The model

Gateway API splits one resource into three, along organisational lines:

GatewayClass   <- infrastructure provider    (platform team, cluster-scoped)
    |
  Gateway      <- a listener: port, protocol, TLS   (platform/ops)
    |
  HTTPRoute    <- routing rules              (application team, namespaced)

That separation is the design’s real point: the person who owns TLS and load balancers isn’t the person who owns /api/v2 routing. Role-oriented design, not just a richer schema.

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: prod-gateway
  namespace: infra
spec:
  gatewayClassName: envoy
  listeners:
    - name: https
      protocol: HTTPS
      port: 443
      tls:
        certificateRefs: [{ name: prod-tls }]
      allowedRoutes:
        namespaces:
          from: Selector          # which namespaces may attach routes
          selector:
            matchLabels: { gateway-access: "true" }
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: api
  namespace: team-payments
spec:
  parentRefs: [{ name: prod-gateway, namespace: infra }]
  hostnames: ["api.example.com"]
  rules:
    - matches:
        - path: { type: PathPrefix, value: /payments }
      backendRefs:
        - name: payments-v1
          port: 8080
          weight: 90
        - name: payments-v2         # canary, in the spec - no annotations
          port: 8080
          weight: 10

What’s in the spec that used to be annotations

Capability Ingress Gateway API
Header/method/query matching annotations spec
Traffic splitting / canary annotations weight
Header modification annotations filters
Redirects and rewrites annotations filters
Request mirroring rarely filter
TCP, UDP, gRPC routing no TCPRoute, UDPRoute, GRPCRoute
Cross-namespace routing no ReferenceGrant

Weighted traffic splitting in the spec is the one to name — progressive delivery without a service mesh or vendor annotations. See ../27_cicd/08_progressive_delivery.md.

Cross-namespace references

A route in one namespace attaching to a Gateway in another is explicitly controlled from both directions: the Gateway’s allowedRoutes says who may attach, and a ReferenceGrant in the target namespace permits references to its Services.

This is a genuine security improvement — Ingress had no way to express “team A may route to this Gateway but not to team B’s services”.

Migrating

  1. Install the Gateway API CRDs and a controller (Envoy Gateway, Istio, Cilium, NGINX Gateway Fabric, or a cloud controller).
  2. Create a Gateway alongside your existing Ingress.
  3. Convert routes incrementally — both can serve traffic during migration.
  4. Cut DNS over, then remove the Ingress.

ingress2gateway converts existing manifests as a starting point; vendor annotations still need manual translation, since that’s precisely what wasn’t portable.

Ingress is not deprecated and will keep working. But it receives no new features, so anything you want beyond basic routing is either a vendor annotation or a reason to move.

Interview angle

  • “How do you expose a service outside the cluster?” — Service type LoadBalancer for L4, and for HTTP the Gateway API, which is GA and the recommended path. Ingress still works but is feature-frozen, so new capability lands only in Gateway API.
  • “What was wrong with Ingress?” — the spec covered so little that everything real lived in vendor-specific annotations, which killed portability. It also mixed infrastructure and application concerns in one resource, so platform and app teams contended over it, and it was HTTP-only.
  • “What does Gateway API change structurally?” — three resources split by role: GatewayClass for the provider, Gateway for listeners/ports/TLS owned by the platform team, and HTTPRoute for routing owned by application teams in their own namespaces.
  • “How would you do a canary deployment with it?”backendRefs with weights in the HTTPRoute spec. No annotations, no service mesh required, and it’s portable across controllers.
  • “How do you stop one team routing to another team’s services?”allowedRoutes on the Gateway controls which namespaces may attach, and ReferenceGrant in the target namespace permits cross-namespace backend references. Both sides must agree, which Ingress couldn’t express.
  • “Do you have to migrate?” — no, Ingress keeps working. You migrate when you want features that will only ever exist in Gateway API, and you can run both side by side during the transition.