Set up Cloud Endpoints gRPC for Cloud Run with ESPv2

This page shows you how to set up Cloud Endpoints for Cloud Run with a gRPC backend. Endpoints uses the Extensible Service Proxy V2 (ESPv2) as an API gateway. To provide API management for Cloud Run, you deploy the prebuilt ESPv2 container to Cloud Run. You then help secure your services by using Cloud Run IAM so that ESPv2 can invoke them.

With this set up, ESPv2 intercepts all requests to your services and performs any necessary checks (such as authentication) before invoking the service. When the service responds, ESPv2 gathers and reports telemetry, as shown in the figure below. You can view metrics for your service on the Endpoints > Services page in the Google Cloud console.

Endpoints architecture

For an overview of Cloud Endpoints, see About Endpoints and Endpoints architecture.

Migrating to ESPv2

Previous releases of Cloud Endpoints did not support gRPC on Cloud Run with ESP. To use this feature, migrate to Extensible Service Proxy V2.

Task List

Use the following task list as you work through the tutorial. All tasks are required to complete this tutorial.

  1. Create a Google Cloud project, and if you haven't deployed your own Cloud Run, deploy a sample backend gRPC service. See Before you begin.
  2. Reserve a Cloud Run hostname for the ESPv2 service. See Reserving a Cloud Run hostname.
  3. Create a gRPC API configuration document that describes your API, and configure the routes to your Cloud Run. See Configuring Endpoints.
  4. Deploy the gRPC API configuration document to create a managed service. See Deploying the Endpoints configuration.
  5. Build a new ESPv2 Docker image with your Endpoints service configuration. See Building a new ESPv2 image.
  6. Deploy the ESPv2 container onto Cloud Run. Then grant ESPv2 the Identity and Access Management (IAM) permission to invoke your service. See Deploying the ESPv2 container.
  7. Invoke a service. See Sending a request to the API.
  8. Track activity to your services. See Tracking API activity.
  9. Avoid incurring charges to your Google Cloud account. See Clean up.

Costs

In this document, you use the following billable components of Google Cloud:

To generate a cost estimate based on your projected usage, use the pricing calculator. New Google Cloud users might be eligible for a free trial.

When you finish the tasks that are described in this document, you can avoid continued billing by deleting the resources that you created. For more information, see Clean up.

Before you begin

To get set up:

  1. In the Google Cloud console, go to the Manage resources page and create a project.

    Go to the Manage resources page

  2. Make sure that billing is enabled for your project.

    Learn how to enable billing

  3. Make a note of the project ID because it is needed later. On the rest of this page, this project ID is referred to as ESP_PROJECT_ID.

  4. Make a note of the project number because it is needed later. On the rest of this page, this project number is referred to as ESP_PROJECT_NUMBER.

  5. Download and install the Google Cloud CLI.

    Download the gcloud CLI

  6. Follow the steps in the gRPC Python quickstart to install gRPC and the gRPC tools.

  7. Deploy the python-grpc-bookstore-server example backend gRPC Cloud Run service for use with this tutorial. The gRPC service uses the following container image:

    gcr.io/endpointsv2/python-grpc-bookstore-server:2

    Follow the steps in Quickstart: Deploy a Prebuilt Sample Container to deploy the service. Make sure to replace the container image specified in that quickstart with gcr.io/endpointsv2/python-grpc-bookstore-server:2

    Note of the region and project ID where your service is deployed. On the rest of this page, this project ID is referred to as BACKEND_PROJECT_ID. The name of the deployed Cloud Run service is referred to as BACKEND_SERVICE_NAME. Its Cloud Run host name is referred to as BACKEND_HOST_NAME.

Reserving a Cloud Run hostname

You must reserve a Cloud Run hostname for the ESPv2 service in order to configure the OpenAPI document or gRPC service configuration. To reserve a hostname, you will deploy a sample container to Cloud Run. Later, you will deploy the ESPv2 container onto the same Cloud Run service.

  1. Make sure that gcloud CLI is authorized to access your data and services.
    1. Log in.
      gcloud auth login
    2. On the new browser tab that opens, choose an account that has the Editor or Owner role in the Google Cloud project that you created for deploying ESPv2 to Cloud Run.
  2. Set the region.
    gcloud config set run/region us-central1
  3. Deploy the sample image gcr.io/cloudrun/hello to Cloud Run. Replace CLOUD_RUN_SERVICE_NAME with the name that you want to use for the service.
    gcloud run deploy CLOUD_RUN_SERVICE_NAME \
        --image="gcr.io/cloudrun/hello" \
        --allow-unauthenticated \
        --platform managed \
        --project=ESP_PROJECT_ID
    

    On successful completion, the command displays a message similar to the following:

    Service [CLOUD_RUN_SERVICE_NAME] revision [CLOUD_RUN_SERVICE_NAME-REVISION_NUM] has been deployed and is serving traffic at CLOUD_RUN_SERVICE_URL

    For example, if you set CLOUD_RUN_SERVICE_NAME to gateway:

    Service [gateway] revision [gateway-00001] has been deployed and is serving traffic at https://gateway-12345-uc.a.run.app

    In this example, https://gateway-12345-uc.a.run.app is the CLOUD_RUN_SERVICE_URL and gateway-12345-uc.a.run.app is the CLOUD_RUN_HOSTNAME.

  4. Make a note of CLOUD_RUN_SERVICE_NAME and CLOUD_RUN_HOSTNAME. You later deploy ESPv2 onto the CLOUD_RUN_SERVICE_NAME Cloud Run service. You specify CLOUD_RUN_HOSTNAME in the host field of your OpenAPI document.

Configuring Endpoints

The bookstore-grpc sample contains the files that you need to copy locally and configure.

  1. Create a self-contained protobuf descriptor file from your service .proto file:
    1. Save a copy of bookstore.proto from the example repository to your current working directory. This file defines the Bookstore service's API.
    2. Create the following directory under your working directory: mkdir generated_pb2
    3. Create the descriptor file, api_descriptor.pb, by using the protoc protocol buffers compiler. Run the following command in the directory where you saved bookstore.proto:
      python3 -m grpc_tools.protoc \
          --include_imports \
          --include_source_info \
          --proto_path=. \
          --descriptor_set_out=api_descriptor.pb \
          --python_out=generated_pb2 \
          --grpc_python_out=generated_pb2 \
          bookstore.proto

      In the preceding command, --proto_path is set to the current working directory. In your gRPC build environment, if you use a different directory for .proto input files, change --proto_path so the compiler searches the directory where you saved bookstore.proto.

  2. Create a text file called api_config.yaml in your current working directory (the same directory that contains bookstore.proto). For convenience, this page refers to the gRPC API configuration document by that file name, but you can name it something else if you prefer. Add the following contents to the file:
    # The configuration schema is defined by the service.proto file.
    # https://github.com/googleapis/googleapis/blob/master/google/api/service.proto
    
    type: google.api.Service
    config_version: 3
    name: CLOUD_RUN_HOSTNAME
    title: Cloud Endpoints + Cloud Run gRPC
    apis:
      - name: endpoints.examples.bookstore.Bookstore
    usage:
      rules:
      # ListShelves methods can be called without an API Key.
      - selector: endpoints.examples.bookstore.Bookstore.ListShelves
        allow_unregistered_calls: true
    backend:
      rules:
        - selector: "*"
          address: grpcs://BACKEND_HOST_NAME
    
    Indentation is important for yaml format. For example the name field must be at the same level as type.
  3. In the name field, specify CLOUD_RUN_HOSTNAME, the hostname portion of the URL that was reserved above in Reserving a Cloud Run hostname. Don't include the protocol identifier, such as https:// or grpcs://.

  4. In the address field in the backend.rules section, replace BACKEND_HOST_NAME with the actual gRPC Bookstore Cloud Run service created in Before you begin.

  5. Note the value of the title property in the api_config.yaml file:

    title: Cloud Endpoints + Cloud Run gRPC

    The value of the title property becomes the name of the Endpoints service after you deploy the configuration.

  6. Save your gRPC API configuration document.

See Configuring Endpoints for more information.

Deploying the Endpoints configuration

To deploy the Endpoints configuration, you use the gcloud endpoints services deploy command. This command uses Service Management to create a managed service.

  1. Make sure you are in the directory where the api_descriptor.pb and api_config.yaml files are located.
  2. Confirm that the default project that the gcloud command-line tool is currently using is the Google Cloud project that you want to deploy the Endpoints configuration to. Validate the project ID returned from the following command to make sure that the service doesn't get created in the wrong project.
    gcloud config list project
    

    If you need to change the default project, run the following command:

    gcloud config set project YOUR_PROJECT_ID
    
  3. Deploy the proto descriptor file and the configuration file by using the Google Cloud CLI:
    gcloud endpoints services deploy api_descriptor.pb api_config.yaml
    

    As it is creating and configuring the service, Service Management outputs information to the terminal. When the deployment completes, a message similar to the following is displayed:

    Service Configuration [CONFIG_ID] uploaded for service [bookstore.endpoints.example-project.cloud.goog]

    CONFIG_ID is the unique Endpoints service configuration ID created by the deployment. For example:

    Service Configuration [2017-02-13r0] uploaded for service [bookstore.endpoints.example-project.cloud.goog]
    

    In the previous example, 2017-02-13r0 is the service configuration ID and bookstore.endpoints.example-project.cloud.goog is the service name. The service configuration ID consists of a date stamp followed by a revision number. If you deploy the Endpoints configuration again on the same day, the revision number is incremented in the service configuration ID.

Checking required services

At a minimum, Endpoints and ESP require the following Google services to be enabled:
Name Title
servicemanagement.googleapis.com Service Management API
servicecontrol.googleapis.com Service Control API

In most cases, the gcloud endpoints services deploy command enables these required services. However, the gcloud command completes successfully but doesn't enable the required services in the following circumstances:

  • If you used a third-party application such as Terraform, and you don't include these services.

  • You deployed the Endpoints configuration to an existing Google Cloud project in which these services were explicitly disabled.

Use the following command to confirm that the required services are enabled:

gcloud services list

If you do not see the required services listed, enable them:

gcloud services enable servicemanagement.googleapis.com
gcloud services enable servicecontrol.googleapis.com

Also enable your Endpoints service:

gcloud services enable ENDPOINTS_SERVICE_NAME

To determine the ENDPOINTS_SERVICE_NAME you can either:

  • After deploying the Endpoints configuration, go to the Endpoints page in the Cloud console. The list of possible ENDPOINTS_SERVICE_NAME are shown under the Service name column.

  • For OpenAPI, the ENDPOINTS_SERVICE_NAME is what you specified in the host field of your OpenAPI spec. For gRPC, the ENDPOINTS_SERVICE_NAME is what you specified in the name field of your gRPC Endpoints configuration.

For more information about the gcloud commands, see gcloud services.

If you get an error message, see Troubleshooting Endpoints configuration deployment.

See Deploying the Endpoints configuration for additional information.

Building a new ESPv2 image

Build the Endpoints service config into a new ESPv2 docker image. You will later deploy this image onto the reserved Cloud Run service.

To build the service config into a new ESPv2 docker image:

  1. Download this script to your local machine where the gcloud CLI is installed.

  2. Run the script with the following command:

    chmod +x gcloud_build_image
    
    ./gcloud_build_image -s CLOUD_RUN_HOSTNAME \
        -c CONFIG_ID -p ESP_PROJECT_ID

    For CLOUD_RUN_HOSTNAME, specify the hostname of the URL that you reserved above in Reserving a Cloud Run hostname. Don't include the protocol identifier, https://.

    For example:

    chmod +x gcloud_build_image
    
    ./gcloud_build_image -s gateway-12345-uc.a.run.app \
        -c 2019-02-01r0 -p your-project-id
  3. The script uses the gcloud command to download the service config, build the service config into a new ESPv2 image, and upload the new image to your project container registry. The script automatically uses the latest release of ESPv2, denoted by the ESP_VERSION in the output image name. The output image is uploaded to:

    gcr.io/ESP_PROJECT_ID/endpoints-runtime-serverless:ESP_VERSION-CLOUD_RUN_HOSTNAME-CONFIG_ID

    For example:

    gcr.io/your-project-id/endpoints-runtime-serverless:2.14.0-gateway-12345-uc.a.run.app-2019-02-01r0"

Deploying the ESPv2 container

  1. Deploy the ESPv2 Cloud Run service with the new image you built above. Replace CLOUD_RUN_SERVICE_NAME with the same Cloud Run service name you used when you originally reserved the hostname above in Reserving a Cloud Run hostname:

    gcloud run deploy CLOUD_RUN_SERVICE_NAME \
      --image="gcr.io/ESP_PROJECT_ID/endpoints-runtime-serverless:ESP_VERSION-CLOUD_RUN_HOSTNAME-CONFIG_ID" \
      --allow-unauthenticated \
      --platform managed \
      --project=ESP_PROJECT_ID
  2. If you want to configure Endpoints to use additional ESPv2 startup options, such as enabling CORS, you can pass the arguments in the ESPv2_ARGS environment variable:

    gcloud run deploy CLOUD_RUN_SERVICE_NAME \
      --image="gcr.io/ESP_PROJECT_ID/endpoints-runtime-serverless:ESP_VERSION-CLOUD_RUN_HOSTNAME-CONFIG_ID" \
      --set-env-vars=ESPv2_ARGS=--cors_preset=basic \
      --allow-unauthenticated \
      --platform managed \
      --project ESP_PROJECT_ID

    For more information and examples on setting the ESPv2_ARGS environment variable, including the list of available options and information on how to specify multiple options, see Extensible Service Proxy V2 flags.

  3. Grant ESPv2 permission to invoke your Cloud Run services. Run the following command for each service. In the following command:
    • Replace BACKEND_SERVICE_NAME with the name of the Cloud Run service being invoked. If you are using the service created by deploying `gcr.io/endpointsv2/python-grpc-bookstore-server:2`, then use python-grpc-bookstore-server as this value.
    • Replace ESP_PROJECT_NUMBER with the project number of the project that you created for ESPv2. One way to find this is to go to the IAM page in the Google Cloud console and find the Default compute service account, which is the service account used in the `member` flag.
    gcloud run services add-iam-policy-binding BACKEND_SERVICE_NAME \
      --member "serviceAccount:ESP_PROJECT_NUMBER-compute@developer.gserviceaccount.com" \
      --role "roles/run.invoker" \
      --platform managed \
      --project BACKEND_PROJECT_ID

For more information, see Managing access using IAM.

Sending requests to the API

To send requests to the sample API, you can use a sample gRPC client written in Python.

  1. Clone the git repo where the gRPC client code is hosted:

    git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
  2. Change your working directory:

    cd python-docs-samples/endpoints/bookstore-grpc/
  3. Install dependencies:

    pip3 install virtualenv
    virtualenv env
    source env/bin/activate
    pip3 install -r requirements.txt
  4. Send a request to the sample API:

    python3 bookstore_client.py --host CLOUD_RUN_HOSTNAME --port 443 --use_tls true

    Specify the hostname of your ESPv2 Cloud Run service in CLOUD_RUN_HOSTNAME, without the protocol identifier. For example:

    python3 bookstore_client.py --host espv2-grpc-HASH-uc.a.run.app --port 443 --use_tls true

If you don't get a successful response, see Troubleshooting response errors.

You just deployed and tested an API in Endpoints!

Tracking API activity

  1. View the activity graphs for your API on the Endpoints > Service page in the Google Cloud console.

    View Endpoints activity graphs

    It may take a few moments for the request to be reflected in the graphs.

  2. Look at the request logs for your API on the Logs Explorer page.

    View Endpoints request logs

Creating a developer portal for the API

You can use Cloud Endpoints Portal to create a developer portal, a website that you can use to interact with the sample API. To learn more, see Cloud Endpoints Portal Overview.

Clean up

To avoid incurring charges to your Google Cloud account for the resources used on this page, follow these steps.

See Deleting an API and API instances for information on stopping the services used by this tutorial.

What's next