使用入门:Kubernetes 上使用 ESPv2 的 Endpoints

本教程介绍如何使用 gRPC (ESPv2) 将一个简单的示例 gRPC 服务部署到不在Google Cloud上运行的 Kubernetes 集群中。本教程使用 Python 版本的 bookstore-grpc 示例。如需其他语言的 gRPC 示例,请参阅后续步骤部分。

本教程使用了示例代码和 ESPv2 的预构建容器映像,这些映像存储在 Artifact Registry 中。如果您不熟悉容器,请参阅以下内容了解详情:

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

配置 Endpoints

bookstore-grpc 示例包含您在本地复制并进行配置所需的文件。

  1. 通过服务 .proto 文件创建一个独立的 protobuf 描述符文件:
    1. 保存示例代码库中 bookstore.proto 的副本。此文件用于定义 Bookstore 服务的 API。
    2. 创建以下目录:mkdir generated_pb2
    3. 使用 protoc Protocol Buffers 编译器创建描述符文件 api_descriptor.pb。在您保存了 bookstore.proto 的目录中运行以下命令:
      python -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 文件的目录。

  2. 创建 gRPC API 配置 YAML 文件:
    1. 保存 api_config.yaml 文件的副本。此文件用于定义 Bookstore 服务的 gRPC API 配置
    2. api_config.yaml 文件中的 MY_PROJECT_ID 替换为您的 Google Cloud 项目 ID。例如:
      #
      # Name of the service configuration.
      #
      name: bookstore.endpoints.example-project-12345.cloud.goog
      

      请注意,此文件中 apis.name 字段的值应该与 .proto 文件中的完全限定 API 名称完全匹配;否则部署将无法正常运行。Bookstore 服务是在 endpoints.examples.bookstore 包内的 bookstore.proto 中定义的。其完全限定的 API 名称为 endpoints.examples.bookstore.Bookstore,与其在 api_config.yaml 文件中的名称相同。

      apis:
        - name: endpoints.examples.bookstore.Bookstore

如需了解详情,请参阅配置 Endpoints

部署 Endpoints 配置

如需部署 Endpoints 配置,请使用 gcloud endpoints services deploy 命令。此命令使用 Service Infrastructure,这是 Google 的基础服务平台,供 Endpoints 及其他服务用来创建并管理 API 和服务。

  1. 确保您位于 api_descriptor.pbapi_config.yaml 文件所在的目录中。
  2. 确认 gcloud 命令行工具当前使用的默认项目是您要向其部署 Endpoints 配置的 Google Cloud 项目。验证从以下命令返回的项目 ID,以确保不会在错误的项目中创建服务。
    gcloud config list project
    

    如果您需要更改默认项目,请运行以下命令:

    gcloud config set project YOUR_PROJECT_ID
    
  3. 使用 Google Cloud CLI 部署 proto descriptor 文件和配置文件:
    gcloud endpoints services deploy api_descriptor.pb api_config.yaml
    

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

    Service Configuration [CONFIG_ID] uploaded for service [bookstore.endpoints.example-project.cloud.goog]

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

    Service Configuration [2017-02-13r0] uploaded for service [bookstore.endpoints.example-project.cloud.goog]
    

    在前面的示例中,2017-02-13r0 是服务配置 ID,bookstore.endpoints.example-project.cloud.goog 是服务名称。服务配置 ID 由日期戳后跟一个修订版本号组成。如果您在同一天再次部署 Endpoints 配置,服务配置 ID 中的修订版本号将递增。

如果您收到错误消息,请参阅排查 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 服务

为您的服务创建凭据

为了管理您的 API,ESP 和 ESPv2 都需要使用 Service Infrastructure 中的服务。为了调用这些服务,ESP 和 ESPv2 必须使用访问令牌。当您将 ESP 或 ESPv2 部署到 Google Cloud 环境(例如 GKE 或 Compute Engine)时,ESP 和 ESPv2 会通过 Google Cloud 元数据服务为您获取访问令牌。

将 ESP 或 ESPv2 部署到非Google Cloud 环境(例如本地桌面、本地 Kubernetes 集群或其他云服务商)时,您必须提供包含私钥的服务账号 JSON 文件。ESP 和 ESPv2 使用服务账号生成访问令牌,以调用管理 API 所需的服务。

您可以使用 Google Cloud 控制台或 Google Cloud CLI 创建服务账号和私钥文件:

控制台

  1. 在 Google Cloud 控制台中,打开服务账号页面。

    转到“服务账号”页面

  2. 点击选择项目
  3. 选择在其中创建了 API 的项目,并点击打开
  4. 点击 + 创建服务账号
  5. 服务账号名称字段中,输入您的服务账号的名称。
  6. 点击创建
  7. 点击继续
  8. 点击完成
  9. 点击新创建的服务账号的电子邮件地址。
  10. 点击密钥
  11. 依次点击添加密钥创建新密钥
  12. 点击创建。JSON 密钥文件将下载到您的计算机上。

    务必要安全存储密钥文件,因为它能够以服务账号的身份进行身份验证。您可以根据需要移动并重命名此文件。

  13. 点击关闭

gcloud

  1. 输入以下命令,以显示Google Cloud 项目的项目 ID:

    gcloud projects list
  2. 替换以下命令中的 PROJECT_ID,以将默认项目设置为您的 API 所属的项目:

    gcloud config set project PROJECT_ID
  3. 确保 Google Cloud CLI (gcloud) 有权访问您在 Google Cloud上的数据和服务:

    gcloud auth login

    如果您有多个账号,请务必选择 API 所在的 Google Cloud 项目中的账号。如果您运行 gcloud auth list,则您选择的账号将显示为该项目的有效账号。

  4. 如需创建服务账号,请运行以下命令,并将 SERVICE_ACCOUNT_NAMEMy Service Account 分别替换为您要使用的名称和显示名:

    gcloud iam service-accounts create SERVICE_ACCOUNT_NAME \
       --display-name "My Service Account"

    该命令将采用以下格式指定服务账号的电子邮件地址:

    SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com

    后续命令会用到此电子邮件地址。

  5. 创建服务账号密钥文件:

    gcloud iam service-accounts keys create ~/service-account-creds.json \
       --iam-account SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com

添加所需的 IAM 角色:

本部分介绍 ESP 和 ESPv2 使用的 IAM 资源,以及关联的服务账号访问这些资源所需的 IAM 角色。

端点服务配置

ESP 和 ESPv2 调用使用端点服务配置的 Service Control。端点服务配置是 IAM 资源,ESP 和 ESPv2 需要 Service Controller 角色才能访问它。

IAM 角色属于端点服务配置,而非项目。一个项目可能有多个端点服务配置。

使用以下 gcloud 命令将角色添加到端点服务配置的关联服务账号。

gcloud endpoints services add-iam-policy-binding SERVICE_NAME \
  --member serviceAccount:SERVICE_ACCOUNT_NAME@DEPLOY_PROJECT_ID.iam.gserviceaccount.com \
  --role roles/servicemanagement.serviceController

其中
* SERVICE_NAME 是端点服务名称
* SERVICE_ACCOUNT_NAME@DEPLOY_PROJECT_ID.iam.gserviceaccount.com 是关联的服务账号。

Cloud Trace

ESP 和 ESPv2 调用 Cloud Trace 服务以将 Trace 导出到项目。此项目称为跟踪项目。在 ESP 中,跟踪项目和拥有端点服务配置的项目是相同的。在 ESPv2 中,跟踪项目可通过 --tracing_project_id 标志指定,默认为部署项目。

ESP 和 ESPv2 需要 Cloud Trace Agent 角色才能启用 Cloud Trace。

使用以下 gcloud 命令将该角色添加到关联的服务账号:

gcloud projects add-iam-policy-binding TRACING_PROJECT_ID \
  --member serviceAccount:SERVICE_ACCOUNT_NAME@DEPLOY_PROJECT_ID.iam.gserviceaccount.com \
  --role roles/cloudtrace.agent

其中
* TRACING_PROJECT_ID 是跟踪项目 ID
* SERVICE_ACCOUNT_NAME@DEPLOY_PROJECT_ID.iam.gserviceaccount.com是关联的服务账号。如需了解详情,请参阅 什么是角色和权限?

如需详细了解这些命令,请参阅 gcloud iam service-accounts

部署 API 后端

目前,您已将服务配置部署到 Service Management,但尚未部署将提供 API 后端的代码。本部分逐步介绍如何将示例 API 和 ESPv2 的预构建容器部署到 Kubernetes。

为 ESPv2 提供服务凭据

ESPv2 在容器内部运行,并且需要访问存储在本地 service-account-creds.json 文件中的凭据。要让 ESPv2 能够访问这些凭据,请创建 Kubernetes 密钥,并将此密钥作为 Kubernetes 卷装载。

要创建 Kubernetes 密钥并装载卷,请执行以下操作:

  1. 如果您使用 Google Cloud 控制台创建服务账号,请将 JSON 文件重命名为 service-account-creds.json。将其移至 api_descriptor.pbapi_config.yaml 文件所在的目录。
  2. 使用服务账号凭据创建 Kubernetes Secret

    kubectl create secret generic service-account-creds \
        --from-file=service-account-creds.json
    

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

    secret "service-account-creds" created

用于将 API 和 ESPv2 部署到 Kubernetes 的部署清单文件已包含 Secret 卷,如该文件的以下两个部分所示:

volumes:
- name: service-account-creds
  secret:
    secretName: service-account-creds
volumeMounts:
- mountPath: /etc/esp/creds
  name: service-account-creds
  readOnly: true

配置服务名称并启动服务

ESPv2 需要知道您的服务名称,才能找到您之前使用 gcloud endpoints services deploy 命令部署的配置。

要配置服务名称并启动服务,请执行以下操作:

  1. 将部署清单文件 grpc-bookstore.yaml 的一个副本保存到 service-account-creds.json 所在的目录中。
  2. 打开 grpc-bookstore.yaml 并将 SERVICE_NAME 替换为您的 Endpoints 服务的名称。此名称与您在 api_config.yaml 文件的 name 字段中配置的名称相同。

    containers:
    - name: esp
      image: gcr.io/endpoints-release/endpoints-runtime:2
      args: [
        "--listener_port=9000",
        "--service=SERVICE_NAME",
        "--rollout_strategy=managed",
        "--backend=grpc://127.0.0.1:8000",
        "--non_gcp",
        "--service_account_key=/etc/esp/creds/service-account-creds.json",
      ]

    --rollout_strategy=managed 选项可将 ESPv2 配置为使用最新部署的服务配置。如果指定此选项,则 ESPv2 会在您部署新服务配置后的一分钟内检测到更改并自动开始使用该服务配置。建议您指定此选项,而不是提供特定配置 ID 供 ESPv2 使用。如需详细了解 ESPv2 参数,请参阅 ESPv2 启动选项

  3. 启动服务以在 Kubernetes 上部署服务:

    kubectl create -f grpc-bookstore.yaml

    如果您看到类似以下内容的错误消息:

    The connection to the server localhost:8080 was refused - did you specify the right host or port?

    这表示未正确配置 kubectl。如需了解详情,请参阅配置 kubectl

获取服务的外部 IP 地址

如需向示例 API 发送请求,您需要具备服务的外部 IP 地址。在容器中启动服务后,外部 IP 地址可能需要过几分钟才可以使用。

  1. 查看外部 IP 地址:

    kubectl get service
  2. 请记下 EXTERNAL-IP 的值,并将其保存在 SERVER_IP 环境变量中,与向示例 API 发送请求时一样。

    export SERVER_IP=YOUR_EXTERNAL_IP
    

向 API 发送请求

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

  1. 克隆托管 gRPC 客户端代码的 Git 代码库:

    git clone https://github.com/GoogleCloudPlatform/python-docs-samples.git
       

  2. 切换您的工作目录:

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

  3. 安装依赖项:

    pip install virtualenv
    virtualenv env
    source env/bin/activate
    python -m pip install -r requirements.txt

  4. 向示例 API 发送一个请求:

    python bookstore_client.py --host SERVER_IP --port 80
    

如果未成功收到响应,请参阅排查响应错误

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