Walkthrough configuring Apigee for gRPC on Cloud Run

This article provides step-by-step instructions on configuring a gRPC backend on Cloud Run and an Apigee X Proxy by updating an existing Envoy based Load Balancer. We'll show how to create unique URLs / routing urls on the GCP Load Balancer that will only work for gRPC / http2 services. This walkthrough compliments the instructions published here:
https://cloud.google.com/apigee/docs/api-platform/fundamentals/build-simple-api-proxy#creating-grpc-...

All the commands / instructions should be run in a GCP Cloud Shell (https://shell.cloud.google.com) session in the GCP project where Apigee is installed.

Create gRPC backend on Cloud Run

We'll use Docker containers and Cloud Run for the gRPC backend

  1. In Cloud Shell, clone the gRPC repo 
    export PROJECT=$GOOGLE_CLOUD_PROJECT
    mkdir grpc-backend
    cd grpc-backend
    git clone https://github.com/grpc/grpc.git
    cd $HOME/grpc-backend/grpc/examples/python/helloworld
  2. Create Dockerfile for the Hello World example
    touch Dockerfile
    cloudshell edit Dockerfile​
  3. Add the following code to the Dockerfile
    FROM python:3.7
    WORKDIR /app
    COPY . .
    RUN pip install grpcio protobuf
    EXPOSE 50051
    CMD ["python", "greeter_server.py"]

  4. Build the Docker image and then list the images created
    docker build .
    docker images -a

    teodlh_1-1694549059407.png

  5. Save the imageid from above to an environment variable and run the Docker image locally
    export DOCKER_IMAGE=<imageid>
    docker run -p 8080:50051 -it $DOCKER_IMAGE​
  6. Use grpcurl to ensure the service is working. grpcurl expects to send Service.Method to gRPC endpoints and validates that against the proto file. If you look at the protofile referenced, you’ll see that the package keyword is used to specify the package name for the service. The package name is used to uniquely identify the service.  In this case, the fully qualified name of the service is helloworld.Greeter
    grpcurl -plaintext -import-path $HOME/grpc-backend/grpc/examples/protos \
    -proto helloworld.proto -d '{"name":"Guest"}' \
    localhost:8080 helloworld.Greeter/SayHello
  7. If you get a response like the one below, the Docker image is working!
    teodlh_2-1694549059414.png
  8. Once the image is working, create an global Artifact Registry and configure Docker to use the Artifact Registry
    gcloud artifacts repositories create grpcdemo \
        --repository-format=Docker \
        --location=us \
        --description="gRPC Demo repo"
    gcloud auth configure-docker us-docker.pkg.dev​
  9. Tag the Docker image, Push the Docker image, and create a Cloud Run service from the Docker image. Optional: Change REGION= to a region closest to your Apigee instance
    export REGION=us-east1
    docker tag $DOCKER_IMAGE us-docker.pkg.dev/$PROJECT/grpcdemo/my-grpc-service
    docker push us-docker.pkg.dev/$PROJECT/grpcdemo/my-grpc-service
    gcloud run deploy my-grpc-service \
    --image us-docker.pkg.dev/$PROJECT/grpcdemo/my-grpc-service \
    --platform managed --use-http2 --allow-unauthenticated \
    --region $REGION --port 50051
  10. Once the deployment completes, grab the service URL (omitting https://) and update the command below to test your gRPC backend
teodlh_3-1694549059439.png
grpcurl -import-path $HOME/grpc-backend/grpc/examples/protos -proto helloworld.proto \
-d '{"name":"Guest"}' <serviceurl>:443 helloworld.Greeter/SayHello

If you get a successful response you’re ready to update the GCP LB to support gRPC!

teodlh_4-1694549059415.png

Update Load Balancer

For this step, we’ll create a unique path for gRPC traffic. We'll use a unique ssl certificate and a route rule for the domain name using the nip.io service. This assumes that your backend is using a PSC NEG connected to Apigee.  If you’re using MIGs, you can follow the public documentation for these steps.

  1. Identify the IP and forwarding rule of your load balancer
    gcloud compute forwarding-rules list​

    teodlh_5-1694549059415.png

  2. Create environment variables from the output above
    export FORWARDING_RULE=<NAME from above>
    export IP_ADDRESS=<IP_ADDRESS from above>
    export TARGET_PROXY=<TARGET from above>​
  3.  Identify the URL Map and SSL certificate names by getting the details of the Target Proxy
    gcloud compute target-https-proxies describe $TARGET_PROXY​

    teodlh_0-1694563908890.png

  4. Use the output to create environment variables for use later
    export URL_MAP=<url map name from above>
    export SSL_CERT=<certificate name from above>​
  5. Identify your current SSL certificate domain names
    gcloud compute ssl-certificates describe $SSL_CERT  --format json | jq .managed.domains​

    teodlh_7-1694549059434.png

  6. Create a new certificate that includes grpc specific nip.io dns name. Adding your existing domain names is not required.
    export DOMAINS="<existing domain name>","grpc.$IP_ADDRESS.nip.io"
    gcloud compute ssl-certificates create apigee-ssl-grpc \
           --domains $DOMAINS​
  7. Update the target proxy to use the new certificate
    gcloud compute target-https-proxies update $TARGET_PROXY \
    --ssl-certificates apigee-ssl-grpc​
  8.  Create a Backend service that supports HTTP2
    gcloud compute backend-services create apigee-grpc \
      --load-balancing-scheme=EXTERNAL_MANAGED \
      --protocol=HTTP2 \
      --global --project=$PROJECT​
  9. Find the name of the Apigee NEG
    gcloud compute network-endpoint-groups list​

    teodlh_8-1694549059451.png

  10.  
  11. Add the backend service to the Apigee (NEG)
    export APIGEE_NEG=<NAME from above>
    gcloud compute backend-services add-backend apigee-grpc \
      --network-endpoint-group=$APIGEE_NEG \
      --network-endpoint-group-region=<LOCATION from above> \
      --global --project=$PROJECT​
  12. Edit the URL map
    gcloud compute url-maps edit $URL_MAP​
  13. Edit the values for <IP-ADDRESS> and <PROJECT_ID> below and paste them under the defaultService so it matches the screenshot. Do not modify / remove defaultService as it will break any existing routing rules. Note that you’re in vi so press ‘i’ to begin insert mode. When you’re done type “:” to enter command mode and type wq to write and quit  (:wq to save and exit).
    defaultService:<DO NOT REMOVE/MODIFY THE ORIGINAL OUTPUT. COPY AND PASTE ONLY THE hostRules THE BELOW>
    hostRules:
    - hosts:
      - grpc.<IP-ADDRESS>.nip.io
      pathMatcher: grpc-domain
    name: apigee-lb
    pathMatchers:
    - defaultService: https://www.googleapis.com/compute/v1/projects/<PROJECT_ID>/global/backendServices/apigee-grpc
      name: grpc-domain

    teodlh_1-1694564375621.png

Create API Proxy

  1. Update your environment group to support grpc.<IP Address>.nip.io
    teodlh_10-1694549059410.png
  2. In the GCP Cloud Console, create a Target Server that uses the gRPC Protocol. Note: you must use the GCP console and not the classic Apigee admin console. Choose gRPC - Target preview for the protocol
    teodlh_11-1694549059428.png
  3. Create a Reverse proxy and use a fictitious Target.  For the Base path, specify the service name/method from the proto file the API clients use
    teodlh_12-1694549059441.png
  4. Edit the proxy and change the Target Endpoint configuration using the code below. Save and Deploy.
    <TargetEndpoint name="default">
      <Description/>
      <FaultRules/>
      <HTTPTargetConnection>
        <LoadBalancer>
          <Server name="grpc-server"/>
        </LoadBalancer>
        <Path>/helloworld.Greeter/SayHello</Path>
      </HTTPTargetConnection>
    </TargetEndpoint>​
  5. Test by updating the command below to include the grpc domain name created earlier
grpcurl -import-path $HOME/grpc-backend/grpc/examples/protos -proto helloworld.proto -d '{"name":"Guest"}'grpc.<IP Address>.nip.io:443 helloworld.Greeter/SayHello​

Optional: Add a verify API Key policy

  1. Add a Verify API Key policy that looks at headers for the API Key 
    <VerifyAPIKey continueOnError="false" enabled="true" name="VA-VerifyKey">
      <DisplayName>VA-VerifyKey</DisplayName>
      <Properties/>
      <APIKey ref="request.header.apikey"/>
    </VerifyAPIKey>​
  2. Create a product that specifies the supported gRPC Service Name and Methods. Note: gRPC proxies require that they exist in their own products. gRPC proxies that are combine with REST or GraphQL proxies will not respond.
    teodlh_1-1694617900617.png
  3. Create an app registration that is only subscribed to the gRPC product. The app registration must not contain any non-gRPC products or the gRPC proxy will not work.
    teodlh_3-1694617978978.png

     


  4. Test by passing the apikey as a header
    grpcurl -import-path $HOME/grpc/examples/protos -proto helloworld.proto -H "apikey":"<api key>"  -d '{"name":"Guest"}' grpc.<IP Address>nip.io:443 helloworld.Greeter/SayHello
Contributors
Version history
Last update:
‎09-14-2023 12:06 PM
Updated by: