在本地或其他平台上运行 Extensible Service Proxy

本页面介绍了如何在本地机器、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. 更新 Cloud SDK:

    gcloud components update
    
  2. 确保 Cloud SDK (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 需要使用 Service Infrastructure 中的服务。ESP 必须使用访问令牌才能调用这些服务。 当您将 ESP 部署到 Google Cloud 环境(例如 GKE 或 Compute Engine)时,ESP 会通过 Google Cloud 元数据服务为您获取访问令牌。

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

您可以使用 Cloud Console 或 gcloud 命令行工具创建服务帐号和私钥文件,并为服务帐号分配以下角色:

控制台

  1. 在 Cloud Console 中,打开服务帐号页面。

    转到“服务帐号”页面

  2. 点击选择项目
  3. 选择在其中创建了 API 的项目,并点击打开
  4. 点击 + 创建服务帐号
  5. 服务帐号名称字段中,输入您的服务帐号的名称。
  6. 点击创建
  7. 点击选择角色,然后选择 Service Management > Service Controller
  8. 点击 + 添加其他角色
  9. 点击选择角色,然后选择 Cloud Trace > Cloud Trace Agent
  10. 点击继续
  11. 点击 + 创建密钥
  12. 在右侧面板中,为密钥类型使用默认类型 JSON
  13. 点击创建
  14. 在对话框中,点击关闭
  15. 点击完成

如此即会创建服务帐号并将其私钥下载为一个 JSON 文件。

gcloud

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

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

    gcloud config set project PROJECT_ID
    
  3. 确保 Cloud SDK (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
    
  6. 添加 Service Controller 角色:

    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member serviceAccount:SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com \
        --role roles/servicemanagement.serviceController
    
  7. 添加 Cloud Trace Agent 角色以启用 Cloud Trace:

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

如需详细了解这些命令,请参阅 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 实例

后续步骤