在本地或其他平台上运行可扩展服务代理

本页面介绍了如何在本地机器、Amazon Web Services (AWS) 之类的其他云服务商平台或非 Google Cloud 平台上的 Kubernetes 集群中配置和运行 Extensible Service Proxy (ESP) 实例。

您可以在 Linux 或 macOS 计算机或虚拟机 (VM) 上运行 ESP。Microsoft Windows 不受支持。您可以在同一主机或不同主机上部署您的应用和 ESP。通过托管 ESP 的本地实例,您可以达到以下目的:

  • 在将 ESP 部署到生产平台之前先进行试用。
  • 核实安全设置已配置且正常运作,并且 Endpoints > 服务页面如期显示指标和日志。

前提条件

首先,本页面假定您已完成以下操作:

  • 您已安装 Docker(如果要在本地部署 ESP 容器或部署到虚拟机)。如需了解详情,请参阅安装 Docker

  • 您已在本地或在可连接到要运行 ESP 的主机上部署 API。

  • 已配置 Cloud Endpoints已部署相关配置,可为 API 创建托管式服务。

如果您需要一个 API 来进行 ESP 测试,则可以配置并部署可选:使用示例 API 中的示例代码。如果您已配置并部署您的 API,请跳转至创建服务账号

可选:使用示例 API

本部分逐步介绍如何在本地配置和部署 Python 版本的 Endpoints getting-started 示例。仅当您没有 API 用来进行 ESP 测试时,才执行本部分中的步骤。

Cloud Endpoints getting-started 示例提供其他语言版本。 请参阅示例页面,了解按您的首选语言提供的 getting-started 示例在 GitHub 上的位置。请按照示例的 README.md 文件中的说明在本地运行,然后按照本部分中的说明配置 Endpoints 并部署 Endpoints 配置。

获取所需软件

如果您尚未设置 Python 开发环境,请参阅设置 Python 开发环境以获取相关指导。请确保已安装以下工具:

获取示例代码

  1. 将示例应用代码库克隆到本地机器:

    git clone https://github.com/GoogleCloudPlatform/python-docs-samples
    
  2. 转到包含示例代码的目录:

    cd python-docs-samples/endpoints/getting-started
    

配置 Endpoints

  1. 在示例代码目录中,打开 openapi.yaml 配置文件。

    swagger: "2.0"
    info:
      description: "A simple Google Cloud Endpoints API example."
      title: "Endpoints Example"
      version: "1.0.0"
    host: "echo-api.endpoints.YOUR-PROJECT-ID.cloud.goog"
  2. host 字段中,将 YOUR-PROJECT-ID 替换为您自己的 Google Cloud 项目 ID。

  3. 保存 openapi.yaml 文件。

部署 Endpoints 配置

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

  1. 更新 gcloud CLI:

    gcloud components update
  2. 确保 gcloud CLI (gcloud) 有权访问您在 Google Cloud 上的数据和服务:

    gcloud auth login

    在浏览器打开的新标签页中,选择一个账号。

  3. 将默认项目设置为您的项目 ID:

    gcloud config set project YOUR-PROJECT-ID
    

    YOUR-PROJECT-ID 替换为您在 openapi.yaml 文件中指定的 Google Cloud 项目的 ID。

  4. 部署您的配置:

    gcloud endpoints services deploy openapi.yaml

Service Management 会使用您在 openapi.yaml 文件的 host 字段中指定的文本新建一项名为 echo-api.endpoints.YOUR-PROJECT-ID.cloud.goog 的 Endpoints 服务(若该服务不存在),然后根据您的 OpenAPI 配置文件配置该服务。

在创建和配置服务时,Service Management 会向终端输出信息。您尽可忽略有关 openapi.yaml 文件中的路径未要求使用 API 密钥的警告。成功完成后,您会看到如下所示的一行内容,服务配置 ID 和服务名称显示在方括号内:

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

在上面的示例中,2017-02-13r0 是服务配置 ID,echo-api.endpoints.example-project-12345.cloud.goog 是服务名称。

启动本地服务器

  1. 创建 virtualenv 并将其激活,然后安装应用依赖项。

    virtualenv env
    source env/bin/activate
    pip install -r requirements.txt
    
  2. 启动服务器:

    python main.py
    
  3. 打开另一个终端窗口,并使用 curl 发送请求:

    curl --request POST \
      --header "content-type:application/json" \
      --data '{"message":"hello world"}' \
      http://localhost:8080/echo
    

    API 会回显您向其发送的消息,并以如下内容作为响应:

    {
    "message": "hello world"
    }
    

创建服务账号

为了管理您的 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

在容器中运行 ESP

本部分介绍如何部署 ESP 容器。您要执行的步骤取决于您在哪里部署 ESP 容器:

在以下示例中,ESP 选项 --http_port 仅在 gRPC 服务配置了 HTTP/JSON 转码时才有效。如需了解详情,请参阅将 HTTP/JSON 转码为 gRPC

在本地或其他平台上的 Docker 容器中运行 ESP

  1. 将包含服务账号私钥的 JSON 文件重命名为 service-account-creds.json,并将其复制到 $HOME/Downloads/(如果此文件之前被下载到其他目录)。这样,完整路径名称便会与以下 docker run 命令中 --service_account_key 的值匹配。

  2. 在以下 docker run 命令中,将 YOUR_SERVICE_NAME 替换为您的服务名称

Linux

sudo docker run \
    --detach \
    --name="esp" \
    --net="host" \
    --volume=$HOME/Downloads:/esp \
    --publish=8082 \
    gcr.io/endpoints-release/endpoints-runtime:1 \
    --service=YOUR_SERVICE_NAME \
    --rollout_strategy=managed \
    --http_port=8082 \
    --http2_port=8083 \
    --backend=grpc://localhost:8080 \
    --service_account_key=/esp/service-account-creds.json
  

macOS

Docker --net="host" 选项不适用于 macOS。因此,您必须明确执行从主机到容器的端口映射,并将 --net="host" 替换为 --publish 8082:8082。您还需要将 localhost 替换为 macOS 专用的特殊 DNS 名称 docker.for.mac.localhost。如需了解详情,请参阅 Docker 文档中的用例和变通方案

sudo docker run \
  --detach \
  --name="esp" \
  --publish=8082:8082 \
  --volume=$HOME/Downloads:/esp \
  gcr.io/endpoints-release/endpoints-runtime:1 \
  --service=YOUR_SERVICE_NAME \
  --rollout_strategy=managed \
  --http_port=8082 \
  --http2_port=8083 \
  --backend=grpc://docker.for.mac.localhost:8080 \
  --service_account_key=/esp/service-account-creds.json
  

其他平台

sudo docker run \
  --detach \
  --name="esp" \
  --net="host" \
  --volume=$HOME/Downloads:/esp \
  --publish=8082 \
  gcr.io/endpoints-release/endpoints-runtime:1 \
  --service=YOUR_SERVICE_NAME \
  --rollout_strategy=managed \
  --http_port=8082 \
  --http2_port=8083 \
  --backend=grpc://IP_Address:PORT \
  --service_account_key=/esp/service-account-creds.json
  

下表介绍了上述命令中使用的 Docker 选项。如需了解示例中使用的 ESP 选项,请参阅 ESP 启动选项

选项 说明
--detach 此 Docker 选项将以分离模式启动容器,以使其在后台运行。
--name="esp" 此 Docker 选项可为容器提供便于访问的名称。 例如,如需查看容器生成的日志,可以运行 docker logs esp
--net="host" 此 Docker 选项表示 Docker 容器应使用与宿主机相同的网络配置,从而使该容器可以在宿主机上调用 localhost 上的服务。此选项不适用于在本地 macOS 计算机上运行 ESP 的情况。
--publish=8082:8082 若要在 macOS 本地运行 ESP,请使用此 Docker 选项(而不是 --net="host")明确执行从主机到容器的端口映射。
--volume=
$HOME/Downloads:/esp
此 Docker 选项可将本地 $HOME/Downloads 目录映射到容器中的 /esp 目录。此映射由 --service_account_key ESP 选项使用。

在 Kubernetes 集群上的容器中运行 ESP

本部分介绍如何将 ESP 部署到非 Google Cloud 上的 Kubernetes 集群。

如需让 Endpoints 管理您的 API,请将 ESP 容器部署到与 API 容器相同的 Kubernetes pod。运行 ESP 和 API 的一组 pod 通过标签选择器(例如 app: my-api)划分到一个 Kubernetes 服务下。Kubernetes 服务会指定访问政策,以对发送到代理端口的客户端请求执行负载平衡。

  1. 将包含服务账号私钥的 JSON 文件重命名为 service-account-creds.json,并将其复制到 $HOME/Downloads/(如果此文件之前被下载到其他目录)。这样,完整路径名称便会与以下步骤中的命令匹配。

  2. 运行以下命令以创建 Kubernetes Secret,并将该 Secret 作为 Kubernetes 卷进行装载。

    kubectl create secret generic service-account-creds \
      --from-file=$HOME/Downloads/service-account-creds.json
    

    成功后,系统会显示以下消息:secret "service-account-creds" created

  3. 在 Kubernetes 配置文件中,添加以下内容,并将 YOUR_APP_NAME 替换为您的 API 的名称,将 YOUR_SERVICE_NAME 替换为您的服务名称

    spec:
    replicas: 1
    template:
      metadata:
        labels:
          app: "YOUR_APP_NAME"
      spec:
        volumes:
          - name: service-account-creds
            secret:
              secretName: service-account-creds
              containers:
          - name: esp
            image: gcr.io/endpoints-release/endpoints-runtime:1
            args: [
              "--http_port=8082",
              "--http2_port=8083",
              "--backend=grpc://127.0.0.1:8081",
              "--service=YOUR_SERVICE_NAME",
              "--rollout_strategy=managed",
              "--service_account_key=/etc/nginx/creds/service-account-creds.json"
            ]
            ports:
              - containerPort: 8080
            volumeMounts:
              - mountPath: /etc/nginx/creds
                name: service-account-creds
                readOnly: true
    

    如需了解示例中使用的 ESP 选项,请参阅 ESP 启动选项

  4. 将 ESP 部署到 Kubernetes。将 YOUR_CONFIGURATION_FILE 替换为您的 Kubernetes 配置文件的名称。

    kubectl apply -f YOUR_CONFIGURATION_FILE

发送请求

如需确认服务帐号文件是否正确以及端口是否已正确映射,请向您的 API 发送一些请求,并确保请求经过 ESP。您可以通过运行以下命令来查看 ESP 日志:

sudo docker logs esp

以下示例向示例 API 发送请求。如果您未使用示例 API,我们建议您运行类似的测试。

您已将 ESP 容器配置为在端口 8082 上接收请求。如果您通过 http://localhost:8080 直接向服务器发送请求,这些请求将绕过 ESP。例如:

curl --request POST \
  --header "content-type:application/json" \
  --data '{"message":"hello world"}' \
  http://localhost:8080/echo

响应:

  {
    "message": "hello world"
  }

如果您向 http://localhost:8082 发送经过 ESP 的请求,但未发送 API 密钥,则 ESP 会拒绝该请求。例如:

curl --request POST \
  --header "content-type:application/json" \
  --data '{"message":"hello world"}' \
  http://localhost:8082/echo

响应:

  {
   "code": 16,
   "message": "Method doesn't allow unregistered callers (callers without
    established identity). Please use API Key or other form of API consumer
    identity to call this API.",
   "details": [
    {
     "@type": "type.googleapis.com/google.rpc.DebugInfo",
     "stackEntries": [],
     "detail": "service_control"
    }
   ]
  }

要使用 API 密钥测试 API,请执行以下操作:

  1. API 凭据页面上创建 API 密钥。

    转到“凭据”页面

  2. 点击创建凭据,然后选择 API 密钥

  3. 复制该密钥,然后将其粘贴到以下环境变量语句中:

    export KEY=AIza...
    
  4. 使用该密钥发送请求:

    curl --request POST \
      --header "content-type:application/json" \
      --data '{"message":"hello world"}' \
      http://localhost:8082/echo?key=$KEY

    您会看到成功响应:

    {
      "message": "hello world"
    }

清理

使用 docker 工具关闭并移除 esp Docker 容器:

    sudo docker stop esp
    sudo docker rm esp
若要清理已部署的服务配置,请参阅删除 API 和 API 实例

后续步骤