Skip to content

Kubernetes Gateway API Reference: HTTPRoute, GatewayClass, Traffic Splitting & GRPCRoute

Kubernetes Gateway API is the successor to Ingress — richer, more expressive, and role-based. It graduated to GA (v1) in K8s 1.28. HTTPRoute, GRPCRoute, TCPRoute and more replace the single Ingress spec, while Gateway is the infrastructure object that cluster operators control separately from app developers.

1. Gateway API vs Ingress

Why Gateway API exists and how it maps to Ingress concepts
Concept Ingress Gateway API
Infrastructure config IngressClass (basic) GatewayClass — controller-specific
Listener + TLS Ingress.spec.tls Gateway — defines listeners + TLS
Routing rules Ingress.spec.rules HTTPRoute / GRPCRoute / TCPRoute
Role separation Single resource, often one owner GatewayClass (cluster admin), Gateway (platform), Routes (developers)
Traffic splitting Annotation hack (nginx-specific) First-class backendRefs weights
Header matching Annotation-based Native spec fields
Status Stable (GA since K8s 1.1) GA (v1) since K8s 1.28
# Install Gateway API CRDs (required before using any implementation):
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.1.0/standard-install.yaml

# Implementations (pick one — they provide the GatewayClass):
# - Envoy Gateway: envoyproxy/gateway
# - Cilium: uses eBPF, no proxy
# - Istio: full service mesh + Gateway API
# - Kong: ingress-kong
# - Traefik: traefik/traefik (v3+)
# - NGINX Gateway Fabric: nginxinc/nginx-gateway-fabric

# Install Envoy Gateway (popular, lightweight):
helm install eg oci://docker.io/envoyproxy/gateway-helm   --namespace envoy-gateway-system --create-namespace   --version v1.1.2

2. GatewayClass, Gateway & HTTPRoute

Core objects — the three-layer separation of concerns
# GatewayClass (cluster admin — declares which controller handles Gateways):
# Created automatically by Envoy Gateway / Cilium / etc. after install
# List available: kubectl get gatewayclass

# Gateway (platform team — defines listeners, ports, TLS):
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: prod-gateway
  namespace: gateway-infra
spec:
  gatewayClassName: eg              # matches GatewayClass name from controller
  listeners:
    - name: http
      port: 80
      protocol: HTTP
      allowedRoutes:
        namespaces:
          from: Selector            # only allow routes from labeled namespaces
          selector:
            matchLabels:
              gateway-access: "true"
    - name: https
      port: 443
      protocol: HTTPS
      tls:
        certificateRefs:
          - kind: Secret
            name: wildcard-tls      # TLS cert from cert-manager
      allowedRoutes:
        namespaces:
          from: All

# HTTPRoute (app developer — defines routing rules):
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: api-route
  namespace: production
spec:
  parentRefs:
    - name: prod-gateway
      namespace: gateway-infra      # reference to Gateway above
  hostnames:
    - api.example.com
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /api
      backendRefs:
        - name: api-service
          port: 8080

3. Traffic Splitting & Header Matching

Canary by weight, A/B by header, and URL rewrites — all in spec
# Traffic splitting by weight (canary — no annotations needed):
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: api-canary
  namespace: production
spec:
  parentRefs:
    - name: prod-gateway
      namespace: gateway-infra
  hostnames: [api.example.com]
  rules:
    - matches:
        - path: {type: PathPrefix, value: /api}
      backendRefs:
        - name: api-service-stable
          port: 8080
          weight: 90                # 90% of traffic
        - name: api-service-canary
          port: 8080
          weight: 10                # 10% to canary

# Header-based routing (A/B testing, beta users):
rules:
  - matches:
      - headers:
          - name: X-Beta-User
            value: "true"
    backendRefs:
      - name: api-service-beta
        port: 8080
  - backendRefs:                    # default (no match)
      - name: api-service-stable
        port: 8080

# URL rewrite (strip /api prefix):
rules:
  - matches:
      - path: {type: PathPrefix, value: /api}
    filters:
      - type: URLRewrite
        urlRewrite:
          path:
            type: ReplacePrefixMatch
            replacePrefixMatch: /     # strip /api prefix
    backendRefs:
      - name: api-service
        port: 8080

4. TLS with cert-manager & ReferenceGrant

Cross-namespace TLS secrets and cert-manager ClusterIssuer integration
# Gateway references TLS cert from cert-manager:
# cert-manager automatically creates the Secret when it sees a Gateway with:
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: prod-gateway
  namespace: gateway-infra
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod  # trigger auto-cert
spec:
  listeners:
    - name: https
      port: 443
      protocol: HTTPS
      hostname: "*.example.com"
      tls:
        certificateRefs:
          - name: wildcard-example-cert   # cert-manager creates this

# ReferenceGrant — allow HTTPRoute in 'production' to reference backend in 'backend-ns':
# (Gateway API cross-namespace references need explicit grants)
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
  name: allow-production-routes
  namespace: backend-ns              # namespace BEING referenced
spec:
  from:
    - group: gateway.networking.k8s.io
      kind: HTTPRoute
      namespace: production          # namespace doing the referencing
  to:
    - group: ""
      kind: Service

# Check Gateway + HTTPRoute status:
kubectl get gateway prod-gateway -n gateway-infra -o yaml | grep -A10 status
kubectl get httproute -A                               # list all routes
kubectl describe httproute api-route -n production     # conditions + events

5. GRPCRoute & TCPRoute

Route gRPC services and raw TCP — beyond HTTP
# GRPCRoute (GA in v1.1.0) — route gRPC traffic with service/method matching:
apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
  name: grpc-route
  namespace: production
spec:
  parentRefs:
    - name: prod-gateway
      namespace: gateway-infra
  hostnames: [grpc.example.com]
  rules:
    - matches:
        - method:
            service: user.UserService    # full gRPC service name
            method: GetUser              # specific method (optional — omit to match all)
      backendRefs:
        - name: user-grpc-service
          port: 50051
    - matches:
        - method:
            service: order.OrderService  # all methods on OrderService
      backendRefs:
        - name: order-grpc-service
          port: 50051

# TCPRoute (experimental) — raw TCP passthrough (databases, custom protocols):
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TCPRoute
metadata:
  name: postgres-route
  namespace: data
spec:
  parentRefs:
    - name: prod-gateway
      namespace: gateway-infra
      sectionName: postgres-listener   # must have TCP listener on Gateway
  rules:
    - backendRefs:
        - name: postgres-service
          port: 5432

# Add TCP listener to Gateway for TCPRoute:
# - name: postgres-listener
#   port: 5432
#   protocol: TCP
#   allowedRoutes:
#     namespaces: {from: Selector}

Track Kubernetes Gateway API and Kubernetes releases.
ReleaseRun monitors Kubernetes, Docker, and 13+ DevOps technologies.

Related: NGINX Ingress Controller Reference | Kubernetes YAML Reference | cert-manager Reference

🔍 Free tool: K8s YAML Security Linter — check Gateway API manifests — HTTPRoute, GRPCRoute — for K8s security misconfigurations.

Founded

2023 in London, UK

Contact

hello@releaserun.com