使用 ESPv2 为 Cloud Run 设置 Endpoints OpenAPI
本页面介绍如何为 Cloud Run 设置 Endpoints。 Endpoints 使用 Extensible Service Proxy V2 (ESPv2) 作为 API 网关。如需为 Cloud Run 提供 API 管理功能,请将预构建的 ESPv2 容器部署到 Cloud Run。然后,使用 Cloud Run Identity and Access Management (IAM) 保护服务,以便 ESPv2 可调用它们。
如此设置之后,ESPv2 会拦截向您服务发出的所有请求,并在调用服务之前执行任何必要的检查(如身份验证)。当服务响应时,ESPv2 会收集并报告遥测数据,如下图所示。您可以在 Google Cloud 控制台中的 Endpoints > 服务页面上查看服务的指标。
如需大致了解 Cloud Endpoints,请参阅关于 Endpoints 和 Endpoints 架构。
迁移到 ESPv2
以前版本的 Endpoints 支持在 Cloud Run 中使用 Extensible Service Proxy(ESP)。 如果您有要迁移到 ESPv2 的现有 API,请参阅迁移到 Extensible Service Proxy V2 了解更多信息。
任务列表
学习本教程时,请使用以下任务列表。完成本教程所需的所有任务。
- 创建一个 Google Cloud 项目,如果您尚未部署自己的 Cloud Run,请部署一个示例后端服务。请参阅准备工作。
- 为 ESPv2 服务预留 Cloud Run 主机名。请参阅预留 Cloud Run 主机名。
- 创建一个描述您的 API 的 OpenAPI 文档,并配置到您的 Cloud Run 的路由。请参阅配置 Endpoints。
- 部署 OpenAPI 文档以创建托管式服务。请参阅部署 Endpoints 配置。
- 使用您的 Endpoints 服务配置构建新的 ESPv2 Docker 映像。请参阅构建新的 ESPv2 映像。
- 将 ESPv2 容器部署到 Cloud Run。然后为 ESPv2 授予 Identity and Access Management (IAM) 权限以调用您的服务。请参阅部署 ESPv2 容器。
- 调用一个服务。请参阅向 API 发送请求。
- 跟踪您的服务的活动。请参阅跟踪 API 活动。
- 避免您的 Google Cloud 账号产生费用。 请参阅清理。
费用
在本文档中,您将使用 Google Cloud的以下收费组件:
如需根据您的预计使用量来估算费用,请使用价格计算器。
完成本文档中描述的任务后,您可以通过删除所创建的资源来避免继续计费。如需了解详情,请参阅清理。
准备工作
如需进行设置,请执行以下操作:
在 Google Cloud 控制台中,前往管理资源页面并创建一个项目。
确保您的项目已启用结算功能。
请记下项目 ID,您稍后需要用到它。在本页面的其余部分,此项目 ID 称为 ESPv2_PROJECT_ID。
请记下项目编号,您稍后会用到它。在本页面的其余部分,此项目编号称为 ESPv2_PROJECT_NUMBER。
下载并安装 Google Cloud CLI。
如果您尚未部署自己的 Cloud Run 后端服务,请按照《快速入门:部署预建的示例容器》中的步骤选择或创建 Google Cloud 项目并部署示例后端。记下部署服务的区域和项目 ID。在本页面的其余部分,此项目 ID 称为 BACKEND_PROJECT_ID。已部署服务的名称为 BACKEND_SERVICE_NAME。
预留 Cloud Run 主机名
您必须为 ESPv2 服务预留 Cloud Run 主机名,才能配置 OpenAPI 文档或 gRPC 服务配置。为了预留主机名,您需要将示例容器部署到 Cloud Run。稍后,您会将 ESPv2 容器部署到相同的 Cloud Run 服务中。
-
确保 gcloud CLI 有权访问您的数据和服务。
- 登录。
gcloud auth login
- 在打开的新浏览器标签页上,选择一个账号,该账号在您为将 ESPv2 部署到 Cloud Run 而创建的 Google Cloud 项目中具有编辑者或所有者角色。
- 登录。
- 设置区域。
gcloud config set run/region us-central1
-
将示例映像
gcr.io/cloudrun/hello部署到 Cloud Run。将 ESPv2_CLOUD_RUN_SERVICE_NAME 替换为您要使用的服务名称。gcloud run deploy ESPv2_CLOUD_RUN_SERVICE_NAME \ --image="gcr.io/cloudrun/hello" \ --allow-unauthenticated \ --platform managed \ --project=ESPv2_PROJECT_ID成功完成上述操作后,该命令将显示如下所示的消息:
Service [ESPv2_CLOUD_RUN_SERVICE_NAME] revision [ESPv2_CLOUD_RUN_SERVICE_NAME-REVISION_NUM] has been deployed and is serving traffic at CLOUD_RUN_SERVICE_URL
例如,如果将 ESPv2_CLOUD_RUN_SERVICE_NAME 设置为
gateway:Service [gateway] revision [gateway-00001] has been deployed and is serving traffic at https://gateway-12345-uc.a.run.app
在此示例中,
https://gateway-12345-uc.a.run.app为 CLOUD_RUN_SERVICE_URL,gateway-12345-uc.a.run.app为 ESPv2_CLOUD_RUN_HOSTNAME。 - 记下 ESPv2_CLOUD_RUN_SERVICE_NAME 和 ESPv2_CLOUD_RUN_HOSTNAME。您稍后会将 ESPv2 部署到 ESPv2_CLOUD_RUN_SERVICE_NAME Cloud Run 服务。您可以在 OpenAPI 文档的
host字段中指定ESPv2_CLOUD_RUN_HOSTNAME。
配置 Endpoints
您必须拥有基于 OpenAPI 2.0 或 OpenAPI 3.x 的 OpenAPI 文档,该文档描述了您的应用的表面和各项身份验证要求。如需了解详情,请参阅支持的 OpenAPI 版本。
您还需要添加包含各应用的网址的 Google 专属字段,以便 ESPv2 获得调用应用所需的信息。如果您刚接触 OpenAPI,请参阅 OpenAPI 概览了解详情。
-
创建名为
openapi-run.yaml的文本文件。为方便起见,本页面用此文件名指代 OpenAPI 文档,但您也可以改用其他名称。 -
您的 App Engine 后端应用是在
openapi-run.yaml文件中定义的,可以是x-google-backend定义(对于 OpenAPI 2.0),也可以是x-google-api-management定义(对于 OpenAPI 3.x)。例如:OpenAPI 2.0
swagger: '2.0' info: title: Cloud Endpoints + Cloud Run description: Sample API on Cloud Endpoints with a Cloud Run backend version: 1.0.0 host: ESPv2_CLOUD_RUN_HOSTNAME schemes: - https produces: - application/json x-google-backend: address: BACKEND_SERVICE_NAME protocol: h2 paths: /hello: get: summary: Greet a user operationId: hello responses: '200': description: A successful response schema: type: string
OpenAPI 3.x
openapi: 3.0.4 info: title: Cloud Endpoints + Cloud Run description: Sample API on Cloud Endpoints with a Cloud Run backend version: 1.0.0 servers: - url: https://ESPv2_CLOUD_RUN_HOSTNAME x-google-endpoint: {} x-google-api-management: backends: cloudrun_backend: address: BACKEND_SERVICE_NAME protocol: h2 x-google-backend: cloudrun_backend paths: /hello: get: summary: Greet a user operationId: hello responses: '200': description: A successful response content: application/json: schema: type: string
缩进对 YAML 格式而言非常重要。例如,
host字段(对于 OpenAPI 2.0)或servers对象必须与info处于同一级别。 在
address字段中,将 BACKEND_SERVICE_NAME 替换为后端 Cloud Run 服务的实际网址,即准备工作第 6 步中创建的网址。此示例假定您使用的是快速入门:部署预建的示例容器中创建的
hello后端服务。如果您使用的是其他后端 Cloud Run 服务,请将 BACKEND_SERVICE_NAME 替换为您的 Cloud Run 服务的网址。为您的服务指定主机名。所需的值取决于您使用的 OpenAPI 规范版本。
OpenAPI 2.0
在
host字段中,指定 ESPv2_CLOUD_RUN_HOSTNAME,即预留 Cloud Run 主机名中预留的网址的主机名部分。 请勿包含协议标识符https://。例如:swagger: '2.0' info: title: Cloud Endpoints + Cloud Run description: Sample API on Cloud Endpoints with a Cloud Run backend version: 1.0.0 host: gateway-12345-uc.a.run.app
OpenAPI 3.x
在
servers对象的url字段中,指定完整网址,包括协议标识符https://和预留 Cloud Run 主机名中预留的网址的主机名部分 ESPv2_CLOUD_RUN_HOSTNAME。例如:openapi: 3.0.4 info: title: Cloud Endpoints + Cloud Run description: Sample API on Cloud Endpoints with a Cloud Run backend version: 1.0.0 servers: - url: https://gateway-12345-uc.a.run.app x-google-endpoint: {}
请记下
openapi-run.yaml文件中title属性的值:title: Cloud Endpoints + Cloud Run
在您部署配置后,
title属性的值会成为 Endpoints 服务的名称。- 保存您的 OpenAPI 文档。
如需了解 OpenAPI 文档中 Endpoints 所需的字段,请参阅配置 Endpoints。
配置 Endpoints 以要求提供 API 密钥
如需控制对 API 的访问权限,您可以将 Endpoints 配置为要求提供 API 密钥。调用您 API 的客户端必须提供与您的项目关联的 API 密钥。如需了解详情,请参阅使用 API 密钥限制 API 访问权限。
如果您没有与本快速入门中使用的 Google Cloud 项目关联的 API 密钥,则可以按照创建 API 密钥中的步骤添加一个。
如需使用与您的 Google Cloud 项目关联的 API 密钥测试 API 密钥强制执行,请按以下步骤操作:
- 为您的服务启用 API 密钥支持。 输入以下命令,其中:
- ESPv2_CLOUD_RUN_HOSTNAME 是 Cloud Run 上为 ESPv2 服务指定的网址的主机名组成部分。它用于 OpenAPI 文档的
host字段中,以指定 API 的托管位置。
gcloud services enable ESPv2_CLOUD_RUN_HOSTNAME
- ESPv2_CLOUD_RUN_HOSTNAME 是 Cloud Run 上为 ESPv2 服务指定的网址的主机名组成部分。它用于 OpenAPI 文档的
- 打开项目的
openapi-run.yaml文件。 - 在
securityDefinitions部分下添加api_key安全方案。这定义了一个名为api_key的安全机制,该机制会在x-api-key标头中查找 API 密钥。swagger: '2.0' host: ESPv2_CLOUD_RUN_HOSTNAME info: version: 1.0.0 title: Cloud Endpoints + Cloud Run schemes: - https produces: - application/json securityDefinitions: api_key: type: "apiKey" name: "key" in: "query"
-
通过在
openapi-run.yaml文件的顶层添加security: - api_key: []指令,将api_key安全机制应用于所有 API 方法。swagger: '2.0' host: ESPv2_CLOUD_RUN_HOSTNAME info: version: 1.0.0 title: Cloud Endpoints + Cloud Run schemes: - https produces: - application/json securityDefinitions: api_key: type: "apiKey" name: "key" in: "query" security: - api_key: []
- 如果您想保护特定方法,而不是整个 API,请在顶层添加一个空的
security: []指令,然后将security: - api_key: []指令添加到您要保护的特定方法的定义中。paths: /shelves: get: summary: Lists all shelves operationId: listShelves security: [] post: summary: Creates a new shelf operationId: createShelf security: - api_key: [] -
修改
openapi-run.yaml文件后,将更新后的配置部署到您的 Endpoints 服务。
使用 API 密钥调用 API
如果 API 或 API 方法需要 API 密钥,请使用名为 key 的查询参数提供该密钥,如以下 curl 示例所示:
curl "${ESPv2_CLOUD_RUN_HOSTNAME}/echo?key=${API_KEY}"
最佳做法
如果您依赖 API 密钥来保护对 API 和用户数据的访问权限,请确保在配置 Extensible Service Proxy V2 (ESPv2) 启动选项时将 --service_control_network_fail_policy 标志设置为 close。该标志的默认值为 open.
ESPv2 调用 Service Control 来验证 API 密钥。如果在连接到 Service Control 时出现网络故障并且 ESPv2 无法验证 API 密钥,这会导致使用欺诈性密钥向您的 API 发出的任何潜在请求被拒绝。
部署 Endpoints 配置
如需部署 Endpoints 配置,请使用 gcloud endpoints services deploy 命令。此命令使用 Service Management 创建一项托管式服务。
如需部署 Endpoints 配置,请执行以下操作:
- 确保您位于 OpenAPI 文档所在的目录中。
上传配置并创建托管式服务。
gcloud endpoints services deploy openapi-run.yaml \ --project ESPv2_PROJECT_ID
这将创建一个新的 Endpoints 服务,其名称是您在
openapi-run.yaml文件的host字段中指定的名称。该服务会根据您的 OpenAPI 文档进行配置。在创建和配置服务时,Service Management 会向终端输出信息。部署完成后,系统将显示如下所示的消息:
Service Configuration [CONFIG_ID] uploaded for service [ESPv2_CLOUD_RUN_HOSTNAME]
CONFIG_ID 是部署创建的唯一 Endpoints 服务配置 ID。例如:
Service Configuration [2019-02-01r0] uploaded for service [gateway-12345-uc.a.run.app]
服务配置 ID 由日期戳后跟一个修订版本号组成。如果您在同一天再次部署
openapi-run.yaml,则服务配置 ID 中的修订版本号将递增。您可以在 Google Cloud 控制台中的 Endpoints > 服务页面上查看服务配置和部署历史记录。如果您收到错误消息,请参阅排查 Endpoints 配置部署问题。
检查所需服务
Endpoints 和 ESP 至少需要启用以下 Google 服务:| 姓名 | 标题 |
|---|---|
servicemanagement.googleapis.com |
Service Management API |
servicecontrol.googleapis.com |
Service Control API |
在大多数情况下,gcloud endpoints services deploy 命令会启用这些必需的服务。但在以下情况下,gcloud 命令会成功完成,但不启用必需的服务:
您使用了 Terraform 之类的第三方应用,但未添加这些服务。
您将 Endpoints 配置部署到已明确停用这些服务的现有Google Cloud 项目。
使用以下命令确认必需服务是否已启用:
gcloud services list
如果您没有看到列出的必需服务,请启用它们:
gcloud services enable servicemanagement.googleapis.com
gcloud services enable servicecontrol.googleapis.com同时启用 Endpoints 服务:
gcloud services enable ENDPOINTS_SERVICE_NAME
要确定 ENDPOINTS_SERVICE_NAME,您可以执行以下任一操作:
部署 Endpoints 配置后,转到 Cloud 控制台中的 Endpoints 页面。服务名称列下显示了可能的 ENDPOINTS_SERVICE_NAME 列表。
对于 OpenAPI,ENDPOINTS_SERVICE_NAME 是您在 OpenAPI 规范的
host字段中指定的值。对于 gRPC,ENDPOINTS_SERVICE_NAME 是您在 gRPC Endpoints 配置的name字段中指定的值。
如需详细了解 gcloud 命令,请参阅 gcloud 服务。
构建新的 ESPv2 映像
将 Endpoints 服务配置构建到新的 ESPv2 Docker 映像中。您稍后会将此映像部署到预留的 Cloud Run 服务。
如需将服务配置构建到新的 ESPv2 Docker 映像中,请执行以下操作:
将此脚本下载到安装了 gcloud CLI 的本地机器上。
使用以下命令运行脚本:
chmod +x gcloud_build_image./gcloud_build_image -s ESPv2_CLOUD_RUN_HOSTNAME \ -c CONFIG_ID -p ESPv2_PROJECT_ID对于 ESPv2_CLOUD_RUN_HOSTNAME,请指定在上文的预留 Cloud Run 主机名中预留的网址的主机名。请勿包含协议标识符
https://。例如:
chmod +x gcloud_build_image./gcloud_build_image -s gateway-12345-uc.a.run.app \ -c 2019-02-01r0 -p your-project-id-
该脚本使用
gcloud命令下载服务配置,将服务配置构建到新的 ESPv2 映像中,然后将新映像上传到项目 Container Registry 中:脚本会自动使用最新版本的 ESPv2,由输出映像名称中的 ESPv2_VERSION 表示。输出映像将上传到:gcr.io/ESPv2_PROJECT_ID/endpoints-runtime-serverless:ESPv2_VERSION-ESPv2_CLOUD_RUN_HOSTNAME-CONFIG_ID
例如:
gcr.io/your-project-id/endpoints-runtime-serverless:2.14.0-gateway-12345-uc.a.run.app-2019-02-01r0"
部署 ESPv2 容器
使用您之前构建的新映像部署 ESPv2 Cloud Run 服务。 将 ESPv2_CLOUD_RUN_SERVICE_NAME 替换为您在上文的预留 Cloud Run 主机名中最初预留主机名时所用的 Cloud Run 服务名称:
gcloud run deploy ESPv2_CLOUD_RUN_SERVICE_NAME \ --image="gcr.io/ESPv2_PROJECT_ID/endpoints-runtime-serverless:ESPv2_VERSION-ESPv2_CLOUD_RUN_HOSTNAME-CONFIG_ID" \ --allow-unauthenticated \ --platform managed \ --project=ESPv2_PROJECT_ID
如果要将 Endpoints 配置为使用其他 ESPv2 启动选项(例如启用 CORS),您可以在
ESPv2_ARGS环境变量中传递参数:gcloud run deploy ESPv2_CLOUD_RUN_SERVICE_NAME \ --image="gcr.io/ESPv2_PROJECT_ID/endpoints-runtime-serverless:ESPv2_VERSION-ESPv2_CLOUD_RUN_HOSTNAME-CONFIG_ID" \ --set-env-vars=ESPv2_ARGS=--cors_preset=basic \ --allow-unauthenticated \ --platform managed \ --project ESPv2_PROJECT_ID
如需详细了解如何设置
ESPv2_ARGS环境变量并获取更多相关示例(包括可用选项的列表以及如何指定多个选项的信息),请参阅 Extensible Service Proxy V2 标志。- 授予 ESPv2 权限以调用 Service Management 和 Service Control。
- 在 Google Cloud 控制台中,前往 Cloud Run 页面。
- 您可以查看您部署的 Cloud Run 实例以及与其关联的服务账号。
- 向服务账号授予所需权限:
- 为 ESPv2 授予调用 Cloud Run 服务的权限。对每个服务运行以下命令。在以下命令中:
- 将 BACKEND_SERVICE_NAME 替换为要调用的 Cloud Run 服务的名称。如果您使用的是快速入门:部署预建的示例容器中创建的后端服务,则使用
hello作为此值。 - 将 ESPv2_PROJECT_NUMBER 替换为您针对 ESPv2 创建的项目的编号。如需找到此编号,一种方法是转到 Google Cloud 控制台中的 IAM 页面并查找默认计算服务账号,即“member”标志中使用的服务账号。
gcloud run services add-iam-policy-binding BACKEND_SERVICE_NAME \ --member "serviceAccount:ESPv2_PROJECT_NUMBER-compute@developer.gserviceaccount.com" \ --role "roles/run.invoker" \ --platform managed \ --project BACKEND_PROJECT_ID
- 将 BACKEND_SERVICE_NAME 替换为要调用的 Cloud Run 服务的名称。如果您使用的是快速入门:部署预建的示例容器中创建的后端服务,则使用
gcloud projects add-iam-policy-binding PROJECT_ID \
--member "serviceAccount:SERVICE_ACCOUNT" \
--role roles/servicemanagement.serviceController如需了解详情,请参阅使用 IAM 管理访问权限。
向 API 发送请求
本部分介绍如何向 API 发送请求。
- 为 Endpoints 服务名称创建环境变量。这是您在 OpenAPI 文档的
host字段中指定的名称。例如:Linux 或 macOS:
export ENDPOINTS_HOST=gateway-12345-uc.a.run.appWindows PowerShell:
$Env: ENDPOINTS_HOST="gateway-12345-uc.a.run.app"
Linux 或 macOS
通过您在上一步中设置的 ENDPOINTS_HOST 环境变量,使用 curl 发送一个 HTTP 请求。
curl --request GET \
--header "content-type:application/json" \
"https://${ENDPOINTS_HOST}/hello"PowerShell
通过您在上一步中设置的 ENDPOINTS_HOST 环境变量,使用 Invoke-WebRequest 发送一个 HTTP 请求。
(Invoke-WebRequest -Method GET `
-Headers @{"content-type"="application/json"} `
-URI "https://$Env:ENDPOINTS_HOST/hello").Content
在上面的示例中,前两行以反引号结束。将示例粘贴到 PowerShell 中时,请确保反引号后面没有空格。 如需了解示例请求中使用的选项,请参阅 Microsoft 文档中的 Invoke-WebRequest。
第三方应用
您可以使用第三方应用,例如 Chrome 浏览器扩展程序 Postman 发送请求。
- 选择
GET作为 HTTP 谓词。 - 对于标头,请选择键
content-type和值application/json。 使用实际的网址而不是环境变量,例如:
https://gateway-12345-uc.a.run.app/hello
如果未成功收到响应,请参阅排查响应错误。
您刚刚在 Endpoints 中部署并测试了一个 API!
跟踪 API 活动
在 Google Cloud 控制台中的 Endpoints > 服务页面上查看 API 的活动图表。
请求可能需要一些时间才能体现在图表中。
在“日志浏览器”页面上查看 API 的请求日志。查看 Endpoints 请求日志
清理
为避免因本页中使用的资源导致您的 Google Cloud 账号产生费用,请按照以下步骤操作。
如需了解如何停止本教程使用的服务,请参阅删除 API 和 API 实例。