Private Service Connect 健康状况

1. 简介

此 Codelab 将探讨 Private Service Connect (PSC) 健康状况,以实现自动区域故障切换。PSC 健康状况是一项网络功能,可提高服务弹性和可用性。

借助 PSC 健康状况,服务提供方可以定义自定义健康状况政策(状态定义了健康或不健康的服务),并自动将这些信号传播给通过 PSC 后端连接到服务的使用方。此功能专门用于支持自动跨区域故障切换。如果区域性提供方服务运行状况不佳,使用方负载平衡器会自动停止将流量路由到该区域,并将流量定向到另一区域中运行状况良好的服务。

与之前的跨区域故障切换方法(例如离群值检测)相比,PSC 健康状况可提供更准确的故障切换信号,因为它直接基于提供方服务后端(虚拟机实例组或网络端点)的汇总健康状况。提供方可以定义自己的健康状况逻辑,确保只有当服务真正满足必要的健康状况条件时,提供方才会接收流量。

学习内容

  • PSC 健康状况的组成部分以及它们如何协同工作来确定生产者服务的健康状态
  • 使用 gcloud 命令为提供方服务实现 PSC 健康检查
  • 配置跨区域 PSC 使用方访问负载平衡器以使用提供方 PSC 健康状况政策中的健康信号
  • 测试服务故障场景并验证自动跨区域故障切换

所需条件

  • Google Cloud 项目
  • 授予预定义 roles/compute.admin 角色或广泛的基本角色(如 roles/admin 或旧版 roles/owner)的 IAM 权限
  • 熟悉 Google Cloud 网络概念并会使用 Google Cloud CLI

2. 概念

PSC 网络

此 Codelab 网络拓扑包含两个有效 Google Cloud 区域中的使用方和提供方 VPC 网络。

使用方一侧具有区域级子网,其中包含用于通过 跨区域内部应用负载平衡器(使用 PSC 网络端点组 (NEG) 后端)访问提供方服务的客户端虚拟机实例。有两条区域级负载平衡器转发规则,使用区域级 IP 地址,用于全球(跨区域)客户端入站流量。后端服务是一种全球资源,支持不同区域中的 NEG。在故障切换场景中,连接到任一区域级前端转发规则的客户端都可以被定向到运行状况良好的全球级后端。

figure1

图 1. Codelab 网络拓扑

提供方一侧具有区域级子网,其中包含区域级内部直通式网络负载平衡器,可通过区域级 PSC 服务附件资源公开服务。后端服务包含区域性代管式实例组 (MIG),并通过探测 http 请求和验证 200 (OK) 响应来检查健康状况

请参阅有关 Private Service Connect 兼容性的最新文档,了解提供方配置,以查看哪些负载平衡器支持 PSC 健康检查。

服务健康状况

在创建负载平衡器期间配置的提供方后端服务健康检查可作为 PSC 健康状况功能的原始信号。健康状况来源资源会使用该信号以及健康状况汇总政策资源中定义的其他限制条件来确定单个后端服务的健康状态

默认情况下,当同时满足以下两个限制条件时,服务会被视为运行状况良好:

  • 至少有 x% 的后端健康状况良好(默认值为 60
  • 至少有 y 个后端健康(默认值为 1

复合健康检查会引用所有后端服务的所有健康状况来源,以确定整个区域级提供方服务的总体健康状况。在本实验中,每个区域级生产者服务都只有一个后端服务健康状况来源,汇总到一个复合健康检查中。

figure2

图 2. PSC 健康状况资源模型

复合健康检查资源定义还引用了生产者服务负载平衡器的转发规则。使用方访问负载平衡器后端 PSC NEG 在逻辑上连接到提供方 PSC 服务连接和提供方负载平衡器转发规则。这会将使用方访问负载平衡器与提供方服务的复合健康检查状态相关联。然后,区域级提供方服务的总体健康状况会传播到使用方负载平衡器,以便选择合适的后端。

3. 项目设置

访问您的项目

此 Codelab 旨在让您使用单个 Google Cloud 项目。配置步骤使用 gcloud 和 Linux shell 命令。

注意:在生产环境部署中,PSC 使用方资源和提供方服务通常位于不同的项目中。

首先,使用以下命令访问 Google Cloud 云项目命令行:

设置项目 ID

gcloud config set project YOUR_PROJECT_ID_HERE

设置 shell 环境变量

export PROJECT_ID=$(gcloud config list --format="value(core.project)")
export REGION_1="us-west1"
export ZONE_1="us-west1-c"
export REGION_2="us-east1"
export ZONE_2="us-east1-c"
echo ${PROJECT_ID}
echo ${REGION_1}
echo ${ZONE_1}
echo ${REGION_2}
echo ${ZONE_2}

启用 API 服务

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

4. 提供方服务

创建共享资源

创建网络

gcloud compute networks create vnet-producer --subnet-mode=custom

创建子网

# create subnet for service workload in region 1
gcloud compute networks subnets create subnet-foo \
  --network=vnet-producer \
  --region=${REGION_1} \
  --range=172.16.1.0/24 \
  --enable-private-ip-google-access

# create subnet for psc nat in region 1
gcloud compute networks subnets create subnet-foo-pscnat \
  --network=vnet-producer \
  --region=${REGION_1} \
  --range=192.168.1.0/29 \
  --purpose=PRIVATE_SERVICE_CONNECT
# create subnet for service workload in region 2
gcloud compute networks subnets create subnet-bar \
  --network=vnet-producer \
  --region=${REGION_2} \
  --range=172.16.2.0/24 \
  --enable-private-ip-google-access

# create subnet for psc nat in region 2
gcloud compute networks subnets create subnet-bar-pscnat \
  --network=vnet-producer \
  --region=${REGION_2} \
  --range=192.168.2.0/29 \
  --purpose=PRIVATE_SERVICE_CONNECT

创建防火墙组件

需要防火墙规则来允许流量进入虚拟机资源(隐式默认防火墙规则是拒绝入站流量并允许出站流量)。政策是部署防火墙规则的首选方式,具体做法是创建网络防火墙政策资源,创建规则并将其添加到政策中,然后将政策与 VPC 网络相关联。

# create fw policy
gcloud compute network-firewall-policies create fw-policy-producer --global
# create fw policy rules
gcloud compute network-firewall-policies rules create 1001 \
  --description="allow iap for ssh" \
  --firewall-policy=fw-policy-producer \
  --global-firewall-policy \
  --action=allow \
  --direction=INGRESS \
  --layer4-configs=tcp:22  \
  --src-ip-ranges=35.235.240.0/20

gcloud compute network-firewall-policies rules create 1002 \
  --description="allow health checks" \
  --firewall-policy=fw-policy-producer \
  --global-firewall-policy \
  --action=allow \
  --direction=INGRESS \
  --layer4-configs=tcp,udp,icmp  \
  --src-ip-ranges=130.211.0.0/22,35.191.0.0/16

gcloud compute network-firewall-policies rules create 1003 \
  --description="allow psc nat clients" \
  --firewall-policy=fw-policy-producer \
  --global-firewall-policy \
  --action=allow \
  --direction=INGRESS \
  --layer4-configs=tcp:80  \
  --src-ip-ranges=192.168.1.0/29,192.168.2.0/29
# associate fw policy to vnet
gcloud compute network-firewall-policies associations create \
  --firewall-policy=fw-policy-producer \
  --network=vnet-producer \
  --name=fw-policy-association-producer \
  --global-firewall-policy

创建 Cloud Router 路由器和 NAT 网关

# create routers for nat in each region
gcloud compute routers create cr-nat-foo \
  --network=vnet-producer \
  --asn=16550 \
  --region=${REGION_1}

gcloud compute routers create cr-nat-bar \
  --network=vnet-producer \
  --asn=16550 \
  --region=${REGION_2}
# create nat gateways in each region
gcloud compute routers nats create natgw-foo \
  --router=cr-nat-foo \
  --region=${REGION_1} \
  --auto-allocate-nat-external-ips \
  --nat-all-subnet-ip-ranges

gcloud compute routers nats create natgw-bar \
  --router=cr-nat-bar \
  --region=${REGION_2} \
  --auto-allocate-nat-external-ips \
  --nat-all-subnet-ip-ranges

创建具有 HTTP 服务器的虚拟机启动配置

cat > vm-server-startup.sh << 'EOF'
#! /bin/bash
apt-get update
apt-get install apache2 -y
vm_hostname="$(curl -H "Metadata-Flavor:Google" \
http://169.254.169.254/computeMetadata/v1/instance/name)"
vm_zone="$(curl -H "Metadata-Flavor:Google" \
http://169.254.169.254/computeMetadata/v1/instance/zone)"
echo "Page served from: $vm_hostname in zone $vm_zone" | \
tee /var/www/html/index.html
systemctl restart apache2
EOF

在区域 1 中设置服务 foo

创建服务计算

# create managed instance group template
gcloud compute instance-templates create mig-template-foo \
  --machine-type=e2-micro \
  --network=vnet-producer \
  --region=${REGION_1} \
  --subnet=subnet-foo \
  --no-address \
  --shielded-secure-boot \
  --metadata-from-file=startup-script=vm-server-startup.sh
# create regional managed instance group
gcloud compute instance-groups managed create mig-foo \
  --region=${REGION_1} \
  --size=2 \
  --template=mig-template-foo \
  --base-instance-name=service-foo

创建服务负载平衡器组件

# create lb health check
gcloud compute health-checks create http hc-foo-http \
  --region=${REGION_1} \
  --port=80 \
  --enable-logging
# create backend service
gcloud compute backend-services create ilb-foo \
  --load-balancing-scheme=INTERNAL \
  --protocol=tcp \
  --region=${REGION_1} \
  --health-checks=hc-foo-http \
  --health-checks-region=${REGION_1}

# add managed instance group to backend service
gcloud compute backend-services add-backend ilb-foo \
  --instance-group=mig-foo \
  --instance-group-region=${REGION_1} \
  --region=${REGION_1}
# create forwarding rule
gcloud compute forwarding-rules create fr-foo \
  --region=${REGION_1} \
  --load-balancing-scheme=INTERNAL \
  --network=vnet-producer \
  --subnet=subnet-foo \
  --address=172.16.1.99 \
  --ip-protocol=TCP \
  --ports=80 \
  --backend-service=ilb-foo \
  --backend-service-region=${REGION_1} \
  --allow-global-access

发布 PSC 服务

# create psc service attachment
gcloud compute service-attachments create psc-sa-foo \
  --region=${REGION_1} \
  --target-service=projects/${PROJECT_ID}/regions/${REGION_1}/forwardingRules/fr-foo \
  --connection-preference=ACCEPT_AUTOMATIC \
  --nat-subnets=subnet-foo-pscnat

在区域 2 中设置服务 bar

创建服务计算

# create managed instance group template
gcloud compute instance-templates create mig-template-bar \
  --machine-type=e2-micro \
  --network=vnet-producer \
  --region=${REGION_2} \
  --subnet=subnet-bar \
  --no-address \
  --shielded-secure-boot \
  --metadata-from-file=startup-script=vm-server-startup.sh
# create regional managed instance group
gcloud compute instance-groups managed create mig-bar \
  --region=${REGION_2} \
  --size=2 \
  --template=mig-template-bar \
  --base-instance-name=service-bar

创建服务负载平衡器组件

# create lb health check
gcloud compute health-checks create http hc-bar-http \
  --region=${REGION_2} \
  --port=80 \
  --enable-logging
# create backend service
gcloud compute backend-services create ilb-bar \
  --load-balancing-scheme=INTERNAL \
  --protocol=tcp \
  --region=${REGION_2} \
  --health-checks=hc-bar-http \
  --health-checks-region=${REGION_2}

# add managed instance group to backend service
gcloud compute backend-services add-backend ilb-bar \
  --instance-group=mig-bar \
  --instance-group-region=${REGION_2} \
  --region=${REGION_2}
# create forwarding rule
gcloud compute forwarding-rules create fr-bar \
  --region=${REGION_2} \
  --load-balancing-scheme=INTERNAL \
  --network=vnet-producer \
  --subnet=subnet-bar \
  --address=172.16.2.99 \
  --ip-protocol=TCP \
  --ports=80 \
  --backend-service=ilb-bar \
  --backend-service-region=${REGION_2} \
  --allow-global-access

发布 PSC 服务

# create psc service attachment
gcloud compute service-attachments create psc-sa-bar \
  --region=${REGION_2} \
  --target-service=projects/${PROJECT_ID}/regions/${REGION_2}/forwardingRules/fr-bar \
  --connection-preference=ACCEPT_AUTOMATIC \
  --nat-subnets=subnet-bar-pscnat

5. 消费者访问权限

设置客户端资源

创建网络组件

# create vpc network
gcloud compute networks create vnet-consumer --subnet-mode=custom
# create client subnet in each region
gcloud compute networks subnets create subnet-client-1 \
  --network=vnet-consumer \
  --region=${REGION_1} \
  --range=10.10.1.0/24 \
  --enable-private-ip-google-access

gcloud compute networks subnets create subnet-client-2 \
  --network=vnet-consumer \
  --region=${REGION_2} \
  --range=10.10.2.0/24 \
  --enable-private-ip-google-access

消费者应用(基于代理)负载平衡器需要代理专用子网。这些子网提供了一个 IP 地址池,基于代理的负载平衡器在向后端发送流量时会使用其中的 IP 地址作为内部源地址。

# create proxy subnet in each region
gcloud compute networks subnets create subnet-proxy-1 \
  --purpose=GLOBAL_MANAGED_PROXY \
  --role=ACTIVE \
  --network=vnet-consumer \
  --region=${REGION_1} \
  --range=10.10.128.0/23

gcloud compute networks subnets create subnet-proxy-2 \
  --purpose=GLOBAL_MANAGED_PROXY \
  --role=ACTIVE \
  --network=vnet-consumer \
  --region=${REGION_2} \
  --range=10.10.130.0/23

创建防火墙组件

# create fw policy
gcloud compute network-firewall-policies create fw-policy-consumer --global
# create fw policy rules
gcloud compute network-firewall-policies rules create 1001 \
  --description="allow iap for ssh" \
  --firewall-policy=fw-policy-consumer \
  --global-firewall-policy \
  --action=allow \
  --direction=INGRESS \
  --layer4-configs=tcp:22  \
  --src-ip-ranges=35.235.240.0/20
# associate fw policy to vnet
gcloud compute network-firewall-policies associations create \
  --firewall-policy=fw-policy-consumer \
  --network=vnet-consumer \
  --name=fw-policy-association-consumer \
  --global-firewall-policy

创建负载均衡器组件

# create psc network endpoint group per region
gcloud compute network-endpoint-groups create neg-foo \
  --network-endpoint-type=private-service-connect \
  --psc-target-service=projects/${PROJECT_ID}/regions/${REGION_1}/serviceAttachments/psc-sa-foo \
  --region=${REGION_1} \
  --network=vnet-consumer \
  --subnet=subnet-client-1

gcloud compute network-endpoint-groups create neg-bar \
  --network-endpoint-type=private-service-connect \
  --psc-target-service=projects/${PROJECT_ID}/regions/${REGION_2}/serviceAttachments/psc-sa-bar \
  --region=${REGION_2} \
  --network=vnet-consumer \
  --subnet=subnet-client-2
# verify psc connections
gcloud compute network-endpoint-groups list --format="value(selfLink, pscData.pscConnectionStatus)"
# create global backend service
gcloud compute backend-services create bes-foobar \
  --load-balancing-scheme=INTERNAL_MANAGED \
  --protocol=HTTP \
  --global
# add negs to backend service
gcloud compute backend-services add-backend bes-foobar \
  --network-endpoint-group=neg-foo \
  --network-endpoint-group-region=${REGION_1} \
  --global

gcloud compute backend-services add-backend bes-foobar \
  --network-endpoint-group=neg-bar \
  --network-endpoint-group-region=${REGION_2} \
  --global
# create global url map
gcloud compute url-maps create ilb-foobar \
  --default-service=bes-foobar \
  --global
# create global target proxy
gcloud compute target-http-proxies create proxy-foobar \
  --url-map=ilb-foobar \
  --global
# create global forwarding rule for region 1
gcloud compute forwarding-rules create fr-foobar-1 \
  --load-balancing-scheme=INTERNAL_MANAGED \
  --network=vnet-consumer \
  --subnet=subnet-client-1 \
  --subnet-region=${REGION_1} \
  --address=10.10.1.99 \
  --ports=80 \
  --target-http-proxy=proxy-foobar \
  --global
# create global forwarding rule for region 2
gcloud compute forwarding-rules create fr-foobar-2 \
  --load-balancing-scheme=INTERNAL_MANAGED \
  --network=vnet-consumer \
  --subnet=subnet-client-2 \
  --subnet-region=${REGION_2} \
  --address=10.10.2.99 \
  --ports=80 \
  --target-http-proxy=proxy-foobar \
  --global

创建 DNS 记录

# create dns zone
gcloud dns managed-zones create zone-foobar \
  --description="private zone for foobar" \
  --dns-name=foobar.com \
  --networks=vnet-consumer \
  --visibility=private
# create geo dns record
gcloud dns record-sets create www.foobar.com \
  --zone=zone-foobar \
  --type=A \
  --ttl=300 \
  --routing-policy-type=GEO \
  --routing-policy-item="location=${REGION_1},rrdatas=10.10.1.99" \
  --routing-policy-item="location=${REGION_2},rrdatas=10.10.2.99"

创建计算资源

# create client vm in region 1
gcloud compute instances create client-1 \
  --machine-type=e2-micro \
  --zone=${ZONE_1} \
  --subnet=subnet-client-1 \
  --no-address \
  --shielded-secure-boot
# create client vm in region 2
gcloud compute instances create client-2 \
  --machine-type=e2-micro \
  --zone=${ZONE_2} \
  --subnet=subnet-client-2 \
  --no-address \
  --shielded-secure-boot

测试服务基准

通过 SSH 连接到区域 1 中的客户端虚拟机

gcloud compute ssh client-1 --zone=${ZONE_1}
# send request to service using hostname
curl -v www.foobar.com
# send request to load balancer forwarding rule region 1
curl 10.10.1.99
# send request to load balancer forwarding rule region 2
curl 10.10.2.99
# exit vm ssh
exit

可选:尝试从区域 2 中的客户端虚拟机运行相同的测试:gcloud compute ssh client-2 --zone=${ZONE_2}

关键点:对于通过 region-x 中的转发规则进入的客户端请求,负载平衡器的正常行为是优先选择同一 region-x 中的后端。如果所有后端资源的健康状况良好,则延迟最低的区域胜出。全局后端将故障切换到具有适当健康信号的其他区域。

但由于实际的提供方服务资源位于提供方 VPC 网络中的提供方负载平衡器后面,因此使用方负载平衡器之前无法获取这些健康状况信号,也就无法做出此类后端故障切换判定。PSC 健康状况通过将服务健康状况信息从提供方传播到使用方来解决此问题。

6. 健康类资源

PSC 健康状况资源由提供方配置,用于表示区域级服务的总体健康状况。健康状况政策基于服务提供方为维持正常运行的服务等级而定义的适当措施。设置阈值是为了在不再满足提供方定义的条件时通知消费者进行故障切换。

在区域 1 中设置服务健康状况 foo

创建健康状况汇总政策

gcloud beta compute health-aggregation-policies create foo-health-policy \
  --region=${REGION_1} \
  --healthy-percent-threshold=60 \
  --min-healthy-threshold=1

创建健康状况来源

gcloud beta compute health-sources create foo-health-source \
  --region=${REGION_1} \
  --source-type=BACKEND_SERVICE \
  --sources=ilb-foo \
  --health-aggregation-policy=foo-health-policy

创建复合健康检查

gcloud beta compute composite-health-checks create foo-health-composite \
  --region=${REGION_1} \
  --health-sources=foo-health-source \
  --health-destination=projects/${PROJECT_ID}/regions/${REGION_1}/forwardingRules/fr-foo

验证服务 foo 健康状况配置

可以使用 list(和 describe)命令按区域查看健康资源配置

# show health aggregation policies
gcloud beta compute health-aggregation-policies list --regions=${REGION_1}

# show health sources
gcloud beta compute health-sources list --regions=${REGION_1}

# show composite health checks
gcloud beta compute composite-health-checks list --regions=${REGION_1}

在区域 2 中设置服务健康状况 bar

创建健康状况汇总政策

gcloud beta compute health-aggregation-policies create bar-health-policy \
  --region=${REGION_2} \
  --healthy-percent-threshold=60 \
  --min-healthy-threshold=1

创建健康状况来源

gcloud beta compute health-sources create bar-health-source \
  --region=${REGION_2} \
  --source-type=BACKEND_SERVICE \
  --sources=ilb-bar \
  --health-aggregation-policy=bar-health-policy

创建复合健康检查

gcloud beta compute composite-health-checks create bar-health-composite \
  --region=${REGION_2} \
  --health-sources=bar-health-source \
  --health-destination=projects/${PROJECT_ID}/regions/${REGION_2}/forwardingRules/fr-bar

验证服务 bar 健康状况配置

# show health aggregation policies
gcloud beta compute health-aggregation-policies list --regions=${REGION_2}

# show health sources
gcloud beta compute health-sources list --regions=${REGION_2}

# show composite health checks
gcloud beta compute composite-health-checks list --regions=${REGION_2}

配置部分到此结束,接下来是测试。

7. 故障切换测试

服务 foo 区域 1 健康状况不佳的场景

此方案通过停止两个虚拟机实例中的一个上的 Web 服务器,模拟区域 1 中 PSC 提供方服务 foo 的故障。

获取服务器虚拟机的详细信息

# set env var for a foo service vm name
export FOO_FAIL_NAME=$(gcloud compute instance-groups managed list-instances mig-foo \
  --limit=1 \
  --region=${REGION_1} \
  --format="value(name)")
echo ${FOO_FAIL_NAME}
# set env var for a foo service zone
export FOO_FAIL_ZONE=$(gcloud compute instance-groups managed list-instances mig-foo \
  --limit=1 \
  --region=${REGION_1} \
  --format="value(ZONE)")
echo ${FOO_FAIL_ZONE}

通过 SSH 连接到服务器虚拟机并停止 http 服务器

gcloud compute ssh ${FOO_FAIL_NAME} --zone=${FOO_FAIL_ZONE}
# stop apache http server to fail service
sudo systemctl stop apache2
# verify service dead
sudo systemctl status apache2 | grep Active:
# exit vm ssh
exit

验证区域服务是否健康状况不佳

# check health state of backend service
gcloud compute backend-services get-health ilb-foo --region=${REGION_1}

输出应类似于以下内容...

backend: .../regions/<REGION_1>/instanceGroups/mig-foo
status:
  healthStatus:
  -   forwardingRule: .../regions/<REGION_1>/forwardingRules/fr-foo
    forwardingRuleIp: 172.16.1.99
    healthState: UNHEALTHY
    instance: .../zones/<ZONE_1x>/instances/<FOO_FAIL_NAME>
    ipAddress: <FOO_FAIL_IP>
    port: 80
  -   forwardingRule: .../regions/<REGION_1>/forwardingRules/fr-foo
    forwardingRuleIp: 172.16.1.99
    healthState: HEALTHY
    instance: .../zones/<ZONE_1y>/instances/<FOO_OTHER_NAME>
    ipAddress: <FOO_OTHER_IP>
    port: 80
  kind: compute#backendServiceGroupHealth

通过 SSH 连接到区域 1 客户端虚拟机并测试故障切换

gcloud compute ssh client-1 --zone=${ZONE_1}
# send request to service using hostname
curl -v www.foobar.com
# curl to ilb vip in region 1
curl 10.10.1.99
# curl to ilb vip in region 2
curl 10.10.2.99

PSC 健康状况已更新使用方负载平衡器,并指示其避开区域 1 中运行状况不佳的后端服务。而是将流量定向到区域 2 中运行状况良好的服务 bar

# exit client vm ssh
exit

通过 SSH 连接到服务器虚拟机并重启 http 服务器

# ssh to foo service vm
gcloud compute ssh ${FOO_FAIL_NAME} --zone=${FOO_FAIL_ZONE}
# start apache http server to return service to healthy
sudo systemctl start apache2
# verify service running
sudo systemctl status apache2 | grep Active:
# exit vm ssh
exit

更改健康状况政策

生产者可以根据不同的条件调整服务健康状况政策。健康状况汇总政策资源用于指定最低阈值,以确保所有不同健康状况来源(后端服务)的健康状况良好。

更新 bar 服务健康状况汇总政策

gcloud beta compute health-aggregation-policies update bar-health-policy \
  --region=${REGION_2} \
  --description="min 40% threshold" \
  --healthy-percent-threshold=40 \
  --min-healthy-threshold=2
# verify new policy is applied
gcloud beta compute health-aggregation-policies list --regions=${REGION_2}

生产者健康状况政策变更实现了以下目标:

  1. 将状况良好判断阈值下限百分比从 60% 降至 40% - 现在,单个虚拟机实例故障将不会根据 --healthy-percent-threshold 触发运行状况不佳状态(故障状态将为 50%,而只需 40% 即可达到状况良好状态)
  2. 将后端健康状况良好的最低数量从 1 个增加到 2 个虚拟机实例 - 现在,单个虚拟机实例发生故障根据 --min-healthy-threshold 触发健康状况不佳状态(故障状态将为 1,但需要 2 才能健康)

服务 bar 区域 2 健康状况不佳场景

此方案通过停止两个虚拟机实例中的一个上的 Web 服务器,模拟区域 2 中 PSC 提供方服务 bar 的故障。

获取服务器虚拟机的详细信息

# set env var for a bar service vm name
export BAR_FAIL_NAME=$(gcloud compute instance-groups managed list-instances mig-bar \
  --limit=1 \
  --region=${REGION_2} \
  --format="value(name)")
echo ${BAR_FAIL_NAME}
# set env var for a bar service zone
export BAR_FAIL_ZONE=$(gcloud compute instance-groups managed list-instances mig-bar \
  --limit=1 \
  --region=${REGION_2} \
  --format="value(ZONE)")
echo ${BAR_FAIL_ZONE}

通过 SSH 连接到服务器虚拟机并停止 http 服务器

gcloud compute ssh ${BAR_FAIL_NAME} --zone=${BAR_FAIL_ZONE}
# stop apache http server to fail service
sudo systemctl stop apache2
# verify service dead
sudo systemctl status apache2 | grep Active:
# exit vm ssh
exit

验证区域服务是否健康状况不佳

# check health state of backend service
gcloud compute backend-services get-health ilb-bar --region=${REGION_2}

输出应类似于以下内容...

backend: .../regions/<REGION_2>/instanceGroups/mig-bar
status:
  healthStatus:
  -   forwardingRule: .../regions/<REGION_2>/forwardingRules/fr-bar
    forwardingRuleIp: 172.16.2.99
    healthState: UNHEALTHY
    instance: .../zones/<ZONE_2x>/instances/<BAR_FAIL_NAME>
    ipAddress: <BAR_FAIL_IP>
    port: 80
  -   forwardingRule: .../regions/<REGION_2>/forwardingRules/fr-bar
    forwardingRuleIp: 172.16.2.99
    healthState: HEALTHY
    instance: .../zones/<ZONE_2y>/instances/<BAR_OTHER_NAME>
    ipAddress: <BAR_OTHER_IP>
    port: 80
  kind: compute#backendServiceGroupHealth

通过 SSH 连接到区域 2 客户端虚拟机并测试故障切换

gcloud compute ssh client-2 --zone=${ZONE_2}
# send request to service using hostname
curl -v www.foobar.com
# curl to ilb vip in region 1
curl 10.10.1.99
# curl to ilb vip in region 2
curl 10.10.2.99

PSC 健康状况已更新使用方负载平衡器,并指示其避开区域 2 中运行状况不佳的后端服务。而是将流量定向到区域 1 中运行状况良好的服务 foo

如果使用方负载平衡器将所有提供方服务都视为运行状况不佳,则负载平衡器无法故障切换到运行状况良好的实例。预期行为是负载平衡器将流量分配到所有运行状况不佳的后端(故障开放)。

# exit client vm ssh
exit

测试部分到此结束…接下来是清理工作。

8. 清理

# delete health resources
gcloud -q beta compute composite-health-checks delete foo-health-composite --region=${REGION_1}

gcloud -q beta compute health-sources delete foo-health-source --region=${REGION_1}

gcloud -q beta compute health-aggregation-policies delete foo-health-policy --region=${REGION_1}

gcloud -q beta compute composite-health-checks delete bar-health-composite --region=${REGION_2}

gcloud -q beta compute health-sources delete bar-health-source --region=${REGION_2}

gcloud -q beta compute health-aggregation-policies delete bar-health-policy --region=${REGION_2}
# delete consumer compute and load balancer resources
gcloud -q compute instances delete client-2 --zone=${ZONE_2}

gcloud -q compute instances delete client-1 --zone=${ZONE_1}

gcloud -q dns record-sets delete www.foobar.com --type=A --zone=zone-foobar

gcloud -q dns managed-zones delete zone-foobar

gcloud -q compute forwarding-rules delete fr-foobar-2 --global

gcloud -q compute forwarding-rules delete fr-foobar-1 --global

gcloud -q compute target-http-proxies delete proxy-foobar --global

gcloud -q compute url-maps delete ilb-foobar --global

gcloud -q compute backend-services delete bes-foobar --global


# delete consumer network resources
gcloud -q compute network-endpoint-groups delete neg-bar --region=${REGION_2}

gcloud -q compute network-endpoint-groups delete neg-foo --region=${REGION_1}

gcloud -q compute networks subnets delete subnet-proxy-2 --region=${REGION_2}

gcloud -q compute networks subnets delete subnet-proxy-1 --region=${REGION_1}

gcloud -q compute networks subnets delete subnet-client-2 --region=${REGION_2}

gcloud -q compute networks subnets delete subnet-client-1 --region=${REGION_1}

gcloud -q compute network-firewall-policies associations delete \
  --firewall-policy=fw-policy-consumer \
  --name=fw-policy-association-consumer \
  --global-firewall-policy

gcloud -q compute network-firewall-policies delete fw-policy-consumer --global

gcloud -q compute networks delete vnet-consumer
# delete producer load balancer resources
gcloud -q compute service-attachments delete psc-sa-bar --region=${REGION_2}

gcloud -q compute service-attachments delete psc-sa-foo --region=${REGION_1}

gcloud -q compute forwarding-rules delete fr-bar --region=${REGION_2}

gcloud -q compute forwarding-rules delete fr-foo --region=${REGION_1}

gcloud -q compute backend-services delete ilb-bar --region=${REGION_2}

gcloud -q compute backend-services delete ilb-foo --region=${REGION_1}

gcloud -q compute health-checks delete hc-bar-http --region=${REGION_2}

gcloud -q compute health-checks delete hc-foo-http --region=${REGION_1}
# delete producer compute resources
gcloud -q compute instance-groups managed delete mig-bar --region=${REGION_2}

gcloud -q compute instance-groups managed delete mig-foo --region=${REGION_1}

gcloud -q compute instance-templates delete mig-template-bar --global

gcloud -q compute instance-templates delete mig-template-foo --global
# delete producer network resources
gcloud -q compute networks subnets delete subnet-bar-pscnat --region=${REGION_2}

gcloud -q compute networks subnets delete subnet-foo-pscnat --region=${REGION_1}

gcloud -q compute networks subnets delete subnet-bar --region=${REGION_2}

gcloud -q compute networks subnets delete subnet-foo --region=${REGION_1}

gcloud -q compute routers delete cr-nat-bar --region=${REGION_2}

gcloud -q compute routers delete cr-nat-foo --region=${REGION_1}

gcloud -q compute network-firewall-policies associations delete \
  --firewall-policy=fw-policy-producer \
  --name=fw-policy-association-producer \
  --global-firewall-policy

gcloud -q compute network-firewall-policies delete fw-policy-producer --global

gcloud -q compute networks delete vnet-producer
# delete shell variables and script file
unset FOO_FAIL_NAME FOO_FAIL_ZONE BAR_FAIL_NAME BAR_FAIL_ZONE

unset PROJECT_ID REGION_1 ZONE_1 REGION_2 ZONE_2

rm vm-server-startup.sh
#

9. 总结

恭喜!您已成功配置 PSC 健康状况并测试了自动区域级故障切换!

欢迎使用此反馈表单提出任何意见、问题或更正。

谢谢!