gRPC services
Route traffic to gRPC services using the GRPCRoute resource for protocol-aware routing.
About
GRPCRoute provides protocol-aware routing for gRPC traffic within the Kubernetes Gateway API. Unlike HTTPRoute, which requires matching on HTTP paths and methods, GRPCRoute allows you to define routing rules using gRPC-native concepts like service and method names.
Consider the difference:
- HTTPRoute Match:
path:/com.example.User/Login
,method: POST
- GRPCRoute Match:
service: yages.Echo
,method: Ping
The GRPCRoute approach is more readable, less error-prone, and aligns with the Gateway API’s role-oriented philosophy.
Before you begin
Deploy a sample gRPC service
Deploy a sample gRPC service for testing purposes. The sample service has two APIs:
yages.Echo.Ping
: Takes no input (empty message) and returns apong
message.yages.Echo.Reverse
: Takes input content and returns the content in reverse order, such ashello world
becomesdlrow olleh
.
Steps to set up the sample gRPC service:
-
Deploy the gRPC echo server and client.
kubectl apply -f - <<EOF apiVersion: apps/v1 kind: Deployment metadata: name: grpc-echo spec: selector: matchLabels: app: grpc-echo replicas: 1 template: metadata: labels: app: grpc-echo spec: containers: - name: grpc-echo image: ghcr.io/projectcontour/yages:v0.1.0 ports: - containerPort: 9000 protocol: TCP env: - name: POD_NAME valueFrom: fieldRef: fieldPath: metadata.name - name: NAMESPACE valueFrom: fieldRef: fieldPath: metadata.namespace - name: GRPC_ECHO_SERVER value: "true" - name: SERVICE_NAME value: grpc-echo --- apiVersion: v1 kind: Service metadata: name: grpc-echo-svc spec: type: ClusterIP ports: - port: 3000 protocol: TCP targetPort: 9000 appProtocol: kubernetes.io/h2c selector: app: grpc-echo --- apiVersion: v1 kind: Pod metadata: name: grpcurl-client spec: containers: - name: grpcurl image: docker.io/fullstorydev/grpcurl:v1.8.7-alpine command: - sleep - "infinity" EOF
-
Create a ReferenceGrant to allow GRPCRoutes to reference the gRPC echo service.
kubectl apply -f - <<EOF apiVersion: gateway.networking.k8s.io/v1beta1 kind: ReferenceGrant metadata: name: allow-grpc-route-to-echo namespace: default spec: from: - group: gateway.networking.k8s.io kind: GRPCRoute namespace: kgateway-system to: - group: "" kind: Service EOF
Set up the Gateway for gRPC routes
Create an HTTPS listener so that the gateway can route gRPC traffic. GRPCRoute requires HTTPS listeners for TLS termination. For more information, see the HTTPS listener guide.
-
Create a TLS certificate for testing.
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \ -keyout grpc.example.com.key \ -out grpc.example.com.crt \ -subj "/CN=grpc.example.com" kubectl create secret tls grpc-example-com-cert \ -n kgateway-system \ --key grpc.example.com.key \ --cert grpc.example.com.crt
-
Create a Gateway resource with an HTTPS listener.
kubectl apply -f - <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: grpc-gateway namespace: kgateway-system labels: app: grpc-echo spec: gatewayClassName: kgateway listeners: - protocol: HTTPS port: 443 name: https hostname: "grpc.example.com" tls: mode: Terminate certificateRefs: - name: grpc-example-com-cert allowedRoutes: namespaces: from: All EOF
Setting Description spec.gatewayClassName
The name of the Kubernetes GatewayClass. When you set up kgateway, a default GatewayClass is set up for you. spec.listeners
Configure the listeners for this Gateway. GRPCRoute requires HTTPS listeners with TLS termination. hostname
The hostname for SNI-based routing. Must match the hostname in your GRPCRoute. tls.mode: Terminate
Terminates TLS at the gateway, required for GRPCRoute. -
Check the status of the Gateway.
kubectl get gateway grpc-gateway -n kgateway-system -o yaml
Example output:
status: addresses: - type: IPAddress value: ${INGRESS_GW_ADDRESS} conditions: - lastTransitionTime: "2024-11-20T16:01:25Z" message: "" observedGeneration: 2 reason: Accepted status: "True" type: Accepted - lastTransitionTime: "2024-11-20T16:01:25Z" message: "" observedGeneration: 2 reason: Programmed status: "True" type: Programmed
Create a GRPCRoute
-
Create the GRPCRoute resource. Include the
grpc.reflection.v1alpha.ServerReflection
method to enable dynamic API exploration. For detailed information about GRPCRoute fields and configuration options, see the Gateway API GRPCRoute documentation.kubectl apply -f - <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: GRPCRoute metadata: name: grpc-echo-route namespace: kgateway-system labels: app: grpc-echo spec: parentRefs: - name: grpc-gateway namespace: kgateway-system sectionName: https hostnames: - "grpc.example.com" rules: - matches: - method: service: "grpc.reflection.v1alpha.ServerReflection" backendRefs: - name: grpc-echo-svc namespace: default port: 3000 - backendRefs: - name: grpc-echo-svc namespace: default port: 3000 EOF
-
Verify that the GRPCRoute is applied successfully.
kubectl get grpcroute grpc-echo-route -n kgateway-system -o yaml
Example output:
status: parents: - conditions: - lastTransitionTime: "2024-11-21T16:22:52Z" message: "" observedGeneration: 1 reason: Accepted status: "True" type: Accepted - lastTransitionTime: "2024-11-21T16:22:52Z" message: "" observedGeneration: 1 reason: ResolvedRefs status: "True" type: ResolvedRefs controllerName: kgateway.dev/kgateway parentRef: group: gateway.networking.k8s.io kind: Gateway name: grpc-gateway namespace: kgateway-system sectionName: https
Verify the gRPC route
Verify that the gRPC route to the echo service is working.
-
Get the external address of the gateway and save it in an environment variable.
export GATEWAY_IP=$(kubectl get gateway grpc-gateway -n kgateway-system -o jsonpath='{.status.addresses[0].value}') echo $GATEWAY_IP
kubectl port-forward svc/grpc-gateway -n kgateway-system 8443:443
-
Explore the API dynamically.
grpcurl -insecure -authority grpc.example.com $GATEWAY_IP:443 list grpcurl -insecure -authority grpc.example.com $GATEWAY_IP:443 describe yages.Echo
grpcurl -insecure -authority grpc.example.com localhost:8443 list grpcurl -insecure -authority grpc.example.com localhost:8443 describe yages.Echo
Expected response:
grpc.health.v1.Health grpc.reflection.v1alpha.ServerReflection yages.Echo yages.Echo is a service: service Echo { rpc Ping ( .yages.Empty ) returns ( .yages.Content ); rpc Reverse ( .yages.Content ) returns ( .yages.Content ); }
-
Send a gRPC request to test the route.
grpcurl -insecure \ -authority grpc.example.com \ $GATEWAY_IP:443 \ yages.Echo/Ping
grpcurl -insecure \ -authority grpc.example.com \ localhost:8443 \ yages.Echo/Ping
Expected response:
{ "text": "pong" }
Next steps
Explore the traffic management, resiliency, and security policies that you can apply to make your gRPC services more robust and secure.
Cleanup
You can remove the resources that you created in this guide.kubectl delete -A gateways,grpcroutes,pod,svc,secrets -l app=grpc-echo
kubectl delete referencegrant allow-grpc-route-to-echo -n default