Search code examples
google-cloud-platformgoogle-cloud-endpointsgoogle-kubernetes-engine

How to configure endpoints and esp to publish gRPC with enabled ServerReflection feature


I created a simple gRPC API service, published it using GKE-ESP-endpoints. It works. Now I would like to publish the service with ServerReflection feature. Reflection has been added into the gRPC server and when some grpc client, for instance grpcurl, directly sends list request to the server, the server returns the correct answer with the list of accessible gRPC services:

$ grpcurl --plaintext localhost:8000 list
grservices.diagnostic

When the same request is sent to public ip of load-balancer the answer is Failed to list services: rpc error: code = NotFound desc = Method does not exist.

Logs of esp:

"POST /grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo HTTP/2.0" 404 0 "-" "grpc-go/1.14.0-dev"

Logs of endpoints:

Endpoints management skipped for an unrecognized HTTP call: POST /grpc.reflection.v1alpha.ServerReflection/ServerReflectionInfo

For me it looks the reason is in because endpoints don't know about grpc.reflection.v1alpha.ServerReflection service and don't allow routing the request to gRPC container. I reviewed all examples that I can googled and didn't see any changes between api-config.yaml files for gRPC with enabled ServerReflection and without ServerReflection.

I have tried to change api_config.yaml and apply it for the deployment with no success unfortunately, because I should have descriptor {{.pb}} file for {{grpc.reflection.v1alpha.ServerReflection}}.

So my question is how to configure endpoints and esp to provide reflection?

Thanks a lot for any ideas and proposals.

api_config.yaml:

type: google.api.Service
config_version: 3

#
# Name of the service configuration.
#
name: diagnostic.endpoints.[id-project].cloud.goog

#
# API title to appear in the user interface (Google Cloud Console).
#
title: diagnostic gRPC API
apis:
- name: grservices.diagnostic
# -name: grpc.reflection.v1alpha.ServerReflection

#
# API usage restrictions.
#
#usage:
#  rules:
#  # Diagnostic methods can be called without an API Key.
#  - selector: grservices.diagnostic.GetDateTime
#    allow_unregistered_calls: true
#
#  - selector: grservices.diagnostic.GetTimeZones
#    allow_unregistered_calls: true
#
##  - selector: grpc.reflection.v1alpha.ServerReflection.ServerReflectionInfo
##    allow_unregistered_calls: true

usage:
  rules:
  # Allow unregistered calls for all methods.
  - selector: "*"
    allow_unregistered_calls: true

Solution

  • The solution is quite simple. I just downloaded reflection.proto and compiled the new .pb file using reflection.proto and my own proto file of my services:

    wget https://raw.githubusercontent.com/grpc/grpc/master/src/proto/grpc/reflection/v1alpha/reflection.proto
    
    python -m grpc.tools.protoc --include_imports --include_source_info --proto_path=.  --proto_path="../googleapis" --python_out=. --grpc_python_out=. --descriptor_set_out=api_descriptor.pb reflection.proto diagnostic.proto
    
    # delete _pb2.py files of reflection. The files are already presented in virtenv as the part of grpcio-reflection package
    rm reflection_pb2.py
    rm reflection_pb2_gprc.py
    
    # upload the new config to endpoints
    gcloud endpoints services deploy api_descriptor.pb api_config.yaml
    

    Testing:

    $ grpcurl -insecure ${EXT_IP}:443 list                      
    grservices.diagnostic
    
    $ grpcurl -insecure ${EXT_IP}:443 list grservices.diagnostic
    GetDateTime
    GetTimeZones
    
    grpcurl -insecure ${EXT_IP}:443 grservices.diagnostic.GetDateTime
    {
      "datetime": "2018-07-23 17:21:16"
    }
    
    $ grpcurl -insecure ${EXT_IP}:443 grservices.diagnostic/GetdateTime
    
    $ grpcurl -d '{"time_zone": "Israel"}' -insecure ${EXT_IP}:443 grservices.diagnostic.GetDateTime
    {
      "datetime": "2018-07-23 20:25:41Z+0300"
    }
    

    The changed part of api_config.yaml file:

    apis:
    - name: grservices.diagnostic
    - name: grpc.reflection.v1alpha.ServerReflection