πŸ“šBook Signing at KubeCon EU 2026Meet us at Booking.com HQ (Mon 18:30-21:00) & vCluster booth #521 (Tue 24 Mar, 12:30-1:30pm) β€” free book giveaway!RSVP Booking.com Event
Networking advanced ⏱ 15 minutes K8s 1.30+

Gateway API gRPC Routes on Kubernetes

Configure Kubernetes Gateway API GRPCRoute for gRPC traffic routing. Service-level matching, header-based routing, and traffic splitting for gRPC services.

By Luca Berton β€’ β€’ πŸ“– 5 min read

πŸ’‘ Quick Answer: Use GRPCRoute (GA in Gateway API v1.2+) to route gRPC traffic by service name, method, or headers. Attach to a Gateway listener on port 443 with protocol: HTTPS. Match gRPC services with matches[].method.service and matches[].method.method. Traffic splitting works like HTTPRoute backendRefs with weights.

The Problem

gRPC uses HTTP/2 with service/method-based routing that doesn’t fit the traditional path-based Ingress model. You need native gRPC routing with service-level matching, header-based canary deployments, and proper load balancing.

The Solution

Gateway Setup

apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
  name: grpc-gateway
  namespace: infrastructure
spec:
  gatewayClassName: cilium  # or istio, envoy-gateway, etc.
  listeners:
    - name: grpc
      protocol: HTTPS
      port: 443
      tls:
        mode: Terminate
        certificateRefs:
          - name: grpc-tls-cert

Basic GRPCRoute

apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
  name: user-service-route
  namespace: production
spec:
  parentRefs:
    - name: grpc-gateway
      namespace: infrastructure
  hostnames:
    - "api.example.com"
  rules:
    - matches:
        - method:
            service: "user.v1.UserService"
      backendRefs:
        - name: user-service
          port: 50051
    - matches:
        - method:
            service: "order.v1.OrderService"
      backendRefs:
        - name: order-service
          port: 50051

Method-Level Routing

apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
  name: method-routing
spec:
  parentRefs:
    - name: grpc-gateway
      namespace: infrastructure
  rules:
    # Route specific methods to specialized backends
    - matches:
        - method:
            service: "ai.v1.InferenceService"
            method: "Predict"
      backendRefs:
        - name: inference-gpu
          port: 50051
    - matches:
        - method:
            service: "ai.v1.InferenceService"
            method: "GetModel"
      backendRefs:
        - name: inference-cpu
          port: 50051

Header-Based Canary

apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
  name: canary-route
spec:
  parentRefs:
    - name: grpc-gateway
      namespace: infrastructure
  rules:
    # Canary: header x-canary=true goes to v2
    - matches:
        - method:
            service: "payment.v1.PaymentService"
          headers:
            - name: x-canary
              value: "true"
      backendRefs:
        - name: payment-service-v2
          port: 50051
    # Default: all other traffic to v1
    - matches:
        - method:
            service: "payment.v1.PaymentService"
      backendRefs:
        - name: payment-service-v1
          port: 50051

Traffic Splitting (Weighted)

apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
  name: weighted-route
spec:
  parentRefs:
    - name: grpc-gateway
      namespace: infrastructure
  rules:
    - matches:
        - method:
            service: "search.v1.SearchService"
      backendRefs:
        - name: search-service-v1
          port: 50051
          weight: 90
        - name: search-service-v2
          port: 50051
          weight: 10

gRPC Backend Service

apiVersion: v1
kind: Service
metadata:
  name: user-service
  namespace: production
spec:
  selector:
    app: user-service
  ports:
    - name: grpc
      port: 50051
      targetPort: 50051
      protocol: TCP
      appProtocol: kubernetes.io/h2c  # Important: signals HTTP/2

Verify Routes

# Check route status
kubectl get grpcroute -A

# Test with grpcurl
grpcurl -d '{"user_id": "123"}' \
  -authority api.example.com \
  api.example.com:443 \
  user.v1.UserService/GetUser

Common Issues

IssueCauseFix
Connection resetBackend not HTTP/2Set appProtocol: kubernetes.io/h2c on Service
Route not attachedGateway doesn’t allow namespaceAdd allowedRoutes to Gateway
404 on methodService/method name wrongMust match proto definition exactly
TLS errorsCertificate doesn’t cover hostnameUpdate cert SANs
No traffic splittingController doesn’t support weightsCheck controller docs

Best Practices

  1. Always use TLS β€” gRPC in production should be encrypted
  2. Set appProtocol β€” Tells the gateway the backend speaks HTTP/2
  3. Use service-level matching first β€” Method-level only when needed
  4. Health check with gRPC health protocol β€” Not HTTP probes
  5. Monitor per-method latency β€” gRPC services can have wildly different method costs

Key Takeaways

  • GRPCRoute is GA in Gateway API v1.2+ for native gRPC routing
  • Match traffic by gRPC service name, method, and headers
  • Traffic splitting enables gRPC canary deployments
  • Backend services need appProtocol: kubernetes.io/h2c for HTTP/2
  • Works with Cilium, Istio, Envoy Gateway, and other Gateway API implementations
#gateway-api #grpc #networking #routing
Luca Berton
Written by Luca Berton

Principal Solutions Architect specializing in Kubernetes, AI/GPU infrastructure, and cloud-native platforms. Author of Kubernetes Recipes and creator of CopyPasteLearn courses.

Kubernetes Recipes book cover

Want More Kubernetes Recipes?

This recipe is from Kubernetes Recipes, our 750-page practical guide with hundreds of production-ready patterns.

Luca Berton Ansible Pilot Ansible by Example Open Empower K8s Recipes Terraform Pilot CopyPasteLearn ProteinLens