调用与 VPC Service Controls 兼容的专用端点

您可以将 Service Directory 的服务注册表与 Workflows 搭配使用,从而为工作流执行过程中的 HTTP 调用指定专用端点。通过在 Virtual Private Cloud (VPC) 网络中创建专用端点,该端点可以兼容 VPC Service Controls。

VPC Service Controls 提供一层独立于 Identity and Access Management (IAM) 的额外安全防御。IAM 可实现精细的“基于身份的访问权限控制”,而 VPC Service Controls 可实现更广泛的基于上下文的边界安全性,包括控制跨边界的数据出站流量。

  • Service Directory 是一个服务注册表,用于存储已注册的网络服务的相关信息,包括其名称、位置和属性。无论其基础架构如何,您都可以自动注册服务并捕获其详细信息。这样,您就可以为您的所有服务端点大规模地发现、发布和连接服务。

  • VPC 网络可为您的虚拟机 (VM) 实例提供连接,并允许您使用内部 IP 地址在 VPC 网络内创建专用端点。在强制执行 IAM 和 VPC Service Controls 时,对 VPC 网络资源的 HTTP 调用通过专用网络发送。

  • VPC Service Controls 是 Google Cloud 的一项功能,可让您设置服务边界并创建数据传输边界。您可以将 VPC Service Controls 与 Workflows 搭配使用,以帮助保护您的服务并降低数据渗漏的风险。

本文档介绍如何将 VPC 网络中的虚拟机注册为 Service Directory 端点。这样,您就可以为工作流提供 Service Directory 服务名称。工作流执行过程使用从服务注册表中检索到的信息来发送相应的 HTTP 请求,而不会出站到公共网络。

下图进行了简要介绍:

使用 Service Directory 中的信息向虚拟机实例上的端口号发送 HTTP 请求

概括来讲,您必须执行以下操作:

  1. 向 Cloud Workflows 服务代理授予权限,以便服务代理可以查看 Service Directory 资源并使用 Service Directory 访问 VPC 网络。
  2. 创建 VPC 网络以提供网络功能。
  3. 创建 VPC 防火墙规则,以便允许或拒绝传入或传出 VPC 网络中的虚拟机实例的流量。
  4. 在 VPC 网络中创建虚拟机实例。Compute Engine 虚拟机实例是托管在 Google 基础架构上的虚拟机。术语“Compute Engine 实例”、“虚拟机实例”和“虚拟机”是同义词,可互换使用。
  5. 在虚拟机上部署应用。您可以在虚拟机实例上运行应用,并确认流量是否按预期传送。
  6. 配置 Service Directory,以便工作流执行作业可以调用 Service Directory 端点。
  7. 创建和部署工作流。工作流中的 private_service_name 值指定您在上一步中注册的 Service Directory 端点。

向 Cloud Workflows 服务代理授予权限

某些 Google Cloud 服务具有服务代理,让服务可以访问您的资源。如果 API 需要服务代理,则 Google 会在您激活并使用 API 后创建服务代理。

  1. 首次部署工作流时,系统会自动使用以下格式创建 Cloud Workflows 服务代理:

    service-PROJECT_NUMBER@gcp-sa-workflows.iam.gserviceaccount.com

    您可以使用以下命令在项目中手动创建服务帐号,而无需执行任何工作流:

    gcloud beta services identity create \
        --service=workflows.googleapis.com \
        --project=PROJECT_ID

    PROJECT_ID 替换为您的 Google Cloud 项目 ID。

  2. 如需查看 Service Directory 资源,请将项目的 Service Directory Viewer 角色 (servicedirectory.viewer) 授予 Workflows 服务代理:

    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member=serviceAccount:service-PROJECT_NUMBER@gcp-sa-workflows.iam.gserviceaccount.com \
        --role=roles/servicedirectory.viewer

    PROJECT_NUMBER 替换为您的 Google Cloud 项目编号。您可以在 Google Cloud 控制台的欢迎页面上或者通过运行以下命令找到项目编号:

    gcloud projects describe PROJECT_ID --format='value(projectNumber)'
  3. 如需使用 Service Directory 访问 VPC 网络,请将项目的 Private Service Connect 授权服务角色 (roles/servicedirectory.pscAuthorizedService) 授予 Workflows 服务代理:

    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member=serviceAccount:service-PROJECT_NUMBER@gcp-sa-workflows.iam.gserviceaccount.com \
        --role=roles/servicedirectory.pscAuthorizedService

创建 VPC 网络

VPC 网络是物理网络的虚拟版本,在 Google 的生产网络内实现。可为 Compute Engine 虚拟机实例提供连接。

您可以创建自动模式或自定义模式 VPC 网络。您创建的每个新网络在同一项目中必须具有唯一的名称。

例如,以下命令会创建一个自动模式 VPC 网络:

gcloud compute networks create NETWORK_NAME \
    --subnet-mode=auto

NETWORK_NAME 替换为 VPC 网络的名称。

如需了解详情,请参阅创建和管理 VPC 网络

创建 VPC 防火墙规则

通过 VPC 防火墙规则,您可以根据端口号、标记或协议允许或拒绝传入或传出 VPC 网络中的虚拟机实例的流量。

VPC 防火墙规则是在网络级别定义的,仅会应用于在其中创建它们的网络;但是,您为规则选择的名称在项目中必须是唯一的。

例如,以下命令为指定的 VPC 网络创建防火墙规则,并允许来自任何 IPv4 地址 0.0.0.0/0 的入站流量。all--rules 标志值使规则适用于所有协议和所有目的地端口。

gcloud compute firewall-rules create RULE_NAME \
    --network=projects/PROJECT_ID/global/networks/NETWORK_NAME \
    --direction=INGRESS \
    --action=ALLOW \
    --source-ranges=0.0.0.0/0 \
    --rules=all

RULE_NAME 替换为防火墙规则的名称。

如需了解详情,请参阅使用 VPC 防火墙规则

在 VPC 网络中创建虚拟机实例

虚拟机实例包括 Google Kubernetes Engine (GKE) 集群、App Engine 柔性环境实例以及在 Compute Engine 虚拟机上构建的其他 Google Cloud 产品。为了支持专用网络访问,VPC 网络资源可以是虚拟机实例、Cloud Interconnect IP 地址或第 4 层内部负载均衡器。

Compute Engine 实例可以运行 Google 提供的 Linux 和 Windows Server 的公共映像,以及您可以从现有系统创建或导入的私有自定义映像。您还可以部署 Docker 容器。

您可以通过使用一组预定义机器类型或创建自己的自定义机器类型,来选择实例的机器属性,例如虚拟 CPU 数量和内存量。

例如,以下命令通过具有网络接口连接到您之前创建的 VPC 网络的公共映像创建 Linux 虚拟机实例。

  1. 创建并启动虚拟机实例:

    gcloud compute instances create VM_NAME \
        --image-family=debian-11 \
        --image-project=debian-cloud \
        --machine-type=e2-micro \
        --network-interface network=projects/PROJECT_ID/global/networks/NETWORK_NAME

    VM_NAME 替换为虚拟机名称。

  2. 如果系统提示您确认实例的可用区,请输入 y

    创建虚拟机实例后,请记下返回的 INTERNAL_IP 地址。

  3. 在 Google Cloud 控制台中,转到虚拟机实例页面。

    进入“虚拟机实例”

  4. 名称列中,点击相应虚拟机实例的名称。

  5. 如果虚拟机正在运行,如需停止虚拟机,请点击 停止

  6. 如需修改虚拟机,请点击 修改

  7. 网络 > 防火墙部分中,如需允许传入虚拟机的 HTTP 或 HTTPS 流量,请选择允许 HTTP 流量允许 HTTPS 流量

    在本示例中,请选中允许 HTTP 流量复选框。

    Compute Engine 会向虚拟机添加网络标记,用于将防火墙规则与虚拟机相关联。然后,它会创建相应的入站防火墙规则,允许 tcp:80 (HTTP) 或 tcp:443 (HTTPS) 上的所有传入流量。

  8. 要保存更改,请点击保存

  9. 如需重启虚拟机,请点击启动/恢复

如需了解详情,请参阅创建并启动虚拟机实例

在虚拟机上部署应用

如需测试网络配置并确认流量是否按预期传送,您可以在虚拟机上部署一个监听端口的简单应用。

例如,以下命令会创建监听端口 3000 的 Node.js Web 服务。

  1. 与虚拟机实例建立 SSH 连接

  2. 更新您的软件包代码库:

    sudo apt update
  3. 安装 NVMNode.jsnpm

    如需了解详情,请参阅设置 Node.js 开发环境

  4. 以交互方式创建一个 package.json 文件:

    npm init

    例如:

    {
    "name": "test",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
    "test": "hello"
    },
    "author": "",
    "license": "ISC"
    }
  5. 安装适用于 Node.js 的 Web 应用框架 Express

    npm install express
  6. 为测试应用编写代码:

    vim app.js

    以下示例将创建一个应用,该应用会以文本“Hello, world!”响应对根路径 (/) 的 GET 请求。

    const express = require('express');
    const app = express();
    
    app.get('/', (req, res) => {
      res.status(200).send('Hello, world!').end();
    });
    
    app.listen(3000, () => {
      console.log('Sample app listening on port 3000.');
    });

    记下应用正在监听的端口。为 Service Directory 服务配置端点时,必须使用相同的端口号。

  7. 确认应用正在监听端口 3000:

    node app.js

Compute Engine 提供了各种部署选项。如需了解详情,请参阅为您的工作负载选择 Compute Engine 部署策略

配置 Service Directory

如需支持在工作流执行中调用专用端点,您必须设置 Service Directory 命名空间,在命名空间中注册服务,并向服务添加端点。

例如,以下命令会创建命名空间、服务以及指定虚拟机实例的 VPC 网络和内部 IP 地址的端点。

  1. 创建命名空间:

    gcloud service-directory namespaces create NAMESPACE \
        --location=REGION
    

    请替换以下内容:

    • NAMESPACE:命名空间的 ID 或命名空间的完全限定标识符。
    • REGION:包含命名空间的 Google Cloud 区域;例如 us-central1
  2. 创建服务:

    gcloud service-directory services create SERVICE \
        --namespace=NAMESPACE \
        --location=REGION
    

    SERVICE 替换为您要创建的服务的名称。

  3. 配置端点。

    gcloud service-directory endpoints create ENDPOINT \
        --namespace=NAMESPACE \
        --service=SERVICE \
        --network=projects/PROJECT_NUMBER/locations/global/networks/NETWORK_NAME \
        --port=PORT_NUMBER \
        --address=IP_ADDRESS \
        --location=REGION
    

    请替换以下内容:

    • ENDPOINT:您要创建的端点的名称。
    • PORT_NUMBER:运行端点的端口;例如 3000
    • IP_ADDRESS:端点的 IPv6 或 IPv4 地址;这是您之前记下的内部 IP 地址。

如需了解详情,请参阅配置 Service Directory配置专用网络访问

创建和部署工作流

从 Workflows 调用或调用专用端点是通过 HTTP 请求完成的。最常见的 HTTP 请求方法具有调用快捷方式(例如 http.gethttp.post),但您可以通过将 call 字段设置为 http.request 并使用 method 字段指定请求类型来发出任何类型的 HTTP 请求。如需了解详情,请参阅发出 HTTP 请求

  1. 为工作流创建源代码文件:

    touch call-private-endpoint.JSON_OR_YAML
    

    根据工作流的格式,将 JSON_OR_YAML 替换为 yamljson

  2. 在文本编辑器中,将以下工作流(在本例中为 url 值使用 HTTP 协议)复制到源代码文件中:

    YAML

    main:
      steps:
        - checkHttp:
            call: http.get
            args:
              url: http://IP_ADDRESS
              private_service_name: "projects/PROJECT_ID/locations/REGION/namespaces/NAMESPACE/services/SERVICE"
            result: res
        - ret:
            return: ${res}

    JSON

    {
      "main": {
        "steps": [
          {
            "checkHttp": {
              "call": "http.get",
              "args": {
                "url": "http://IP_ADDRESS",
                "private_service_name": "projects/PROJECT_ID/locations/REGION/namespaces/NAMESPACE/services/SERVICE"
              },
              "result": "res"
            }
          },
          {
            "ret": {
              "return": "${res}"
            }
          }
        ]
      }
    }

    private_service_name 值必须是一个字符串,采用以下格式指定已注册的 Service Directory 服务名称:

    projects/PROJECT_ID/locations/LOCATION/namespaces/NAMESPACE_NAME/services/SERVICE_NAME

  3. 部署工作流。为便于测试,您可以将 Compute Engine 默认服务帐号附加到工作流以表示其身份:

    gcloud workflows deploy call-private-endpoint \
        --source=call-private-endpoint.JSON_OR_YAML \
        --location=REGION \
        --service-account=PROJECT_NUMBER-compute@developer.gserviceaccount.com
    
  4. 执行工作流:

    gcloud workflows run call-private-endpoint \
        --location=REGION

    您应该会看到类似于以下内容的结果:

    argument: 'null'
    duration: 0.650784403s
    endTime: '2023-06-09T18:19:52.570690079Z'
    name: projects/968807934019/locations/us-central1/workflows/call-private-endpoint/executions/4aac88d3-0b54-419b-b364-b6eb973cc932
    result: '{"body":"Hello, world!","code":200,"headers":{"Connection":"keep-alive","Content-Length":"21","Content-Type":"text/html;
    charset=utf-8","Date":"Fri, 09 Jun 2023 18:19:52 GMT","Etag":"W/\"15-NFaeBgdti+9S7zm5kAdSuGJQm6Q\"","Keep-Alive":"timeout=5","X-Powered-By":"Express"}}'
    startTime: '2023-06-09T18:19:51.919905676Z'
    state: SUCCEEDED
    

后续步骤