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

您可以将工作流执行过程中的 HTTP 调用指定到专用端点, 将 Service Directory 的服务注册表与 Workflows 搭配使用。 通过在虚拟私有云 (VPC) 网络中创建专用端点,该端点可以符合 VPC Service Controls 要求。

VPC Service Controls 提供一层额外的、独立于 Identity and Access Management (IAM) 的安全防御。虽然 IAM 支持 基于身份的精细访问权限控制,VPC Service Controls 可实现更广泛的 基于上下文的边界安全性,包括控制整个 Google Cloud 范围内的数据出站流量 边界。

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

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

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

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

下图提供了概览:

使用来自服务目录的信息向虚拟机实例上的端口号发送 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 资源,请向 Workflows 服务代理授予项目的 Service Directory Viewer 角色 (servicedirectory.viewer):

    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 Authorized Service 角色 (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/0all--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 实例可以运行适用于 Linux 和 Windows 的公共映像 以及 Google 提供的私有自定义映像, 是创建还是从现有系统导入。您还可以部署 Docker 容器。

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

例如,以下命令通过公共 IP 地址 具有连接到您所用 VPC 网络的网络接口的映像 创建 Deployment

  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. 如果虚拟机正在运行,请点击 Stop 以停止虚拟机。

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

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

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

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

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

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

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

在虚拟机上部署应用

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

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

  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. 安装 Express,这是一个适用于 Node.js 的 Web 应用框架:

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

    vim app.js

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

    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 地址的端点 虚拟机实例的 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配置专用网络访问

创建和部署工作流

从工作流调用或调用专用端点是通过 HTTP 请求完成的。最常见的 HTTP 请求方法都有一个调用 快捷方式(例如 http.gethttp.post),但您可以将任何 将 call 字段设置为 http.request,然后指定 HTTP 请求的类型 使用 method 字段指定请求的类型。如需更多信息 请参阅发出 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

后续步骤