Extensible Service Proxy V2 (ESPv2) 是一个基于 Envoy 的代理,通过该代理,Cloud Endpoints 可以提供 API 管理功能。ESPv2 取代了基于 NGINX 的 Extensible Service Proxy (ESP)。
本文档介绍如何将现有 Endpoints API 部署从 ESP 迁移到 ESPv2。
准备工作
在开始迁移之前,请考虑以下不受支持的用例和重大 API 更改。
ESPv2 不受支持的使用场景
- 不支持 App Engine 柔性环境 - App Engine 柔性环境具有内置的 Endpoints 支持,可通过在应用的 - app.yaml文件中设置- endpoints_api_service来启用。此内置 Endpoints 实现仅支持 ESP;因此无法迁移到 ESPv2。- 如果要将 ESPv2 与 App Engine 柔性环境一起使用,请在 - app.yaml中停用- endpoints_api_service。您可以将 ESPv2 部署为单独的 Cloud Run 服务,用于在 App Engine 柔性环境中管理您的应用。部署的运作方式与 ESPv2 用于支持 App Engine 标准环境的方式相同。
- 不支持自定义 NGINX 配置 - ESPv2 是一种基于 Envoy 的代理。它无法支持自定义 NGINX 代理配置。如果您的 ESP 配置使用 - -n或- --nginx_config标志,您的实现可能依赖于无法轻易迁移到 ESPv2 的自定义 NGINX 配置。
重大更改
- 更改了 X-Endpoint-API-UserInfo标头数据格式。如果您的应用使用此标头,则必须将其改为使用新格式。如需了解详情,请参阅处理后端服务中的 JWT。
- 如果请求需要 API 密钥,ESP 将包含使用方项目 ID 的 - X-Endpoint-API-Project-ID标头发送给后端应用。ESPv2 使用两个不同的标头- X-Endpoint-API-Consumer-Type和- X-Endpoint-API-Consumer-Number发送所需的详细信息。如需详细了解通过这些标头发送的- Consumer-Type和- Consumer-Number,请参阅 Service Infrastructure 参考文档。
- 更改了 HTTP 错误响应正文格式。当 ESPv2 拒绝 HTTP 请求时,它会以新的格式生成错误响应正文。如果您的实现使用客户端代码来处理 HTTP 错误 JSON 响应正文,则必须更新客户端代码。如需了解详情,请参阅 HTTP 错误 JSON 响应正文。 
- ESPv2 中增加了新的启动标志,某些 ESP 标志已被弃用或替换。请参阅 ESP 和 ESPv2 之间的启动标志更改。 
迁移 Endpoints API 以使用 ESPv2
将 ESPv2 与无服务器平台(Cloud Run、Cloud Run Functions、App Engine)搭配使用所需的迁移步骤与非无服务器平台(Google Kubernetes Engine、Compute Engine 和 Kubernetes)所需的步骤有所不同。
下文介绍了每种平台类型所需的迁移步骤:
非无服务器平台:GKE、Compute Engine、Kubernetes
ESPv2 可以直接替代 ESP。对于大多数配置,您只需更新到 Docker 映像标记。
但是,如果您的 ESP 配置了以下内容,则可能需要调整启动标志:
- 通过 --http_port、http2_port和/或--ssl_port标志配置了多个端口。
- SSL、- DNS、- Client IP或其他很少使用的标志。
ESPv2 使用新的启动标志,某些 ESP 标志已被弃用或替换。如需了解详情,请参阅 ESP 和 ESPv2 之间的启动标志更改。
GKE 和 Kubernetes
如需为 GKE 和 Kubernetes 迁移 Endpoints 配置,请在部署 yaml 文件中将 ESP 映像标记从 :1 更改为 :2。例如:
- name: esp
  image: gcr.io/endpoints-release/endpoints-runtime:2
  args: [
    "--http_port=8081",
    "--backend=127.0.0.1:8080",
    "--service=SERVICE_NAME",
    "--rollout_strategy=managed",
  ]
Compute Engine
ESP 和 ESPv2 都使用 docker run 命令部署到 Docker 容器。如需将 Compute Engine 的 Endpoints 迁移到 ESPv2,请将命令中的 Docker 映像标记从 :1 更新为 :2。例如:
sudo docker run \
    --detach \
    DOCKER_ARGUMENTS \
    gcr.io/endpoints-release/endpoints-runtime:2 \
    --service=SERVICE_NAME \
    --rollout_strategy=managed \
    --backend=YOUR_API_CONTAINER_NAME:8080
无服务器平台(Cloud Run、Cloud Functions、App Engine)
对于无服务器平台,ESPv2 部署为 Cloud Run 服务,用于管理在 Cloud Run、Cloud Functions 或 App Engine 上运行的应用。要将 Endpoints 迁移到 ESPv2,您必须将现有 Endpoints 服务配置构建到新的 ESPv2 Docker 映像中,然后将映像部署到 ESPv2 Cloud Run 服务。
ESP 和 ESPv2 的部署步骤完全相同,但以下细节除外:
- 在将 ESPv2 部署到 Cloud Run 时,应在 ESPv2 中将映像标记从 - :1更改为- :2。例如:- gcloud run deploy CLOUD_RUN_SERVICE_NAME \ --image="gcr.io/endpoints-release/endpoints-runtime-serverless:2" \ --allow-unauthenticated \ --platform managed \ --project=ESP_PROJECT_ID 
- gcloud_build_image脚本从不同的位置下载。它使用- gcr.io/endpoints-release/endpoints-runtime-serverless:2作为基础映像。
- 环境变量用于指定启动标志。ESP 的变量名称为 - ESP_ARGS。ESPv2 的名称为- ESPv2_ARGS。如需详细了解如何设置- ESPv2_ARGS和可用的启动标志,请参阅 Extensible Service Proxy V2 启动选项。
ESP 和 ESPv2 之间的启动标志更改
与 Extensible Service Proxy 一样,您可以在部署 ESPv2 服务时指定配置标志。从基于 NGINX 的 ESP 更改为基于 Envoy 的 ESPv2 后,一些标志被弃用或替换,并添加了新标志。本部分使用三个表格来介绍这些更改:
被替换的标志
| 新增标志 | 被替换的标志 | 说明 | |
|---|---|---|---|
| --listener_port | --http_port、--http2_port、--ssl_port | 在 ESPv2 中,单个 Envoy 侦听器端口可以支持 http、http2 和 ssl。无需指定单独的端口。 | |
| --ssl_server_cert_path | --ssl_port | 使用 --ssl_server_cert_path时,ESPv2 使用server.key和server.crt文件中的证书。在 ESPv2 中,您可以指定除/etc/nginx/ssl以外的服务器证书路径。此标志取代了 ESP 中的--ssl_port,后者使用来自/etc/nginx/ssl/nginx.key和/etc/nginx/ssl/nginx.crt文件路径的证书。 | |
| --ssl_backend_client_cert_path | --tls_mutual_auth、--enable_grpc_backend_ssl、--grpc_backend_ssl_private_key_file、--grpc_backend_ssl_cert_chain_file | 使用 --ssl_backend_client_cert_path时,ESPv2 使用client.key和client.crt文件中的证书。在 ESPv2 中,您可以指定除/etc/nginx/ssl以外的客户端证书路径。此标志取代了 ESP 中的--tls_mutual_auth,后者使用来自/etc/nginx/ssl/backend.key和/etc/nginx/ssl/backend.crt文件路径的证书。 | |
| --ssl_backend_client_root_certs_file | --grpc_backend_ssl_root_certs_file | 在 ESPv2 中, --ssl_backend_client_root_certs_file适用于所有后端。此标志取代了 ESP 中的--grpc_backend_ssl_root_certs_file,后者仅适用于 gRPC 后端。 | |
| --ssl_minimum_protocol、--ssl_maximum_protocol | --ssl_protocols | 在 ESP 中使用 --ssl_protocols时,您必须列出所有需要的 ssl 协议。在 ESPv2 中,您可以指定最低和最高协议版本。 | |
| --envoy_use_remote_address、--envoy_xff_num_trusted_hops | --xff_trusted_proxy_list、--client_ip_header、--client_ip_position | Envoy 需要 use_remote_address和xff_num_trusted_hops来配置客户端 IP 提取。 | |
| --dns_resolver_addresses | --dns | 替换标志具有相同的行为,但默认值不同。ESP 使用 8.8.8.8 作为 DNS 解析器。ESPv2 使用 /etc/resolv.conf中配置的 DNS 解析器。 | |
| --service_account_key | --non_gcp、--service_account_key | 在 ESP 中, --service_account_key标志隐式允许部署到 GCP 以外的平台。它阻止 ESP 调用实例元数据服务器。 | 在 ESPv2 中,此隐式行为被拆分为另一个标志。迁移时,您可能需要添加 --non_gcp,否则 ESPv2 将无法在 GCP 以外的平台上启动。 | 
新增标志
| 新增标志 | 说明 | 
|---|---|
| --http_request_timeout_s | 设置所有 http/https 远程调用(后端调用和 Google Service Control 调用除外)的超时,以秒为单位。 | 
| --service_control_check_timeout_ms | 设置 Google Service Control Check 调用的超时(以毫秒为单位)。 | 
| --service_control_report_timeout_ms | 设置 Google Service Control Report 调用的超时。 | 
| --service_control_quota_timeout_ms | 设置 Google Service Control Quota 调用的超时。 | 
| --service_control_check_retries | 指定 Google Service Control Check 调用的重试次数。 | 
| --service_control_report_retries | 指定 Google Service Control Report 调用的重试次数。 | 
| --service_control_quota_retries | 指定 Google Service Control Quota 调用的重试次数。 | 
| --backend_dns_lookup_family | 用于定义所有后端的 DNS 查找系列的 Envoy 特定配置。 | 
| --disable_tracing | 用于停用所有跟踪记录的整体标志。 | 
| --tracing_project_id | 用于设置拥有跟踪记录数据的项目的 ID。 | 
| --tracing_incoming_context | 用于指定传入跟踪上下文。 | 
| --tracing_outgoing_context | 用于指定传出跟踪上下文。 | 
已弃用的标志
| 已弃用的标志 | 说明 | 
|---|---|
| --enable_websocket | Envoy 中默认启用 Websocket。 | 
| --experimental_proxy_backend_host_header | 不受支持。 | 
| --allow_invalid_headers | 不受支持。这是 NGINX 配置: ignore_invalid_headers。如果 HTTP 请求包含无效的标头名称,则 ESPv2 将拒绝该请求。有效标头名称由英文字母、数字、连字符和(可能的)下划线组成。在 ESPv2 中,标志--underscores_in_headers确定标头中是否允许使用下划线。 | 
| --client_max_body_size | NGINX 配置,不受支持。 | 
| --client_body_buffer_size | NGINX 配置,不受支持。 | 
| --large_client_header_buffers | NGINX 配置,不受支持。 | 
| --keepalive_timeout | NGINX 配置,不受支持。 | 
| --client_body_timeout | NGINX 配置,不受支持。 | 
| --rewrite | 不受支持。 | 
| --experimental_enable_multiple_api_configs | 不受支持。 | 
| --enable_backend_routing | 不需要。系统会自动为无服务器平台启用后端路由。 | 
| --rollout_fetch_throttle_window_in_s | 不需要。 | 
| --nginx_config | 不受支持。 | 
如需详细了解 ESPv2 启动标志,请参阅 Extensible Service Proxy V2 启动选项。如需查看标志的更多一般示例和帮助文本,请访问 GitHub 代码库。
默认 JWT 位置
默认情况下,JWT 会在 Authorization 标头(以“Bearer”为前缀)、X-Goog-Iap-Jwt-Assertion 标头或 access_token 查询参数中传递。ESP 和 ESPv2 均支持这些位置。使用 ESP 时,您还可以在 Authorization 标头(不带前缀)中传递 JWT。但是,ESPv2 不支持此位置。
如果您希望在迁移到 ESPv2 后继续使用 Authorization 标头(不带前缀)传递 JWT,则可以执行以下操作:
- 在 openAPI 文件中设置 x-google-jwt-locations(适用于 HTTP 后端用户):
x-google-jwt-locations: - header: "Authorization"
- 在 gRPC yaml 文件中设置 Authentication.providers.jwt_locations(适用于 gRPC 后端用户):
jwt_locations:
- header: Authorization处理后端服务中的 JWT
使用 JWT 执行身份验证时,ESPv2 和 ESP 会向后端 API 发送 X-Endpoint-API-UserInfo 标头中的身份验证结果。我们建议您使用此标头,而不是原始 Authorization 标头,因为在无服务器平台中原始 Authorization 标头可能被修改。
X-Endpoint-API-UserInfo 标头包含一个 Base64Url 编码的 JSON 对象。不过,其格式已从 ESP 更改为 ESPv2。
对于 ESPv2,X-Endpoint-API-UserInfo 标头包含原始 JWT 载荷,无需进行任何修改。
在 ESP 中,X-Endpoint-API-UserInfo 标头包含 JWT 载荷以及 ESP 添加的一些特定字段。ESP 会将 id、issuer、email 和 audiences 字段添加到 JSON 对象中。它还会添加 claims 字段以包含原始 JWT 载荷。
# ESPv1 X-Endpoint-API-UserInfo header value
{
  "id": "extracted from 'sub' field",
  "issuer": "extracted from 'iss' field",
  "email": "extracted from 'email' field",
  # The following "audiences" is extracted from 'aud' field.
  # The 'aud' field may have multiple audiences delimited by coma. e.g. "aud: aud1,aud2".
  # but the following "audiences" is always a JSON array.
  "audiences": ["aud1", "aud2"],
  "claims": {
     Original JWT payload
   }
}
以下示例说明了其中的差异,所有这些差异都经过了 base64url 解码。
# This is an example of the original JWT payload: { "iss": "https://accounts.google.com", "email": "abcdefg123456@gmail.com", "sub": "1234567890123456789", "aud": "xyz1.example.com,xyz2.example.com", "foo": "foo.foo.foo.foo", "bar": "bar.bar.bar.bar", "azp": "98765432109876543210", "exp": "1642809446", "iat": "1642805846" } # This is an example of the `X-Endpoint-API-UserInfo` header from ESPv2 # extracted from above JWT payload. { "iss": "https://accounts.google.com", "email": "abcdefg123456@gmail.com", "sub": "1234567890123456789", "aud": "xyz1.example.com,xyz2.example.com", "foo": "foo.foo.foo.foo", "bar": "bar.bar.bar.bar", "azp": "98765432109876543210", "exp": "1642809446", "iat": "1642805846" } # This is an example of the `X-Endpoint-API-UserInfo` header from ESP # extracted from above JWT payload. { "id":"1234567890123456789", "issuer": "https://accounts.google.com", "email": "abcdefg123456@gmail.com", "audiences": [ "xyz1.example.com" "xyz2.example.com" ], "claims": { "iss": "https://accounts.google.com", "email": "abcdefg123456@gmail.com", "sub": "1234567890123456789", "aud": "xyz1.example.com,xyz2.example.com", "foo": "foo.foo.foo.foo", "bar": "bar.bar.bar.bar", "azp": "98765432109876543210", "exp": "1642809446", "iat": "1642805846" } }
请参阅使用自定义方法验证用户身份和服务之间的身份验证,详细了解如何使用 JWT 进行身份验证。
错误 JSON 响应正文格式
如果 ESP 或 ESPv2 拒绝 HTTP 请求,则响应正文将包含状态代码和 JSON 格式的错误消息。ESPv2 中的响应正文格式已更改,如以下示例所示:
ESP 的错误响应正文
{ "code": 5, "message": "Method does not exist.", "details": [ { "@type": "type.googleapis.com/google.rpc.DebugInfo", "stackEntries": [], "detail": "service_control" } ] }
ESPv2 的错误响应正文
{
 "code": 400,
 "message": "Method does not exist.",
}有两个主要区别:
- 在 ESPv2 中,code字段包含 HTTP 状态代码,而不是 ESP 中的 RPC 状态代码。
- ESPv2 的错误响应正文不包含 details字段。
后续步骤
了解: