本文档将引导您完成以下操作:跨不同区域中的两个 GKE 集群部署示例应用,并展示多集群网关如何在流量超出服务容量限制时智能地路由流量。
基于容量的负载均衡是多集群网关的一项功能,可帮助您构建高度可靠且富有弹性的应用。通过定义服务的容量,您可以保护服务免受过载影响,并帮助确保为用户提供一致的体验。当一个集群中的服务达到其容量上限时,负载均衡器会自动将流量重定向到另一个具有可用容量的集群。如需详细了解流量管理,请参阅 GKE 流量管理。
在本教程中,您将使用示例 store 应用来模拟以下现实场景:在线购物服务由单独的团队拥有和运营,并且跨共享 GKE 集群舰队进行部署。
准备工作
多集群 Gateway 需要一些环境准备才能部署。在继续操作之前,请按照为多集群 Gateway 准备环境 中的步骤操作:
最后,请先查看 GKE Gateway Controller 的限制和已知问题,然后才可在环境中使用该控制器。
部署基于容量的负载均衡
本部分中的练习通过跨不同区域的两个 GKE 集群部署应用来演示全球负载均衡和 Service 容量概念。生成的流量按各种每秒请求数 (RPS) 级别发送,以显示如何跨集群和区域对流量进行负载均衡。
下图展示了您将部署的拓扑,以及当流量超出 Service 容量时,流量如何在集群和区域之间溢出:
准备环境
按照为多集群 Gateway 准备环境中的说明准备环境。
确认配置集群上已安装 GatewayClass 资源:
kubectl get gatewayclasses --context=gke-west-1输出内容类似如下:
NAME CONTROLLER ACCEPTED AGE gke-l7-global-external-managed networking.gke.io/gateway True 16h gke-l7-global-external-managed-mc networking.gke.io/gateway True 14h gke-l7-gxlb networking.gke.io/gateway True 16h gke-l7-gxlb-mc networking.gke.io/gateway True 14h gke-l7-regional-external-managed networking.gke.io/gateway True 16h gke-l7-regional-external-managed-mc networking.gke.io/gateway True 14h gke-l7-rilb networking.gke.io/gateway True 16h gke-l7-rilb-mc networking.gke.io/gateway True 14h
部署应用
将示例 Web 应用服务器部署到这两个集群:
kubectl apply --context gke-west-1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/master/gateway/docs/store-traffic-deploy.yaml
kubectl apply --context gke-east-1 -f https://raw.githubusercontent.com/GoogleCloudPlatform/gke-networking-recipes/master/gateway/docs/store-traffic-deploy.yaml
输出内容类似如下:
namespace/store created
deployment.apps/store created
部署 Service、Gateway 和 HTTPRoute
将以下
Service清单同时应用于gke-west-1和gke-east-1集群:cat << EOF | kubectl apply --context gke-west-1 -f - apiVersion: v1 kind: Service metadata: name: store namespace: traffic-test annotations: networking.gke.io/max-rate-per-endpoint: "10" spec: ports: - port: 8080 targetPort: 8080 name: http selector: app: store type: ClusterIP --- kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: store namespace: traffic-test EOFcat << EOF | kubectl apply --context gke-east-1 -f - apiVersion: v1 kind: Service metadata: name: store namespace: traffic-test annotations: networking.gke.io/max-rate-per-endpoint: "10" spec: ports: - port: 8080 targetPort: 8080 name: http selector: app: store type: ClusterIP --- kind: ServiceExport apiVersion: net.gke.io/v1 metadata: name: store namespace: traffic-test EOF此 Service 的
max-rate-per-endpoint设置为每秒 10 个请求。每个集群有 2 个副本,每个 Service 的每个集群有 20 RPS 容量。如需详细了解如何为 Service 选择 Service 容量级别,请参阅确定 Service 的容量。
将以下
Gateway清单应用于配置集群(在此示例中为gke-west-1):cat << EOF | kubectl apply --context gke-west-1 -f - kind: Gateway apiVersion: gateway.networking.k8s.io/v1 metadata: name: store namespace: traffic-test spec: gatewayClassName: gke-l7-global-external-managed-mc listeners: - name: http protocol: HTTP port: 80 allowedRoutes: kinds: - kind: HTTPRoute EOF该清单描述了一个外部全球多集群 Gateway,用于部署具有可公开访问的 IP 地址的外部应用负载均衡器。
将以下
HTTPRoute清单应用于配置集群(在此示例中为gke-west-1):cat << EOF | kubectl apply --context gke-west-1 -f - kind: HTTPRoute apiVersion: gateway.networking.k8s.io/v1 metadata: name: store namespace: traffic-test labels: gateway: store spec: parentRefs: - kind: Gateway namespace: traffic-test name: store rules: - backendRefs: - name: store group: net.gke.io kind: ServiceImport port: 8080 EOF该清单描述了一个 HTTPRoute,用于使用将所有流量定向到 store ServiceImport 的路由规则配置 Gateway。
storeServiceImport 会将跨两个集群的storeService Pod 分组,并允许负载均衡器将它们作为单个 Service 进行寻址。几分钟后,您可以检查 Gateway 的事件,以了解其是否已完成部署:
kubectl describe gateway store -n traffic-test --context gke-west-1输出内容类似如下:
... Status: Addresses: Type: IPAddress Value: 34.102.159.147 Conditions: Last Transition Time: 2023-10-12T21:40:59Z Message: The OSS Gateway API has deprecated this condition, do not depend on it. Observed Generation: 1 Reason: Scheduled Status: True Type: Scheduled Last Transition Time: 2023-10-12T21:40:59Z Message: Observed Generation: 1 Reason: Accepted Status: True Type: Accepted Last Transition Time: 2023-10-12T21:40:59Z Message: Observed Generation: 1 Reason: Programmed Status: True Type: Programmed Last Transition Time: 2023-10-12T21:40:59Z Message: The OSS Gateway API has altered the "Ready" condition semantics and reservedit for future use. GKE Gateway will stop emitting it in a future update, use "Programmed" instead. Observed Generation: 1 Reason: Ready Status: True Type: Ready Listeners: Attached Routes: 1 Conditions: Last Transition Time: 2023-10-12T21:40:59Z Message: Observed Generation: 1 Reason: Programmed Status: True Type: Programmed Last Transition Time: 2023-10-12T21:40:59Z Message: The OSS Gateway API has altered the "Ready" condition semantics and reservedit for future use. GKE Gateway will stop emitting it in a future update, use "Programmed" instead. Observed Generation: 1 Reason: Ready Status: True Type: Ready Name: http Supported Kinds: Group: gateway.networking.k8s.io Kind: HTTPRoute Events: Type Reason Age From Message ---- ------ ---- ---- ------- Normal ADD 12m mc-gateway-controller traffic-test/store Normal SYNC 6m43s mc-gateway-controller traffic-test/store Normal UPDATE 5m40s (x4 over 12m) mc-gateway-controller traffic-test/store Normal SYNC 118s (x6 over 10m) mc-gateway-controller SYNC on traffic-test/store was a success此输出显示 Gateway 已成功部署。在部署 Gateway 后,流量可能需要几分钟时间才能开始通过。记下此输出中的 IP 地址,因为在接下来的步骤中会用到。
确认流量
使用 curl 命令测试 Gateway IP 地址,以确认流量正在传递给应用:
curl GATEWAY_IP_ADDRESS
输出内容类似如下:
{
"cluster_name": "gke-west-1",
"host_header": "34.117.182.69",
"pod_name": "store-54785664b5-mxstv",
"pod_name_emoji": "👳🏿",
"project_id": "project",
"timestamp": "2021-11-01T14:06:38",
"zone": "us-west1-a"
}
此输出会显示 Pod 元数据,表明处理请求所在的区域。
使用负载测试验证流量
如需验证负载均衡器是否正常运行,您可以在 gke-west-1 集群中部署流量生成器。流量生成器在不同的负载级别生成流量,以演示负载均衡器的容量和溢出功能。以下步骤演示了三个级别的负载:
- 10 RPS,低于
gke-west-1中 store Service 的容量。 - 30 RPS,超过
gke-west-1store Service 的容量,导致流量溢出到gke-east-1。 - 60 RPS,超出这两个集群中的 Service 的容量。
配置信息中心
获取 Gateway 的底层 URLmap 的名称:
kubectl get gateway store -n traffic-test --context=gke-west-1 -o=jsonpath="{.metadata.annotations.networking\.gke\.io/url-maps}"输出类似于以下内容:
/projects/PROJECT_NUMBER/global/urlMaps/gkemcg1-traffic-test-store-armvfyupay1t在 Google Cloud 控制台中,前往 Metrics Explorer 页面。
在选择指标下,点击代码:MQL。
输入以下查询,以观察跨两个集群的 store Service 的流量指标:
fetch https_lb_rule | metric 'loadbalancing.googleapis.com/https/backend_request_count' | filter (resource.url_map_name == 'GATEWAY_URL_MAP') | align rate(1m) | every 1m | group_by [resource.backend_scope], [value_backend_request_count_aggregate: aggregate(value.backend_request_count)]将
GATEWAY_URL_MAP替换为上一步中的 URLmap 名称。点击运行查询。在下一部分中部署负载生成器后,请至少等待 5 分钟,使指标显示在图表中。
使用 10 RPS 进行测试
将 Pod 部署到
gke-west-1集群:kubectl run --context gke-west-1 -i --tty --rm loadgen \ --image=cyrilbkr/httperf \ --restart=Never \ -- /bin/sh -c 'httperf \ --server=GATEWAY_IP_ADDRESS \ --hog --uri="/zone" --port 80 --wsess=100000,1,1 --rate 10'将
GATEWAY_IP_ADDRESS替换为上一步中的 Gateway IP 地址。输出类似于以下内容,表明流量生成器正在发送流量:
If you don't see a command prompt, try pressing enter.负载生成器会持续向 Gateway 发送 10 RPS。即使流量来自 Google Cloud 区域内部,负载均衡器也会将其视为来自美国西海岸的客户端流量。为了模拟真实的客户端多样性,负载生成器会将每个 HTTP 请求作为新的 TCP 连接发送,这意味着流量会更均匀地分配到后端 Pod 中。
生成器最多需要 5 分钟来为信息中心生成流量。
查看 Metrics Explorer 信息中心。系统将显示两行,指示为了均衡负载而向每个集群分配的流量:

您应该会看到
us-west1-a收到了大约 10 RPS 的流量,而us-east1-b没有收到任何流量。由于流量生成器在us-west1中运行,因此所有流量都会发送到gke-west-1集群中的 Service。使用 Ctrl+C 停止负载生成器,然后删除 Pod:
kubectl delete pod loadgen --context gke-west-1
使用 30 RPS 进行测试
再次部署负载生成器,但将其配置为发送 30 RPS:
kubectl run --context gke-west-1 -i --tty --rm loadgen \ --image=cyrilbkr/httperf \ --restart=Never \ -- /bin/sh -c 'httperf \ --server=GATEWAY_IP_ADDRESS \ --hog --uri="/zone" --port 80 --wsess=100000,1,1 --rate 30'生成器最多需要 5 分钟来为信息中心生成流量。
查看 Cloud 运维信息中心。

您应该会看到大约 20 RPS 被发送到
us-west1-a,10 RPS 被发送到us-east1-b。这表示gke-west-1中的 Service 得到充分利用,并将 10 RPS 的流量溢出到gke-east-1中的 Service。使用 Ctrl+C 停止负载生成器,然后删除 Pod:
kubectl delete pod loadgen --context gke-west-1
使用 60 RPS 进行测试
将负载生成器配置为发送 60 RPS 并部署:
kubectl run --context gke-west-1 -i --tty --rm loadgen \ --image=cyrilbkr/httperf \ --restart=Never \ -- /bin/sh -c 'httperf \ --server=GATEWAY_IP_ADDRESS \ --hog --uri="/zone" --port 80 --wsess=100000,1,1 --rate 60'等待 5 分钟并查看您的 Cloud 运维信息中心。现在,它应该显示两个集群都收到大约 30 RPS。由于所有 Service 在全球范围内都被过度利用,因此不会发生流量溢出,而且 Service 会吸收其可以吸收的所有流量。

使用 Ctrl+C 停止负载生成器,然后删除 Pod:
kubectl delete pod loadgen --context gke-west-1
清理
完成本文档中的练习后,请按照以下步骤移除资源,防止您的账号产生不必要的费用:
删除集群。
如果不需要为其他目的注册集群,请从舰队中取消注册集群。
停用
multiclusterservicediscovery功能:gcloud container fleet multi-cluster-services disable停用 Multi Cluster Ingress:
gcloud container fleet ingress disable停用 API:
gcloud services disable \ multiclusterservicediscovery.googleapis.com \ multiclusteringress.googleapis.com \ trafficdirector.googleapis.com \ --project=PROJECT_ID
问题排查
没有健康的上行
具体情况:
创建网关但无法访问后端服务(503 响应代码)时,可能会出现以下问题:
no healthy upstream
原因:
此错误消息表示健康检查探测器找不到健康状况良好的后端服务。您的后端服务可能处于健康状况良好状态,但您可能需要自定义健康检查。
临时解决方法:
如需解决此问题,请使用 HealthCheckPolicy 根据应用的要求自定义监控状况检查(例如 /health)。
后续步骤
- 详细了解 Gateway Controller。