Proxy gRPC Traffic
Configure APISIX or API7 Ingress Controller to proxy gRPC traffic to a Kubernetes gRPC service.
Applies to:API7 Ingress Controller (drives API7 Gateway)APISIX Ingress Controller (drives Apache APISIX)
Goal
Route gRPC requests through the gateway to a Kubernetes gRPC service using a Gateway API GRPCRoute or an APISIX CRD route.
Before you begin
- Complete Set Up Ingress Controller and Gateway.
- Install gRPCurl to verify gRPC traffic proxying.
- Download the
helloworld.protofile and save it ashelloworld.proto. - You have
kubectlconfigured against the cluster used in the setup guide. - Choose free ports for the gRPC upstream and the gateway HTTP/2 listener. The examples use
50051and9081.
Set the variables this guide uses:
export UPSTREAM_GRPC_PORT="50051"
export GATEWAY_SERVICE_NAME="apisix-gateway" # your gateway's Service name in namespace aic
export GATEWAY_H2_PORT="9081"
export FORWARD_PORT="9081" # local port for the gateway port-forward
export GRPC_SERVICE="helloworld.Greeter"
export GRPC_METHOD="helloworld.Greeter.SayHello"
export GRPC_REQUEST='{"name":"World"}'
export PROTO_FILE="helloworld.proto"Steps
Step 1: Deploy the example gRPC upstream
Create a manifest for the gRPC server deployment and service in the aic namespace:
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: aic
name: grpc-service
spec:
replicas: 1
selector:
matchLabels:
app: grpc-service
template:
metadata:
labels:
app: grpc-service
spec:
containers:
- name: grpc-service
image: api7/grpc-server-example:1.0.0
ports:
- containerPort: 50051
---
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: grpc-service
spec:
type: ClusterIP
selector:
app: grpc-service
ports:
- name: grpc
port: 50051
targetPort: 50051Apply the manifest and wait for the Pod to become ready:
kubectl apply -f grpc-server.yaml
kubectl wait --for=condition=ready pod -l app=grpc-service -n aic --timeout=120sForward the upstream port to your local machine and verify the gRPC services are available:
kubectl port-forward -n aic "svc/grpc-service" "${UPSTREAM_GRPC_PORT}:${UPSTREAM_GRPC_PORT}" &grpcurl -plaintext "127.0.0.1:${UPSTREAM_GRPC_PORT}" listExpected output:
grpc.reflection.v1alpha.ServerReflection
helloworld.Greeter
helloworld.TestImportList the methods of helloworld.Greeter:
grpcurl -plaintext "127.0.0.1:${UPSTREAM_GRPC_PORT}" list "${GRPC_SERVICE}"Expected output includes helloworld.Greeter.SayHello.
Step 2: Create the gRPC route
Create a manifest for a GRPCRoute that routes SayHello to the gRPC service:
apiVersion: gateway.networking.k8s.io/v1
kind: GRPCRoute
metadata:
namespace: aic
name: grpc-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- method:
service: helloworld.Greeter
method: SayHello
backendRefs:
- name: grpc-service
port: 50051Create a manifest that sets the upstream scheme to grpc and routes to the gRPC service:
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: grpc-service
spec:
ingressClassName: apisix
scheme: grpc
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: grpc-route
spec:
ingressClassName: apisix
http:
- name: helloworld-greeter
match:
paths:
- /helloworld.Greeter/SayHello
methods:
- GET
- POST
backends:
- serviceName: grpc-service
servicePort: 50051Apply the manifest:
kubectl apply -f grpc-route.yamlStep 3: Enable HTTP/2 on the gateway
By default, the gateway supports TLS-encrypted HTTP/2 on port 9443. For non-encrypted HTTP/2, add an extra port to the gateway configuration.
Export the current Helm values:
helm get values -n aic apisix --all > values.yamlIn values.yaml, add 9081 as an additional HTTP/2 port:
service:
http:
containerPort: 9080
enabled: true
servicePort: 80
additionalContainerPorts:
- port: 9081
enable_http2: trueUpgrade the release:
helm upgrade -n aic apisix apisix/apisix -f values.yamlExport the current Helm values:
helm get values -n aic api7-ee-3-gateway --all > values.yamlIn values.yaml, add 9081 as an additional HTTP/2 port:
gateway:
http:
enabled: true
ip: 0.0.0.0
servicePort: 80
containerPort: 9080
additionalContainerPorts:
- port: 9081
enable_http2: trueUpgrade the release:
helm upgrade --install -n aic api7-ee-3-gateway api7/gateway -f values.yamlValidate
Forward the gateway HTTP/2 port to your local machine:
kubectl port-forward -n aic "svc/${GATEWAY_SERVICE_NAME}" "${FORWARD_PORT}:${GATEWAY_H2_PORT}" &Send a gRPC request to the route using helloworld.proto:
grpcurl -plaintext \
-proto "${PROTO_FILE}" \
-d "${GRPC_REQUEST}" \
"127.0.0.1:${FORWARD_PORT}" \
"${GRPC_METHOD}"Expected output:
{
"message": "Hello World"
}Roll back / Clean up
Delete the manifests created in this guide:
kubectl delete -f grpc-route.yaml
kubectl delete -f grpc-server.yamlStop the local port-forward processes if they are still running:
kill %1 2>/dev/null || trueTo remove the additional HTTP/2 port from the gateway, re-run the Helm upgrade without the additionalContainerPorts entry, or re-apply the original values file.
Troubleshoot
| Symptom | Cause | Fix |
|---|---|---|
grpcurl cannot list the upstream services. | The gRPC Pod is not ready or the upstream port-forward is not running. | Verify the Pod status and that UPSTREAM_GRPC_PORT is forwarded. |
grpcurl returns Unavailable for the gateway route. | The route is not accepted, or HTTP/2 is not enabled on the gateway port. | Check the GRPCRoute/ApisixRoute status, confirm enable_http2: true on GATEWAY_H2_PORT, and verify the port-forward targets GATEWAY_SERVICE_NAME. |
| The gateway responds with plain HTTP instead of gRPC. | The gateway listener is using HTTP/1.1, or the client did not use plaintext HTTP/2. | Confirm additionalContainerPorts for GATEWAY_H2_PORT sets enable_http2: true and use grpcurl -plaintext with the local FORWARD_PORT. |