迁移到 Extensible Service Proxy V2

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-TypeX-Endpoint-API-Consumer-Number 发送所需的详细信息。如需详细了解通过这些标头发送的 Consumer-TypeConsumer-Number,请参阅 Service Infrastructure 参考文档

  • 更改了 HTTP 错误响应正文格式。当 ESPv2 拒绝 HTTP 请求时,它会以新的格式生成错误响应正文。如果您的实现使用客户端代码来处理 HTTP 错误 JSON 响应正文,则必须更新客户端代码。如需了解详情,请参阅 HTTP 错误 JSON 响应正文

  • ESPv2 中增加了新的启动标志,某些 ESP 标志已被弃用或替换。请参阅 ESP 和 ESPv2 之间的启动标志更改

迁移 Endpoints API 以使用 ESPv2

将 ESPv2 与无服务器平台(Cloud Run、Cloud Functions、App Engine)搭配使用所需的迁移步骤与非无服务器平台(Google Kubernetes Engine、Compute Engine 和 Kubernetes)所需的步骤有所不同。

下文介绍了每种平台类型所需的迁移步骤:

非无服务器平台:GKE、Compute Engine、Kubernetes

ESPv2 可以直接替代 ESP。对于大多数配置,您只需更新到 Docker 映像标记。

但是,如果您的 ESP 配置了以下内容,则可能需要调整启动标志:

  • 通过 --http_porthttp2_port 和/或 --ssl_port 标志配置了多个端口。
  • SSLDNSClient 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 后,一些标志被弃用或替换,并添加了新标志。本部分使用三个表格来介绍这些更改:

  • 表 1 介绍替换已弃用标志的新标志。
  • 表 2 介绍新增标志。
  • 表 3 介绍已弃用的标志。

被替换的标志

新增标志 被替换的标志 说明
--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.keyserver.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.keyclient.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_addressxff_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,则可以执行以下操作:

x-google-jwt-locations:
- header: "Authorization"
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 会将 idissueremailaudiences 字段添加到 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 字段。

后续步骤

了解: