Streaming gRPC on GKE with Gateway API
Steps to deploy gRPC server streaming service running on GKE behind Google's Global External Application Load Balancer using the Gateway API, Google-managed certificate and Envoy proxy for TLS termination at the backends.
Prerequisites
These steps expect GKE cluster with a Gateway Controller 1 and internet
access (to download the prebuilt container image). Also the usual gcloud
CLI
configured for your project and kubectl
with credentials to your cluster.
You'll also need working DNS subdomain to point to the load balancer IP.
Setup Steps
-
Create static IP
$ gcloud compute addresses create grpcdemo-vip \ --ip-version=IPV4 \ --global
-
Point the public DNS to the previously created global IP (I'll be using
grpcdemo.example.com
) -
Create Google-managed SSL certificate
$ gcloud compute ssl-certificates create grpcdemo-cert \ --domains=grpcdemo.example.com \ --global
-
Generate self-signed certificate for the backend
$ openssl ecparam -genkey -name prime256v1 -noout -out key.pem $ openssl req -x509 -new -key key.pem -out cert.pem -days 3650 -subj '/CN=internal'
TLS is required both between client and GFE, as well as GFE and backend 2.
Important: The certificate has to use one of supported signatures compatible with BoringSSL, see 34 for more details.
-
Create K8S Secret with the self-signed cert
$ kubectl create secret tls grpcdemo-tls \ --cert=cert.pem \ --key=key.pem
-
Create K8S Configmap with Envoy config
$ kubectl create configmap envoy-config --from-file=envoy.yaml
-
Deploy grpcdemo app
$ kubectl apply -f manifests/deploy-grpcdemo.yaml
We're using the Cloud Run gRPC Server Streaming sample application5 which listens on port 8080. The Envoy then listens on port 8443 with self-signed certificate.
-
Deploy grpcdemo svc
$ kubectl apply -f manifests/svc-grpcdemo.yaml
-
Deploy grpcdemo gke-l7-gxlb gateway
$ kubectl apply -f manifests/gateway-grpcdemo.yaml
-
Deploy grpcdemo HealthCheckPolicy
$ kubectl apply -f manifests/httproute-health.yaml
-
Deploy grpcdemo HTTPRoute
$ kubectl apply -f manifests/httproute-grpcdemo.yaml
Don't forget to change the DNS in the manifest.
-
Test
Clone the repository 5 and build the client:
$ git clone https://github.com/GoogleCloudPlatform/golang-samples $ cd golang-samples/run/grpc-server-streaming $ go build -o cli ./client
And run the client:
$ ./cli -server grpcdemo.example.com:443 rpc established to timeserver, starting to stream received message: current_timestamp: 2023-10-24T19:15:32Z received message: current_timestamp: 2023-10-24T19:15:33Z received message: current_timestamp: 2023-10-24T19:15:34Z ...
Footnotes
-
https://cloud.google.com/kubernetes-engine/docs/concepts/gateway-api ↩
-
https://cloud.google.com/load-balancing/docs/https#using_grpc_with_your_applications ↩
-
https://groups.google.com/a/chromium.org/forum/#!msg/blink-dev/kWwLfeIQIBM/9chGZ40TCQAJ ↩
-
https://github.com/GoogleCloudPlatform/golang-samples/tree/main/run/grpc-server-streaming ↩ ↩2