适用于 Google API 的 Private Service Connect

1. 简介

借助 Private Service Connect,您可以使用 VPC 网络内的全局内部 IP 地址创建专用端点,以访问 Google API。您可以为这些内部 IP 地址分配具有有意义的名称的 DNS 名称,例如 storage-pscendpoint.p.googleapis.com 和 bigtable-adsteam.p.googleapis.com。您可以将 API 请求发送到 VPC 网络专用的 Private Service Connect 端点,而不是将 API 请求发送到 storage.googleapis.com 等公共服务端点。

这些名称和 IP 地址是您的 VPC 网络以及使用 Cloud VPN 隧道或 Cloud Interconnect 连接 (VLAN) 连接到该网络的任何本地网络的内部。

您可以控制哪些流量会流向哪个端点,并证明流量保留在 Google Cloud 内部。

学习内容

  • Private Service Connect 用例
  • 网络要求
  • 支持的 API
  • 创建 Private Service Connect 端点
  • 创建 Cloud Storage 存储桶
  • 创建和更新 Cloud DNS 专用区域
  • 创建 NAT GW 以访问公共 googleapis
  • 创建并更新 BOTO 配置文件
  • 在针对您的 PSC 服务端点进行解析的 VM1 上执行 gsutil 列表
  • 在针对公共 googleapis.com 解析的 VM2 上执行 gsutil 列表
  • 使用 Tcpdump 验证 DNS 解析

所需条件

  • 了解 DNS、nano 或 vi 编辑器

2. Private Service Connect 用例

您可以在同一 VPC 网络中创建多个 Private Service Connect 端点。对特定端点的带宽无限制。由于 Private Service Connect 端点使用全球内部 IP 地址,因此 VPC 网络中的任何资源都可以使用它们。

借助多个端点,您可以使用 Cloud Router 路由器和防火墙规则指定不同的网络路径。

  • 您可以创建防火墙规则来阻止某些虚拟机通过 Private Service Connect 端点访问 Google API,同时允许其他虚拟机访问。
  • 您可以在虚拟机实例上设置防火墙规则,禁止所有流量流向互联网;发送到 Private Service Connect 端点的流量仍会到达 Google。
  • 如果您的本地主机使用 Cloud VPN 隧道或 Cloud Interconnect 连接 (VLAN) 连接到 VPC,则您可以通过隧道或 VLAN 发送一些请求,同时通过公共互联网发送其他请求。此配置可让您为专用 Google 访问通道不支持的服务(例如 Google 图书)绕过隧道或 VLAN。如需创建此配置,请创建一个 Private Service Connect 端点,使用 Cloud Router 路由器自定义路由通告通告 Private Service Connect 端点 IP 地址,然后启用 Cloud DNS 入站转发政策。应用可以使用 Private Service Connect 端点的名称通过 Cloud VPN 隧道或 Cloud Interconnect 连接 (VLAN) 发送一些请求,而使用默认 DNS 名称通过互联网发送其他请求。
  • 如果您使用多个 Cloud Interconnect 连接 (VLAN) 将本地网络连接到 VPC 网络,则可以通过一个 VLAN 发送一些本地流量,将其余流量通过其他 VLAN 发送,如图 2 所示。这样,您就可以使用自己的广域网而不是 Google 的广域网,并控制数据移动以满足地理要求。如需创建此配置,请创建两个 Private Service Connect 端点。为管理第一个 VLAN 的 Cloud Router 路由器的 BGP 会话上的第一个端点创建自定义路由通告,并为管理第二个 VLAN 的 Cloud Router 路由器的 BGP 会话上的第二个端点创建不同的自定义路由通告。配置为使用 Private Service Connect 端点名称的本地主机通过相应的 Cloud Interconnect 连接 (VLAN) 发送流量。
  • 您还可以在主动/主动拓扑中使用多个 Cloud Interconnect 连接 (VLAN)。如果您使用管理 VLAN 的 Cloud Router 路由器上的 BGP 会话使用自定义路由通告来通告相同的 Private Service Connect 端点 IP 地址,则系统会使用 ECMP 跨 VLAN 路由从本地系统发送到端点的数据包。

5e142c2fbf6f010e

图 1. 通过配置 Private Service Connect、Cloud Router 和本地主机,您可以控制使用哪个 Cloud Interconnect 连接 (VLAN) 将流量发送到 Google API。

3. 网络要求

如需使用 Private Service Connect,没有外部 IP 地址的虚拟机 (VM) 实例的主要接口必须位于启用了专用 Google 访问通道的子网中。

具有外部 IP 地址的虚拟机可以使用 Private Service Connect 端点访问 Google API 和服务,无论其子网是否启用了专用 Google 访问通道。与 Private Service Connect 端点的连接仍在 Google 的网络中。

无法从对等互连的 VPC 网络访问 Private Service Connect 端点。

支持的 API

创建 Private Service Connect 端点时,您需要选择需要访问的 API 包:all-apis 或 vpc-sc。

借助 API 软件包,您可以访问通过专用 Google 访问通道 VIP 提供的相同 API。

  • all-apis 软件包可让您访问与 private.googleapis.com 相同的 API。
  • vpc-sc 软件包提供与 restricted.googleapis.com 相同的 API 访问权限。

4. Codelab 拓扑和用例

2ac275eb86f26338

图 1 - Codelab 拓扑

Codelab 用例 -

我们的客户需要同时拥有专用(互连)和公共的 googleapis 访问权限才能进行 Cloud Storage 数据传输。为满足我们的客户要求,我们将部署 Private Service Connect,其中包含唯一的 /32 地址、BOTO 配置和 DNS 记录更新。虚拟机 1 将利用 PSC 访问 Cloud Storage 存储分区;相比之下,VM2 将通过 NAT GW 使用公共 googleapis.com IP 范围。

虽然本实验的各个方面均部署在 Google Cloud Platform 内,但同样的使用场景也适用于需要分离流量的混合云部署。

5. 设置和要求

自定进度的环境设置

  1. 登录 Cloud 控制台,然后创建一个新项目或重复使用现有项目。 如果您还没有 Gmail 或 Google Workspace 账号,则必须创建一个

96a9c957bc475304

b9a10ebdf5b5a448.png

a1e3c01a38fa61c2.png

请记住项目 ID,它在所有 Google Cloud 项目中都是唯一的名称(上述名称已被占用,您无法使用,抱歉!)。它稍后将在此 Codelab 中被称为 PROJECT_ID

  1. 接下来,您需要在 Cloud 控制台中启用结算功能,才能使用 Google Cloud 资源。

运行此 Codelab 应该不会产生太多的费用(如果有费用的话)。请务必按照“清理”部分部分,其中会指导您如何关停资源,以免产生超出本教程范围的结算费用。Google Cloud 的新用户符合参与 300 美元的免费试用计划的条件。

启动 Cloud Shell

虽然可以通过笔记本电脑对 Google Cloud 进行远程操作,但在此 Codelab 中,您将使用 Google Cloud Shell,这是一个在云端运行的命令行环境。

在 GCP 控制台中,点击右上角工具栏上的 Cloud Shell 图标:

bce75f34b2c53987.png

预配和连接到环境应该只需要片刻时间。完成后,您应该会看到如下内容:

f6ef2b5f13479f3a.png

这个虚拟机已加载了您需要的所有开发工具。它提供了一个持久的 5GB 主目录,并且在 Google Cloud 中运行,大大增强了网络性能和身份验证功能。只需一个浏览器,即可完成本实验中的所有工作。

6. 准备工作

启用 API

在 Cloud Shell 中,确保已设置项目 ID

gcloud config list project
gcloud config set project [YOUR-PROJECT-NAME]
projectname=YOUR-PROJECT-NAME
echo $projectname

启用所有必要的服务

gcloud services enable compute.googleapis.com
gcloud services enable servicedirectory.googleapis.com
gcloud services enable dns.googleapis.com

7. 创建 VPC 网络

VPC 网络

通过 Cloud Shell

gcloud compute networks create psc-lab --subnet-mode custom

创建子网

通过 Cloud Shell

gcloud compute networks subnets create psclab-subnet \
--network psc-lab --range 10.0.0.0/24 --region us-central1 --enable-private-ip-google-access

创建防火墙规则

要允许 IAP 连接到您的虚拟机实例,请创建以下防火墙规则:

  • 适用于您希望可以使用 IAP 访问的所有虚拟机实例。
  • 允许来自 IP 范围 35.235.240.0/20 的入站流量。此范围包含 IAP 用于 TCP 转发的所有 IP 地址。

通过 Cloud Shell

gcloud compute firewall-rules create psclab-ssh \
    --network psc-lab --allow tcp:22 --source-ranges=35.235.240.0/20

创建 Cloud NAT 实例

创建 Cloud Router

通过 Cloud Shell

gcloud compute routers create crnat \
    --network psc-lab \
    --asn 65000 \
    --region us-central1

创建 Cloud NAT

通过 Cloud Shell

gcloud compute routers nats create cloudnat \
    --router=crnat \
    --auto-allocate-nat-external-ips \
    --nat-all-subnet-ip-ranges \
    --enable-logging \
    --region us-central1

8. 创建 Private Service Connect 端点

配置 Private Service Connect 端点 IP <pscendpointip> 时,您需要提供未在 VPC 中定义的唯一 IP 地址。

通过 Cloud Shell

gcloud compute addresses create psc-ip \
    --global \
    --purpose=PRIVATE_SERVICE_CONNECT \
    --addresses=192.168.255.250 \
    --network=psc-lab

存储“pscendpointip”实验期间

pscendpointip=$(gcloud compute addresses list --filter=name:psc-ip --format="value(address)")

echo $pscendpointip

创建转发规则以将端点连接到 Google API 和服务。

通过 Cloud Shell

gcloud compute forwarding-rules create pscendpoint \
    --global \
    --network=psc-lab \
    --address=psc-ip \
    --target-google-apis-bundle=all-apis

列出已配置的 Private Service Connect 端点

通过 Cloud Shell

gcloud compute forwarding-rules list  \
--filter target="(all-apis OR vpc-sc)" --global

描述已配置的 Private Service Connect 端点

通过 Cloud Shell

gcloud compute forwarding-rules describe \
    pscendpoint --global

9. 创建存储分区

创建一个 Cloud Storage 存储分区,并将 BUCKET_NAME 替换为您偏好的全局唯一名称。

通过 Cloud Shell

gsutil mb  -l us-central1 -b on gs://BUCKET_NAME

存储“BUCKET_NAME”实验期间

BUCKET_NAME=YOUR BUCKET NAME
echo $BUCKET_NAME

10. DNS 配置

当您创建 Private Service Connect 端点时,Service Directory 会为使用该端点提供的 API 和服务生成 DNS 记录。

DNS 记录指向您的 Private Service Connect 端点 IP 地址,并采用以下格式:SERVICE-ENDPOINT.p.googleapis.com。

您可以在 API 请求中使用这些 DNS 名称,将请求定向到 Private Service Connect 端点。您也可以在请求的 Host 标头中使用这些 DNS 名称。

如果您想将 Private Service Connect 端点用于访问 Google API 和服务的客户端应用,请更新您的客户端或应用,使其使用 p.googleapis.com DNS 名称。

如需了解详情,请参阅您的客户端库或客户端库的文档。例如:

  • Python:您可以在 google-api-core 软件包的 Client options 类中配置 api_endpoint。
  • Go:您可以在 API 软件包的客户端选项软件包中配置 WithEndpoint。
  • gcloud:您可以使用此命令配置 api_endpoint_overrides。gcloud config set api_endpoint_overrides/SERVICE ENDPOINT_URL

例如:gcloud config set api_endpoint_overrides/storage https://storage-xyz.p.googleapis.com/storage/v1/

如果您无法将客户端或应用配置为使用其他端点,请创建 DNS 记录以匹配默认 DNS 名称。例如,storage.googleapis.com。请参阅使用默认 DNS 名称创建 DNS 记录

验证 DNS 记录

在 Cloud 控制台中,验证位于“网络服务”→“Cloud DNS”下生成的 DNS 条目。请注意生成的 DNS 名称“p.googleapis.com”。

11. 创建虚拟机

创建用于验证 Private Service Connect 的虚拟机 (psc-instance-1)

通过 Cloud Shell

  gcloud compute instances create psc-instance-1 \
    --subnet psclab-subnet \
    --zone us-central1-a \
    --image=centos-7-v20210122 \
    --image-project=centos-cloud \
    --no-address \
    --metadata=startup-script=yum\ install\ tcpdump\ -y$'\n'yum\ install\ bind-utils\ -y$'\n'yum\ install\ nano\ -y 

登录虚拟机实例 (psc-instance-1)

通过 Cloud Shell 通过 SSH 登录到虚拟机

gcloud compute ssh --zone "us-central1-a" "psc-instance-1" --project "$projectname"

点击“+”(下面的屏幕截图)三次,创建其他 Cloud Shell 终端。

69ea94e1527912bb

创建用于验证公共 Googleapis 的虚拟机 (psc-instance-2)

来自标签页 2

  gcloud compute instances create psc-instance-2 \
    --subnet psclab-subnet \
    --zone us-central1-a \
    --image=centos-7-v20210122 \
    --image-project=centos-cloud \
    --no-address \
    --metadata=startup-script=yum\ install\ tcpdump\ -y$'\n'yum\ install\ bind-utils\ -y$'\n'yum\ install\ nano\ -y 

从标签页 2 通过 Cloud Shell 通过 SSH 连接到虚拟机

gcloud config list project
gcloud config set project [YOUR-PROJECT-NAME]
projectname=YOUR-PROJECT-NAME
echo $projectname


gcloud compute ssh --zone "us-central1-a" "psc-instance-2" --project "$projectname"

从标签页 3 通过 Cloud Shell 通过 SSH 连接到 psc-instance-1

gcloud config list project
gcloud config set project [YOUR-PROJECT-NAME]
projectname=YOUR-PROJECT-NAME
echo $projectname


gcloud compute ssh --zone "us-central1-a" "psc-instance-1" --project "$projectname"

在标签页 4 中,通过 Cloud Shell 通过 SSH 连接到 psc-instance-2

gcloud config list project
gcloud config set project [YOUR-PROJECT-NAME]
projectname=YOUR-PROJECT-NAME
echo $projectname


gcloud compute ssh --zone "us-central1-a" "psc-instance-2" --project "$projectname"

12. 验证现有的 gsutil 行为

从标签页 4 (psc-instance-2) 中启动 tcpdump 并监控 DNS 流量

sudo tcpdump -vv -i eth0 port 53

从标签页 2 检查存储分区 DNS 查找 (psc-instance-2)

BUCKET_NAME=YOUR BUCKET NAME
echo $BUCKET_NAME
gsutil -D ls gs://$BUCKET_NAME

检查 gsutil 调试,HOST storage.googleapis.com 用于 DNS 解析

<snip>
send: 'GET /storage/v1/b/$BUCKET_NAME/o?delimiter=%2F&projection=noAcl&versions=False&fields=prefixes%2CnextPageToken%2Citems%2Fname&alt=json&maxResults=1000 HTTP/1.1\r\nHost: storage.googleapis.com\r\ncontent-length: 0\r\nauthorization: Bearer ya29.c.KpkB7wfaMjfc_WXEKCeNF4Md0fEHnfDU7tqBf3cd0u43yEmYXqj8fX_X5wWdNdDVH6k1EkjeAeIJDzKGvyjPOkf1Io2kVeUqYX69sDv53huW1NslffjAHKchbZ0CP3Cg83TS3Pa55jLcuE0TLbYycVrgSbD3H90LaapUGbWD3kj4IsJLf9J8R98Bqobu8HZwwqk92hlZ4zVzRqOM\r\naccept-encoding: gzip, deflate\r\naccept: application/json\r\nuser-agent: apitools Python/2.7.5 gsutil/4.57 (linux2) analytics/disabled interactive/True command/ls google-cloud-sdk/324.0.0\r\n\r\n'
reply: 'HTTP/1.1 200 OK\r\n'
<snip>

在标签页 4 (psc-instance-2) 中,验证访问存储分区时是否使用了 GoogleAPI.com 公共 DNS A 记录。

metadata.google.internal.domain > psc-instance-2.c.yourprojectname.internal.33973: [udp sum ok] 36442 q: A? storage.googleapis.com. 11/0/0 storage.googleapis.com. A 108.177.111.128, storage.googleapis.com. A 142.250.128.128, storage.googleapis.com. A 74.125.70.128, storage.googleapis.com. A 74.125.201.128, storage.googleapis.com. A 64.233.183.128, storage.googleapis.com. A 173.194.198.128, storage.googleapis.com. A 172.217.219.128, storage.googleapis.com. A 142.250.136.128, storage.googleapis.com. A 209.85.234.128, storage.googleapis.com. A 172.217.212.128, storage.googleapis.com. A 172.217.214.128

13. 修改 gsutil 行为

回想一下,在上一步中,您创建了映射到 PSC 端点 IP 地址的专用 DNS 区域和 A 记录。在以下步骤中,我们现在将通过更新 psc-instance-1 上的虚拟机 BOTO 文件来控制 gsutil 的行为方式。

通过标签页 1 中的虚拟机实例终端查看默认的 BOTO 配置 (psc-instance-1)

[psc-instance ~]$ more  /etc/boto.cfg

输出(您的 project_id 将有所不同)

[GSUtil]
default_project_id  = [your project number]
default_api_version = 2

[GoogleCompute]
service_account = default

使用 nano 或 VI 编辑器更新 BOTO 配置,确保复制并粘贴所有条目。

示例:sudo nano /etc/boto.cfg

示例:sudo vi /etc/boto.cfg

从虚拟机实例终端标签页 1(psc-instance-1)

[Credentials]
gs_host = storage-pscendpoint.p.googleapis.com
gs_host_header = storage.googleapis.com
gs_json_host = storage-pscendpoint.p.googleapis.com
gs_json_host_header = www.googleapis.com

验证配置,[Credentials] 的顺序对于 DNS 查找至关重要

more /etc/boto.cfg
[Credentials]
gs_host = storage-pscendpoint.p.googleapis.com
gs_host_header = storage.googleapis.com
gs_json_host = storage-pscendpoint.p.googleapis.com
gs_json_host_header = www.googleapis.com

[GSUtil]
default_project_id  = [your project number
default_api_version = 2

[GoogleCompute]
service_account = default

14. 验证更新后的 gsutil 查找行为

从标签页 3 (psc-instance-1) 中启动 tcpdump 并监控 DNS 流量

sudo tcpdump -vv -i eth0 port 53

从标签页 1 检查存储分区 gsutil 查找 (psc-instance-1)

BUCKET_NAME=YOUR BUCKET NAME
echo $BUCKET_NAME

gsutil -D ls gs://$BUCKET_NAME

调试日志确认可以通过 Private Service Connect 端点“pscendpoint”访问存储分区

输出:

<snip>
INFO 0131 22:14:18.795986 base_api.py] Making http GET to https://storage-pscendpoint.p.googleapis.com/storage/v1/b/$BUCKET_NAME/o?delimiter=%2F&projection=noAcl&versions=False&fields=prefixes%2CnextPageToken%2Citems%2Fname&alt=json&maxResults=1000
INFO 0131 22:14:18.796415 base_api.py] Headers: {u'Host': 'www.googleapis.com',
 'accept': 'application/json',
 'accept-encoding': 'gzip, deflate',
 'content-length': '0',
 'user-agent': 'apitools Python/2.7.5 gsutil/4.57 (linux2) analytics/disabled interactive/True command/ls google-cloud-sdk/324.0.0'}
INFO 0131 22:14:18.796502 base_api.py] Body: (none)
connect: (storage-pscendpoint.p.googleapis.com, 443)
send: 'GET /storage/v1/b/psc-bucket/o?delimiter=%2F&projection=noAcl&versions=False&fields=prefixes%2CnextPageToken%2Citems%2Fname&alt=json&maxResults=1000 HTTP/1.1\r\ncontent-length: 0\r\naccept-encoding: gzip, deflate\r\naccept: application/json\r\nuser-agent: apitools Python/2.7.5 gsutil/4.57 (linux2) analytics/disabled interactive/True command/ls google-cloud-sdk/324.0.0\r\nhost: www.googleapis.com\r\nauthorization: Bearer ya29.c.KpkB7wd3XWiYeRyTuth5_HPlNV-hPwc2Nn7RSIeMpzrpa_j4EsMPl2m_mDGKAcGHvYIgiC5bT2UVQirAPpSbbpToa6G6lkaBbH5SZwHwgNXYfisp5Ww1UjXe4rTa69a_Wp0WesafcwPNnYzDo3xf5VGh3iGhySA04kTXuyT--MgOU8U-XLII2LJQxUWlV8KEdrvyCuqRb-jsDdk_\r\n\r\n'
reply: 'HTTP/1.1 200 OK\r\n'
<snip>

在标签页 3 (psc-instance-1) 中,验证您的 PSC 端点 IP 是否为尝试访问存储分区时使用的 DNS A 记录。

@psc-instance-1 ~]$ sudo tcpdump -vv -i eth0 port 53
tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
05:02:33.936256 IP (tos 0x0, ttl 64, id 55416, offset 0, flags [DF], proto UDP (17), length 82)
    psc-instance-1.c.yourprojectname.internal.42296 > metadata.google.internal.domain: [bad udp cksum 0x5e4e -> 0xcceb!] 34796+ A? storage-pscendpoint.p.googleapis.com. (54)
05:02:33.936269 IP (tos 0x0, ttl 64, id 55417, offset 0, flags [DF], proto UDP (17), length 82)
    psc-instance-1.c.yourprojectname.internal.42296 > metadata.google.internal.domain: [bad udp cksum 0x5e4e -> 0x3ebd!] 5632+ AAAA? storage-pscendpoint.p.googleapis.com. (54)
05:02:33.944018 IP (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto UDP (17), length 98)
    metadata.google.internal.domain > psc-instance-1.c.yourprojectname.42296: [udp sum ok] 34796 q: A? storage-pscendpoint.p.googleapis.com. 1/0/0 storage-pscendpoint.p.googleapis.com. A 10.10.110.10 (70)
05:02:33.946005 IP (tos 0x0, ttl 64, id 0, offset 0, flags [none], proto UDP (17), length 175)

验证 Private Service Connect 端点 IP 是否已用于 DNS 解析

来自 tab1

nslookup storage-pscendpoint.p.googleapis.com

输出

@psc-instance ~]$ nslookup storage-pscendpoint.p.googleapis.com
Server:         169.254.169.254
Address:        169.254.169.254#53

Non-authoritative answer:
Name:   storage-pscendpoint.p.googleapis.com
Address: <pscip>

15. 清理步骤

退出虚拟机实例(所有标签页)

exit

从单个 Cloud Shell 终端删除实验组件

gcloud compute routers nats delete cloudnat --router=crnat --region=us-central1 --quiet

gcloud compute routers delete crnat --region=us-central1 --quiet

gcloud compute forwarding-rules delete pscendpoint --global --quiet

gcloud compute addresses delete psc-ip --global --quiet

gsutil rm -r gs://$BUCKET_NAME

gcloud compute instances delete psc-instance-1 --zone=us-central1-a --quiet

gcloud compute instances delete psc-instance-2 --zone=us-central1-a --quiet

gcloud compute firewall-rules delete psclab-ssh --quiet

gcloud compute networks subnets delete psclab-subnet --region us-central1 --quiet

gcloud compute networks delete psc-lab --quiet

在控制台中,确保您查看的是正确的项目,然后选择“网络服务”→“Cloud DNS”

16. 恭喜!

恭喜您完成此 Codelab。

所学内容

  • Private Service Connect 用例
  • 网络要求
  • 支持的 API
  • 已创建 Private Service Connect 端点
  • 已创建 Cloud Storage 存储分区
  • 更新了 BOTO 配置文件
  • 已创建 NAT GW
  • 在 VM1 上执行 gsutil 列表,以针对您的 PSC 服务端点进行解析
  • 在 VM2 上执行针对公共 googleapis.com 进行解析的 gsutil 列表
  • 使用 Tcpdump 验证 DNS 解析