Google Cloud ESP gRPC transcoding with Kubernetes backend

12/23/2017

I have a service with a gRPC interface that I would like clients to optionally call using JSON over HTTP. I decided to use Google Cloud Platform and its capability to transcode the HTTP request into a gRPC request. I decided to start with the Hello GRPC Java Example. I was able to successfully get a response when the backend is running via Docker on a Google Compute Engine instance with the following Docker run command:

docker run --detach --name=esp \
  --publish=8000:8000 \
  --publish=9000:9000 \
  --link=grpc-hello:grpc-hello \
  --service hellogrpc.endpoints.skypo-llc.cloud.goog \
  --version 2017-11-30r1 \
  --http_port=8000 \
  --http2_port=9000 \
  --backend=grpc://grpc-hello:50051
  gcr.io/endpoints-release/endpoints-runtime:1          

However, when I attempt to curl the same ESP and backend service deployed to Kubernetes, I get either binary output on port 8000 or a timeout on port 9000:

$ curl -v -d '{"name":"message"}' 
http://helloservice.com:8000/helloworld.Greeter/SayHello?key=REDACTED
.....
Warning: Binary output can mess up your terminal. Use "--output -" to tell 
Warning: curl to output it to your terminal anyway, or consider "--output 
Warning: <FILE>" to save to a file.
* Failed writing body (0 != 57)
* stopped the pause stream!
* Closing connection 0

Here is my Kubernetes config:

apiVersion: v1
kind: Service
metadata:
  name: grpc-hello
spec:
  ports:
  - port: 80
    targetPort: 9000
    protocol: TCP
    name: http
  selector:
    app: grpc-hello
  type: LoadBalancer
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: grpc-hello
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: grpc-hello
    spec:
      containers:
      - name: esp
        image: gcr.io/endpoints-release/endpoints-runtime:1
        args: [
        "--http_port", "8000",
        "--http2_port", "9000",
        "--backend", "grpc://127.0.0.1:50051",
        "--service", "hellogrpc.endpoints.skypo-llc.cloud.goog",
        "--version", "2017-12-22r0",
        ]                                                                                                                                                                                                                                                                  
        ports:
          - containerPort: 9000
            containerPort: 8000
      - name: java-grpc-hello
        image: gcr.io/skypo-llc/java-grpc-hello:1.0
        ports:
          - containerPort: 50051

And my Dockerfile:

FROM gcr.io/google_appengine/openjdk8

RUN apt-get update \
    && apt-get -y -q upgrade \
    && rm -rf /var/lib/apt/lists/*

ADD ./server/build/libs/server.jar /hello/server.jar

EXPOSE 8000
EXPOSE 9000

ENTRYPOINT ["java", "-jar", "/hello/server.jar"]
-- frank
google-cloud-endpoints
java
kubernetes

1 Answer

12/30/2017

The solution was to add port 8000 to the Kubernetes Service section:

  - port: 8000
    targetPort: 8000
    protocol: TCP
    name: http2

So, the entire Service section is now:

apiVersion: v1
kind: Service
metadata:
  name: grpc-hello
spec:
  ports:
  - port: 80
    targetPort: 9000
    protocol: TCP
    name: http
  - port: 8000
    targetPort: 8000
    protocol: TCP
    name: http2
  selector:
    app: grpc-hello
  type: LoadBalancer
-- frank
Source: StackOverflow