使用 ESPv2 为 Knative serving 设置 Cloud Endpoints gRPC

本页介绍了如何为 Knative serving 设置 Cloud Endpoints。Endpoints 使用 Extensible Service Proxy V2 (ESPv2) 作为 API 网关。如需为 Knative serving 提供 API 管理,请将预构建的 ESPv2 容器部署到 GKE 集群上运行的 Knative serving

如此设置之后,ESPv2 会拦截向您服务发出的所有请求,并在调用服务之前执行任何必要的检查(如身份验证)。当服务响应时,ESPv2 会收集并报告遥测数据。

如需大致了解 Endpoints,请参阅 Endpoints 简介Endpoints 架构

任务列表

学习本教程时,请使用以下任务列表。完成本教程所需的所有任务

  1. 创建一个 Google Cloud 项目,如果您尚未部署自己的 Knative serving,请部署示例服务。请参阅准备工作

  2. 创建 GKE 集群,并启用 Knative serving。

  3. 部署 gRPC 示例 Knative serving 服务。

  4. 创建描述 Endpoints API 的 gRPC API 配置文档,并配置到 Knative serving 服务的路由。请参阅配置 Endpoints

  5. 部署 gRPC API 配置文档以创建托管式服务。 请参阅部署 Endpoints 配置

  6. 使用您的 Endpoints 服务配置构建新的 ESPv2 Docker 映像。请参阅构建新的 ESPv2 映像

  7. 部署新的 ESPv2 Knative serving 映像。请参阅部署 ESPv2 Cloud Run 映像

  8. 创建到 ESPv2 Knative serving 服务的网域映射

  9. 通过向 API 发送请求来测试配置。

  10. 跟踪您的服务的活动。 请参阅跟踪 API 活动

  11. 清理.

费用

在本文档中,您将使用 Google Cloud 的以下收费组件:

您可使用价格计算器根据您的预计使用情况来估算费用。 Google Cloud 新用户可能有资格申请免费试用

完成本文档中描述的任务后,您可以通过删除所创建的资源来避免继续计费。如需了解详情,请参阅清理

准备工作

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  5. Make sure that billing is enabled for your Google Cloud project.

  6. 请记下项目 ID,您稍后需要用到它。在本页面的其余部分,此项目 ID 称为 ESP_PROJECT_ID
  7. 下载并安装 gcloud CLI

设置 gcloud 命令行

如需为 Knative serving for Anthos 设置 gcloud CLI,请执行以下操作:

  1. 确保 gcloud CLI 有权访问您的数据和服务。

    1. 登录。

      gcloud auth login

    2. 在打开的新浏览器标签页中,选择一个账号,该账号在您为将 ESPv2 部署到 Knative serving 而创建的 Google Cloud 项目中具有 EditorOwner 角色。

  2. 更新已安装的 gcloud 组件:

    gcloud components update
  3. 将平台设置为 gke 并将 gcloud 的默认项目设置为您刚创建的项目:

    gcloud config set run/platform gke 
    gcloud config set project ESP_PROJECT_ID

    ESP_PROJECT_ID 替换为您创建的项目的 ID。

  4. 为新集群设置所需的区域。您可以使用任何支持 GKE 的区域,例如:

    gcloud config set compute/zone ZONE

    ZONE 替换为您的区域。 例如,使用 us-central1-a。您可以使用 GKE 支持的任何区域。

  5. 为项目启用以下 API,需要使用它们来创建集群、构建容器以及将容器发布到 Google Container Registry:

    gcloud services enable container.googleapis.com containerregistry.googleapis.com cloudbuild.googleapis.com

创建启用了 Knative serving 的 GKE 集群

如需创建集群并为其启用 Knative serving on Google Cloud,请执行以下操作:

  1. 使用以下命令创建一个新集群:

    gcloud container clusters create CLUSTER_NAME \ 
      --addons=HttpLoadBalancing,CloudRun \ 
      --machine-type=n1-standard-4 \ 
      --num-nodes=3

    CLUSTER_NAME 替换为您想要使用的集群名称。

    虽然这些说明未启用集群自动扩缩功能来根据需求调整集群大小,但 Google Cloud 上的 Knative serving 会自动扩缩集群中的实例。

  2. 等待集群创建过程完成。在创建过程中,您应该会看到类似如下所示的消息:

    Creating cluster CLUSTER_NAME...done. 
    Created [https://container.googleapis.com/v1/projects/ESP_PROJECT_ID/zones/ZONE/clusters/CLUSTER_NAME].

    输出还会在输出的 NODE_VERSION 列下显示集群版本。例如 1.15.11-gke.11.14.10-gke.27。记下集群版本,以便稍后在本文档中使用。

  3. 设置 gcloud 默认值以使用新的集群和集群位置,从而避免在使用 gcloud CLI 时指定默认值:

    gcloud config set run/cluster CLUSTER_NAME
    gcloud config set run/cluster_location ZONE
  4. 使用以下命令查看有关新集群的详细信息:

    gcloud container clusters describe CLUSTER_NAME
  5. 使用以下命令为您的集群提取凭据:

    gcloud container clusters get-credentials CLUSTER_NAME

部署 gRPC Cloud Run 服务示例

如需将“grpc-bookstore”Cloud Run for Anthos 示例容器部署到刚创建的集群,请执行以下操作:

  1. 按照 gRPC Python 快速入门中的步骤安装 gRPC 和 gRPC 工具。

  2. 此 gRPC 服务器示例包含用于 Python“grpc-bookstore service”的预构建 Docker 映像:gcr.io/endpointsv2/python-grpc-bookstore-server:2。使用以下命令将“grpc-bookstore”部署到您的集群:

    gcloud run deploy GRPC_SERVICE \
      --image=gcr.io/endpointsv2/python-grpc-bookstore-server:2 \
      --platform=gke \
     --connectivity=internal \
      --use-http2

    请注意,您应将此指定为内部服务,以免外部访问该服务。

    GRPC_SERVICE 替换为您想要使用的服务名称。例如:

    gcloud run deploy grpc-bookstore \
      --image=gcr.io/endpointsv2/python-grpc-bookstore-server:2 \
      --platform=gke \
      --connectivity=internal \
      --use-http2

    完成后,系统会显示以下消息:

    Service [grpc-bookstore] revision [grpc-bookstore-00001-nuk] has been deployed and is serving 100 percent of traffic at http://grpc-bookstore.default.svc.cluster.local

    创建内部服务时,GKE 会创建一个 DNS 名称(在此示例中为 grpc-bookstore.default.svc.cluster.local),该 IP 名称只能解析从集群本身而不是从外部请求发出的请求。您无法从集群外部访问此 DNS。如需了解详情,请参阅 Cloud Run 服务

  3. 要验证您的服务是否正常运行,请将具有相同 Docker 映像的 pod 部署到集群。该映像包含“grpc-bookstore”的 gRPC 客户端代码,可用于测试内部服务。

    1. 使用以下 kubectl 命令将 pod 部署到上面部署的同一集群:

      kubectl run grpc --generator=run-pod/v1 \
        --image=gcr.io/endpointsv2/python-grpc-bookstore-server:2

      此映像包含 bookstore_client.py 脚本,可用于从集群内发出客户端请求。

      注意:对于较新版本的 kubectl,该命令可能会发出以下警告:

      Flag --generator has been deprecated, has no effect and will be removed in the future".

      您可以忽略该警告。

    2. 获取上一步部署 Docker 映像时在集群中创建的“grpc-bookstore”pod 的名称:

      kubectl get pods

      您会在表单中看到输出:

      NAME   READY    STATUS    RESTARTS   AGE
      grpc   1/1      Running   0          23h

      其中 grp 是“grpc-bookstore”pod 的名称。确保 Pod 的 Status 处于Running状态,然后再继续操作。

    3. 使用以下命令向“grpc-bookstore”服务发出客户端请求:

      kubectl exec grpc -ti -- python3 bookstore_client.py \
        --host grpc-bookstore.default.svc.cluster.local --port=80

      此命令会在集群内部运行 bookstore_client.py 脚本,以向主机名 grpc-bookstore.default.svc.cluster.local 上的“grpc-bookstore”服务发出 gRPC 请求。

      如果一切正常,您会看到以下形式的响应:

      ListShelves: shelves {
        id: 1
        theme: "Fiction"
      }
      shelves {
        id: 2
        theme: "Fantasy"
      }

配置 Endpoints

您必须具有描述后端服务的表面和任何身份验证要求的 gRPC API 规范。

设置 gRPC API 规范的名称字段的简介

在 gRPC API 规范的 name 字段中,指定用于访问 Cloud Run for Anthos 服务的 Endpoints 服务名称。Endpoints 服务名称采用域名形式:

API_NAME.endpoints.ESP_PROJECT_ID.cloud.goog

由于 Endpoints 服务名称与域名对应,因此名称必须遵循以下规则:

  • 必须仅包含小写字母、数字、句点或短划线。
  • 不能以短划线开头。
  • 不得包含下划线。

例如:

grpc-boostore-api.endpoints.ESP_PROJECT_ID.cloud.goog

制定 gRPC API 规范

bookstore-grpc 示例包含需要在本地复制和配置的文件。

  1. 为 gRPC API 规范创建新目录,例如 my-anthos-grpc。然后使用 cd 转到该目录。

  2. 克隆将 gRPC 客户端代码托管到新目录的 git 代码库:

    git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
  3. 切换您的工作目录:

    cd python-docs-samples/endpoints/bookstore-grpc/

    请注意,此目录包含 bookstore.proto 文件。此文件用于定义 Bookstore 服务的 API。

  4. 通过服务 .proto 文件创建一个独立的 protobuf 描述符文件:

    1. 在工作目录下创建 generated_pb2 目录。

    2. 使用 protoc Protocol Buffers 编译器创建描述符文件 api_descriptor.pb。在包含 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

    在前面的命令中,--proto_path 设置为当前工作目录。在 gRPC 编译环境中,如果对 .proto 输入文件使用其他目录,请更改 --proto_path,以便编译器搜索您保存了 bookstore.proto 文件的目录。

  5. 修改当前工作目录中的 api_config_anthos.yaml 文件(包含 bookstore.proto 的同一目录)以向该文件添加以下内容:

    type: google.api.Service
    config_version: 3
    #
    # Name of the service configuration.
    #
    name: API_NAME.endpoints.ESP_PROJECT_ID.cloud.goog
    #
    # API title to appear in the user interface (Google Cloud console).
    #
    title: Bookstore gRPC API In Cloud Run Anthors
    apis:
    - name: endpoints.examples.bookstore.Bookstore
    #
    # Create a DNS record to map your service name to IP address
    #
    endpoints:
      - name: API_NAME.endpoints.ESP_PROJECT_ID.cloud.goog
        target: IP_ADDRESS
    #
    # Specify the backend address to route to
    #
    backend:
      rules:
        - selector: "*"
          address: grpc://GRPC_SERVICE.default.svc.cluster.local
          disable_auth: true
    #
    # API usage restrictions.
    #
    usage:
      rules:
      # ListShelves methods can be called without an API Key.
      - selector: endpoints.examples.bookstore.Bookstore.ListShelves
        allow_unregistered_calls: true

    缩进对 yaml 格式而言非常重要。

  6. name 字段中,指定用于访问 Cloud Run for Anthos 服务的 Endpoints API 的域名,格式如下:

    API_NAME.endpoints.ESP_PROJECT_ID.cloud.goog

    例如:

    grpc-bookstore-api.endpoints.ESP_PROJECT_ID.cloud.goog

  7. endpoints 部分会在 cloud.goog 网域上为您的 Endpoints 服务注册 DNS 条目,格式如下:

    endpoints:
      - name: API_NAME.endpoints.ESP_PROJECT_ID.cloud.goog
        target: IP_ADDRESS

    IP_ADDRESS 是集群的 istio-ingress 服务的 IP 地址。要确定此 IP 地址,请执行以下操作:

    1. 前往 Cloud 控制台中的 Google Kubernetes Engine 页面:

      转到 Google Kubernetes Engine

    2. 点击左侧导航面板中的 Service 和 Ingress 以显示服务列表。

    3. 如果您的集群版本为 1.15.3-gke.19 或更高版本、1.14.3-gke.12 或更高版本、1.13.10-gke.8 或更高版本,请向下滚动至 istio-ingress 服务。对于所有其他集群版本,向下滚动至 istio-ingressgateway 服务。

    4. 复制负载平衡器旁边显示的外部 IP 地址(如果有),不带端口设置。例如,如果 IP 地址为 XX.XXX.XX.XXX:15020,请省略 :15020。请忽略列出的其他 IP 地址。

  8. backend 部分中的 address 字段指定采用 proto 方案 grpc:// 的 Cloud Run "grpc-bookstore" 服务的内部 DNS 名称,并停用此服务的身份验证:

    address: grpc://GRPC_SERVICE.default.svc.cluster.local
    disable_auth: true

    例如:

    address: grpc://grpc-bookstore.default.svc.cluster.local
    disable_auth: true

    这是必要的操作,因为从 ESPv2 到 Cloud Run for Anthos 服务的调用在集群内部进行内部调用,因此不需要进行身份验证。

  9. 请记下 api_config_authos.yaml 文件中 title 属性的值:

    title: Bookstore gRPC API In Cloud Run Anthos

    在您部署配置后,title 属性的值会成为 Endpoints 服务的名称。

  10. 保存您的 gRPC API 文档。

如需了解 OpenAPI 文档中 Endpoints 所需的字段,请参阅配置 Endpoints

部署 Endpoints 配置

要部署 Endpoints 配置,请使用 gcloud endpoints services deploy 命令。此命令使用 Service Management 创建一项托管式服务。

如需部署 Endpoints 配置,请执行以下操作:

  1. 确保您位于 gRPC 文档所在的目录中。

  2. 上传配置并创建托管式服务。

    gcloud endpoints services deploy api_descriptor.pb api_config_anthos.yaml \ 
      --project ESP_PROJECT_ID

    这将创建一个新的 Endpoints 服务,其名称是您在 api_config_anthos.yaml 文件的 name 字段中指定的名称。Endpoints 服务会根据您的 OpenAPI 文档进行配置。

    在创建和配置 Endpoints 服务时,Service Management 会向终端输出信息。部署完成后,系统将显示如下所示的消息:

    Service Configuration [CONFIG_ID] uploaded for service [API_NAME.endpoints.ESP_PROJECT_ID.cloud.goog]

    CONFIG_ID 是部署创建的唯一 Endpoints 服务配置 ID。例如:

    Service Configuration [2019-02-01r0] uploaded for service [grpc-bookstore-api.endpoints.ESP_PROJECT_ID.cloud.goog] 

    服务配置 ID 由日期戳后跟一个修订版本号组成。如果您在同一天再次部署 api_config_anthos.yaml,则服务配置 ID 中的修订号会递增。您可以在以下位置查看服务配置和部署历史记录Google Cloud 控制台页面。

    如果您收到错误消息,请参阅排查 Endpoints 配置部署问题

检查所需服务

Endpoints 和 ESP 至少需要启用以下 Google 服务:
姓名 标题
servicemanagement.googleapis.com Service Management API
servicecontrol.googleapis.com Service Control API
endpoints.googleapis.com Google Cloud Endpoints

在大多数情况下,gcloud endpoints services deploy 命令会启用这些必需的服务。但在以下情况下,gcloud 命令会成功完成,但不启用必需的服务:

  • 您使用了 Terraform 之类的第三方应用,但未添加这些服务。

  • 您将 Endpoints 配置部署到已明确停用这些服务的现有 Google Cloud 项目。

使用以下命令确认必需服务是否已启用:

gcloud services list

如果您没有看到列出的必需服务,请启用它们:

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

同时启用 Endpoints 服务:

gcloud services enable ENDPOINTS_SERVICE_NAME

要确定 ENDPOINTS_SERVICE_NAME,您可以执行以下任一操作:

  • 部署 Endpoints 配置后,转到 Cloud 控制台中的端点页面。服务名称列下显示了可能的 ENDPOINTS_SERVICE_NAME 列表。

  • 对于 OpenAPI,ENDPOINTS_SERVICE_NAME 是您在 OpenAPI 规范的 host 字段中指定的值。对于 gRPC,ENDPOINTS_SERVICE_NAME 是您在 gRPC Endpoints 配置的 name 字段中指定的值。

如需详细了解 gcloud 命令,请参阅 gcloud 服务

构建新的 ESPv2 Knative serving 映像

将 Endpoints 服务配置构建到新的 ESPv2 Docker 映像中。创建此映像后,您可以将其部署到您的集群。

如需将服务配置构建到新的 ESPv2 Docker 映像中,请执行以下操作:

  1. 将此脚本下载到安装了 gcloud CLI 的本地机器,并运行以下命令:

    chmod +x gcloud_build_image 
    ./gcloud_build_image -s API_NAME.endpoints.ESP_PROJECT_ID.cloud.goog \ 
    -c CONFIG_ID -p ESP_PROJECT_ID

    该脚本使用 gcloud 命令下载服务配置,将服务配置构建到新的 ESPv2 映像中,然后将新映像上传到项目 Container Registry 中:脚本会自动使用最新版本的 ESPv2,由输出映像名称中的 ESP_VERSION 表示。输出映像将上传到:

    gcr.io/ESP_PROJECT_ID/endpoints-runtime-serverless:ESP_VERSION-API_NAME.endpoints.ESP_PROJECT_ID.cloud.goog-CONFIG_ID

部署 ESPv2 Knative 服务映像

将 ESPv2 Knative serving 服务映像部署到您的集群:

  1. 使用新映像部署 ESPv2 Knative serving 服务:

    gcloud run deploy ESP_V2_SERVICE_NAME \ 
      --image="gcr.io/ESP_PROJECT_ID/endpoints-runtime-serverless:API_NAME.endpoints.ESP_PROJECT_ID.cloud.goog-CONFIG_ID" \ 
      --platform gke \
      --use-http2 \
      --project=ESP_PROJECT_ID

    对于 ESP_PROJECT_ID,请指定要用于 ESPv2 服务的名称。在此示例中,将 ESP_V2_SERVICE_NAME 设置为 espv2

  2. 如果要将 Endpoints 配置为使用其他 ESPv2 启动选项(例如启用 CORS),您可以在 ESPv2_ARGS 环境变量中传递参数:

    gcloud run deploy ESP_V2_SERVICE_NAME \
      --image="gcr.io/ESP_PROJECT_ID/endpoints-runtime-serverless:API_NAME.endpoints.ESP_PROJECT_ID.cloud.goog-CONFIG_ID" \ 
      --set-env-vars=ESPv2_ARGS=--cors_preset=basic \ 
      --platform gke --use-http2 \
      --project ESP_PROJECT_ID

    如需详细了解如何设置 ESPv2_ARGS 环境变量并获取更多相关示例(包括可用选项的列表以及如何指定多个选项的信息),请参阅 Extensible Service Proxy V2 标志

创建映射到 ESPv2 Knative serving 服务的网域

要在发出请求时省略 host 标头,请为 ESPv2 服务添加网域映射:

  1. 转到 Cloud Run

  2. 选择管理自定义网域

  3. 选择添加映射

  4. 从下拉列表中选择添加服务网域映射

  5. 添加映射弹出窗口的选择要映射到的服务字段中,选择您的 ESPv2 服务。

  6. 输入域名字段中,指定要用于通过 Endpoints 访问 Knative serving 服务的域名。例如,您应指定:

    API_NAME.endpoints.ESP_PROJECT_ID.cloud.goog

    其中 API_NAME 是 Endpoints API 的名称。在此示例中,您可以使用“hello-api”:

    grpc-bookstore-api.endpoints.ESP_PROJECT_ID.cloud.goog

  7. 点击继续。此时会显示映射的摘要。

  8. 选择完成以保存映射。

向 API 发送请求

要向示例 API 发送请求,您可以使用以 Python 编写的示例 gRPC 客户端。

  1. 确保您位于包含 gRPC 文档的目录中,例如 api_config_anthos.yaml

  2. 安装依赖项:

    pip3 install virtualenv
    virtualenv env
    source env/bin/activate
    pip3 install -r requirements.txt
  3. 向示例 API 发送一个请求:

    python3 bookstore_client.py --host API_NAME.endpoints.ESP_PROJECT_ID.cloud.goog --port 80

    例如:

    python3 bookstore_client.py --host grpc-bookstore-api.endpoints.ESP_PROJECT_ID.cloud.goog --port 80

    如果一切正常,您会看到以下形式的响应:

    ListShelves: shelves {
      id: 1
      theme: "Fiction"
    }
    shelves {
      id: 2
      theme: "Fantasy"
    }

如果未获得成功响应,请参阅排查响应错误

您刚刚在 Endpoints 中部署并测试了一个 API!

配置 Endpoints API 以使用 HTTPS

对于 Google Cloud 上的 Knative serving,自动 TLS 支持默认处于停用状态。因此,在此示例中,当您通过 ESPv2 访问 Endpoints API 时,您使用 HTTP 进行调用。

您可以配置 ESPv2 以支持使用 HTTPS 的请求。请注意,您可以在 ESPv2(外部服务,而不是“hello”内部后端服务)上配置 HTTPS 支持。

要通过 ESPv2 支持 HTTPS,您必须:

  1. 拥有域名。如果您没有网域,可以从 Google 或其他网域供应商获取一个。

  2. 为 ESPv2 服务创建网域映射,然后按照网域映射页面中的说明相应地更新 DNS 记录。

    如果您是通过 Google Domains 获得的网域,请将其用作 DNS 服务器。否则,请使用 Cloud DNS 或您选择的 DNS 服务器。使用 Google Domains 中的网域是最简单的选择。

  3. 在 Endpoints OpenAPI 规范中:

    1. name 字段设置为引用您的域名,而不是*.cloud.goog

    2. 移除 endpoints 标记及其两个子属性。

如需了解完整说明和教程,请参阅启用 HTTPS 和自动 TLS 证书

跟踪 API 活动

  1. Endpoint 上查看 API 的活动图表 >服务 页面。

    查看 Endpoints 活动图表

    请求可能需要一些时间才能体现在图表中。

  2. 在“日志浏览器”页面上查看 API 的请求日志。

    查看 Endpoints 请求日志

为 API 创建开发者门户

您可以使用 Cloud Endpoints 门户来创建开发者门户,一个可供您与示例 API 互动的网站。如需了解详情,请参阅 Cloud Endpoints 门户概览

清理

为避免因本页中使用的资源导致您的 Google Cloud 账号产生费用,请按照以下步骤操作。

如需了解如何停止本教程使用的服务,请参阅删除 API 和 API 实例

后续步骤