Skip to main content
  1. Articles/

Kubernetes Gateway API: the successor to Ingress is here

Ingress has served us well, but it quickly hits its limits: endless proprietary annotations, no separation of responsibilities, features missing from the official spec. The Gateway API was designed to fix all of that. It’s been GA since Kubernetes 1.28 (October 2023) and is supported by most current network controllers.

Why replace Ingress? #

Ingress suffers from several structural problems:

  • Limited expressiveness: basic HTTP routing is in the spec, everything else goes through nginx.ingress.kubernetes.io/... or traefik.ingress.kubernetes.io/... annotations that aren’t portable.
  • No role separation: infra and application teams modify the same object.
  • Advanced features missing: traffic splitting, header matching, complex redirects, TCP/UDP routing — all out of spec.

The Gateway API solves these three problems with a role-oriented model and a rich spec.

The key resources #

The Gateway API introduces a hierarchy of three main resources:

GatewayClass  →  defined by the infra provider (e.g. Traefik, Cilium, Istio)
    └── Gateway  →  defined by the ops / cluster admin
            └── HTTPRoute / TCPRoute / GRPCRoute  →  defined by the app devs

GatewayClass #

Declares which controller manages the Gateways. Created once by the infra provider.

apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata:
  name: traefik
spec:
  controllerName: traefik.io/gateway-controller

Gateway #

Defines a network entry point (equivalent to a reverse proxy’s “listener”). It’s the ops who manages it, not the devs.

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: main-gateway
  namespace: traefik
spec:
  gatewayClassName: traefik
  listeners:
    - name: web
      port: 80
      protocol: HTTP
      allowedRoutes:
        namespaces:
          from: All
    - name: websecure
      port: 443
      protocol: HTTPS
      tls:
        mode: Terminate
        certificateRefs:
          - name: tls-secret
      allowedRoutes:
        namespaces:
          from: All

HTTPRoute #

This is the object application teams create in their own namespace.

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: mon-app
  namespace: production
spec:
  parentRefs:
    - name: main-gateway
      namespace: traefik
      sectionName: websecure
  hostnames:
    - "mon-app.example.com"
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /
      backendRefs:
        - name: mon-app-svc
          port: 8080

Features missing from Ingress #

Traffic splitting (canary / blue-green) #

No proprietary annotation, straight in the standard spec:

rules:
  - backendRefs:
      - name: app-v1
        port: 8080
        weight: 90
      - name: app-v2
        port: 8080
        weight: 10

HTTP → HTTPS redirect #

rules:
  - filters:
      - type: RequestRedirect
        requestRedirect:
          scheme: https
          statusCode: 301

Path rewriting #

rules:
  - matches:
      - path:
          type: PathPrefix
          value: /api
    filters:
      - type: URLRewrite
        urlRewrite:
          path:
            type: ReplacePrefixMatch
            replacePrefixMatch: /
    backendRefs:
      - name: api-svc
        port: 3000

Header-based routing #

Useful for preview environments or A/B routing:

rules:
  - matches:
      - headers:
          - name: X-Env
            value: staging
    backendRefs:
      - name: app-staging
        port: 8080

Separation of responsibilities #

This is the real organizational gain. The Gateway API defines three personas:

PersonaResourcesResponsibility
Infrastructure providerGatewayClassDeploying the controller (Traefik, Cilium…)
Cluster operatorGatewayListeners, TLS, allowed namespaces
Application developerHTTPRoute, TCPRouteApplication routing in their namespace

Each team only touches the objects that concern it. No more need to grant cluster-wide access to expose an application.

Installation with Traefik #

Traefik has supported the Gateway API since v3. You first need to install the official CRDs:

kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/standard-install.yaml

Then enable the feature gate in Traefik (Helm values):

# values.yaml
providers:
  kubernetesGateway:
    enabled: true

experimental:
  kubernetesGateway:
    enabled: true

Check that the CRDs are properly installed:

kubectl get crd | grep gateway.networking.k8s.io

Project status and experimental channels #

The Gateway API is versioned in two channels:

  • Standard: HTTPRoute, Gateway, GatewayClass, GRPCRouteGA
  • Experimental: TCPRoute, TLSRoute, UDPRoute, BackendLBPolicy — beta, subject to change
# Install the experimental channel (includes standard)
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/experimental-install.yaml

Migrating from Ingress #

No automatic migration, but the mapping is direct:

IngressGateway API
spec.rules[].hostHTTPRoute.spec.hostnames
spec.rules[].http.pathsHTTPRoute.spec.rules[].matches
spec.tlsGateway.spec.listeners[].tls
Proprietary annotationsNative filters in HTTPRoute

Ingress and the Gateway API can coexist during the migration: Traefik handles both simultaneously.

Conclusion #

The Gateway API is no longer a preview, it’s production-ready and actively developed. If you’re starting a new cluster or have time to migrate, now is the right moment. The role separation alone justifies the change in multi-team environments.

The next versions (v1.3+) should bring mesh routing (service-to-service) into the standard spec, which could compete directly with solutions like Istio for simple use cases.