You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

GKE Internal Load Balancer无法在gRPC服务器间均衡分配负载

GKE Internal Load Balancer 流量不均衡问题排查

初始问题描述

我部署的API近期流量上涨约1.5倍后,接口延迟直接翻倍:
latency
我已配置节点、Pod自动扩缩容以及GKE Internal Load Balancer,该现象不符合预期。
外部API将请求转发到高CPU占用的内部服务,观察虚拟机实例(即Kubernetes节点)发现所有流量都被转发到两台节点中的其中一台:
CPU utilization per node
按照负载均衡的预期,节点CPU占用应当更均匀。当前Pod分布为:第一个节点上部署1个Pod,第二个节点上部署2个Pod:
First pod on first node


我的服务配置如下:

$ kubectl describe service model-service
Name:                     model-service
Namespace:                default
Labels:                   app=model-server
Annotations:              networking.gke.io/load-balancer-type: Internal
Selector:                 app=model-server
Type:                     LoadBalancer
IP Families:              <none>
IP:                       10.3.249.180
IPs:                      10.3.249.180
LoadBalancer Ingress:     10.128.0.18
Port:                     rest-api  8501/TCP
TargetPort:               8501/TCP
NodePort:                 rest-api  30406/TCP
Endpoints:                10.0.0.145:8501,10.0.0.152:8501,10.0.1.135:8501
Port:                     grpc-api  8500/TCP
TargetPort:               8500/TCP
NodePort:                 grpc-api  31336/TCP
Endpoints:                10.0.0.145:8500,10.0.0.152:8500,10.0.1.135:8500
Session Affinity:         None
External Traffic Policy:  Cluster
Events:
  Type    Reason               Age                  From                Message
  ----    ------               ----                 ----                -------
  Normal  UpdatedLoadBalancer  6m30s (x2 over 28m)  service-controller  Updated load balancer with new hosts

Kubernetes自动扩缩容能正常触发新Pod创建,但第二个节点上的Pod完全收不到流量,请问如何让GKE实现更均匀的负载均衡?


11月2日更新

根据答复推测问题和模型服务的配置有关,该服务同时暴露REST API和gRPC API,实际接收流量的是gRPC API。
服务对应的转发规则如下:

$ gcloud compute forwarding-rules list --filter="loadBalancingScheme=INTERNAL"
NAME                              REGION       IP_ADDRESS   IP_PROTOCOL  TARGET
aab8065908ed4474fb1212c7bd01d1c1  us-central1  10.128.0.18  TCP          us-central1/backendServices/aab8065908ed4474fb1212c7bd01d1c1

转发规则指向的后端服务配置如下:

$ gcloud compute backend-services describe aab8065908ed4474fb1212c7bd01d1c1
backends:
- balancingMode: CONNECTION
  group: https://www.googleapis.com/compute/v1/projects/questions-279902/zones/us-central1-a/instanceGroups/k8s-ig--42ce3e0a56e1558c
connectionDraining:
  drainingTimeoutSec: 0
creationTimestamp: '2021-02-21T20:45:33.505-08:00'
description: '{"kubernetes.io/service-name":"default/model-service"}'
fingerprint: lA2-fz1kYug=
healthChecks:
- https://www.googleapis.com/compute/v1/projects/questions-279902/global/healthChecks/k8s-42ce3e0a56e1558c-node
id: '2651722917806508034'
kind: compute#backendService
loadBalancingScheme: INTERNAL
name: aab8065908ed4474fb1212c7bd01d1c1
protocol: TCP
region: https://www.googleapis.com/compute/v1/projects/questions-279902/regions/us-central1
selfLink: https://www.googleapis.com/compute/v1/projects/questions-279902/regions/us-central1/backendServices/aab8065908ed4474fb1212c7bd01d1c1
sessionAffinity: NONE
timeoutSec: 30

后端服务关联的健康检查配置如下:

$ gcloud compute health-checks describe k8s-42ce3e0a56e1558c-node                                          
checkIntervalSec: 8
creationTimestamp: '2021-02-21T20:45:18.913-08:00'
description: ''
healthyThreshold: 1
httpHealthCheck:
  host: ''
  port: 10256
  proxyHeader: NONE
  requestPath: /healthz
id: '7949377052344223793'
kind: compute#healthCheck
logConfig:
  enable: true
name: k8s-42ce3e0a56e1558c-node
selfLink: https://www.googleapis.com/compute/v1/projects/questions-279902/global/healthChecks/k8s-42ce3e0a56e1558c-node
timeoutSec: 1
type: HTTP
unhealthyThreshold: 3

我的Pod列表如下:

kubectl get pods
NAME                                       READY   STATUS    RESTARTS   AGE
api-server-deployment-6747f9c484-6srjb     2/2     Running   3          3d22h
label-server-deployment-6f8494cb6f-79g9w   2/2     Running   4          38d
model-server-deployment-55c947cf5f-nvcpw   0/1     Evicted   0          22d
model-server-deployment-55c947cf5f-q8tl7   0/1     Evicted   0          18d
model-server-deployment-766946bc4f-8q298   1/1     Running   0          4d5h
model-server-deployment-766946bc4f-hvwc9   0/1     Evicted   0          6d15h
model-server-deployment-766946bc4f-k4ktk   1/1     Running   0          7h3m
model-server-deployment-766946bc4f-kk7hs   1/1     Running   0          9h
model-server-deployment-766946bc4f-tw2wn   0/1     Evicted   0          7d15h
model-server-deployment-7f579d459d-52j5f   0/1     Evicted   0          35d
model-server-deployment-7f579d459d-bpk77   0/1     Evicted   0          29d
model-server-deployment-7f579d459d-cs8rg   0/1     Evicted   0          37d

新增问题:

  • A)如何确认该健康检查确实判定2/3的后端不健康?
  • B)如何配置健康检查实现流量转发到所有后端?

11月5日更新

排查发现过往多个Pod因内存不足被驱逐,已将Pod迁移到新节点池,旧节点池VM配置为4核4GB内存,新节点池为2核8GB内存,驱逐/内存问题已解决,但负载均衡器仍每次仅将流量转发到单个Pod:
节点1上的Pod1负载:
Pod 1 on node 1
节点2上的Pod2负载:

当前负载均衡器完全不拆分流量,只是随机选择一个gRPC模型服务器转发100%流量,请问是否有遗漏的配置导致该现象?是否和使用gRPC有关?


解决方案

问题A:健康检查状态确认方法

  1. 查看GCP控制台负载均衡后端服务的健康状态页,可直接看到每个后端实例的健康检查结果
  2. 执行gcloud compute backend-services get-health [后端服务名] --region [区域],返回结果中会明确标注每个后端的健康状态
  3. 查看健康检查日志:健康检查已开启日志,可直接在GCP日志浏览器中过滤对应健康检查资源的日志,查看每次检查的返回状态
  4. 登录节点本地访问健康检查端口验证:curl http://localhost:10256/healthz,查看返回是否为200,异常的节点会返回非200状态码

问题B:健康检查配置调整

你当前使用的是GKE默认的节点级健康检查(端口10256是kube-proxy的健康检查端口),如果节点上存在至少一个对应服务的就绪Pod,该接口就会返回200。如果确认节点本身健康检查异常,可先排查节点的kube-proxy状态、防火墙规则是否放通了VPC内部对10256端口的访问。
如果需要更精准的Pod级健康检查,可在Service注解中添加cloud.google.com/load-balancer-type: "Internal"的同时,配置cloud.google.com/backend-config: '{"default": "my-backendconfig"}',通过BackendConfig资源自定义健康检查规则,直接探测Pod的业务端口就绪状态,避免节点级健康检查的误差。

11月5日更新问题解决

你遇到的单Pod独占流量问题确实和gRPC协议直接相关:
gRPC基于HTTP/2实现,默认会在客户端和服务端之间建立长连接,所有请求都会复用同一个TCP连接,而你当前的后端服务负载均衡模式是CONNECTION(基于连接数分配),一旦连接建立成功,后续所有请求都会走同一个连接,不会再做负载均衡。
修复方法如下:

  1. 调整负载均衡调度模式:将后端服务的balancingMode改为UTILIZATION或者RATE,如果是gRPC服务建议使用基于请求量的调度策略
  2. 客户端侧配置gRPC连接策略:开启客户端侧的负载均衡,配置service_config中的loadBalancingPolicy为round_robin,同时设置合理的连接最大存活时间(max_connection_age),强制客户端定期重建连接,分散到不同的后端Pod
  3. 如果是GKE 1.21+版本,可直接使用gRPC专用的负载均衡配置,在BackendConfig中指定protocol: GRPC,开启gRPC级的请求负载均衡,而不是TCP连接级的负载均衡

内容的提问来源于stack exchange,提问作者Johan Wikström

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 06:15:03