本文档介绍了如何解决 Kubernetes 服务流量分配不均的问题。
识别流量分配不均的症状
流量分布不均(通常称为热点)是指一部分 Pod 或节点处理的工作负载占总工作负载的比例过高,而其他 Pod 或节点则未得到充分利用。
常见症状包括:
- 性能瓶颈:用户可能会在过度使用的网络连接上遇到间歇性超时、HTTP 5xx 错误或丟包。
- 资源耗尽:特定 Pod 或节点的 CPU 或内存利用率明显高于舰队中的其余部分。
- 流量不平衡模式:
- 每个 Pod 的不平衡:即使所有 Pod 都报告为健康且就绪,流量也仅命中一小部分可用的 Pod。
- 节点间不平衡:一个或多个节点接收的数据包或请求明显多于其他节点,通常在使用
externalTrafficPolicy: Local且 Pod 放置不均匀时出现。 - 粘性客户端会话:来自单个高流量客户端的所有请求始终路由到同一后端 Pod。
使用 Cloud Monitoring 进行诊断
如需确认这些症状,请使用以下指标直观呈现流量模式:
- 对于第 7 层(Ingress/网关):绘制
loadbalancing.googleapis.com/backend/request_count并按backend_target分组,以比较不同后端之间的请求量。
了解流量分配不均的常见原因
本部分介绍了导致 Kubernetes 服务流量分配不均的常见原因。这种不平衡可能会导致性能瓶颈、某些 Pod 上的资源耗尽以及应用可用性降低,因为某些 Pod 收到的流量明显多于其他 Pod,而某些 Pod 收到的流量很少或没有。
会话亲和性导致分配不均
如果启用了会话亲和性的负载平衡器始终将来自同一客户端的请求路由到同一后端 Pod,则会发生以下问题。如果特定客户端生成大量流量,则该 Pod 会过载,从而形成热点,即该 Pod 接收的负载远高于其他 Pod,而其他 Pod 仍未得到充分利用。
您可以使用 sessionAffinity 字段在 Kubernetes 服务对象中配置会话亲和性。
当 sessionAffinity 设置为 ClientIP 时,Service 会确保源自同一客户端 IP 地址的所有连接始终路由到同一后端 Pod。这可提供基于真实客户端 IP 的会话亲和性。
当 sessionAffinity 设置为 None(默认行为)时,第 4 层负载平衡器通常使用各种网络参数的哈希来分配连接,例如 4 元组(客户端 IP 地址、目标 IP 地址、目标端口、协议)或 5 元组(包括源端口)。虽然此哈希处理可以通过始终将具有相同元组值的连接路由到同一后端来提供一定的连接“粘性”,但如果其他元组元素发生变化,它并不能保证来自特定客户端 IP 地址的所有连接始终会路由到同一 Pod。
如需了解详情,请参阅会话亲和性。
对于 GKE 网关,GCPTrafficDistributionPolicy CRD 用于配置会话亲和性。如需了解详情,请参阅使用政策配置网关资源。
对于区域级外部直通式网络负载平衡器,您可以使用会话亲和性来保持与特定后端的连接粘性。不过,请注意,如果某些客户端生成的流量多于其他客户端,会话亲和性本身可能会导致分配不均匀。
如需了解详情,请参阅会话亲和性和基于后端服务的外部直通式网络负载平衡器概览。
以下示例展示了包含 sessionAffinity: ClientIP 的服务清单:
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: LoadBalancer
sessionAffinity: ClientIP # This can cause uneven distribution
ports:
- port: 80
targetPort: 8080
selector:
app: my-app
连接池导致分配不均匀
当负载平衡器重复使用与特定 Pod 的现有连接时,即使其他 Pod 有可用容量,也会发生连接池化。如果某些连接的持续时间较长或处理的请求明显多于其他连接,则此行为可能会导致失衡。这会将流量集中在某些 Pod 上,类似于会话亲和性,从而创建热点,导致这些 Pod 过载,而其他 Pod 仍未得到充分利用。
负载平衡器通过减少建立新连接的开销来实现连接池,从而提高性能。不过,如果管理不当,连接池可能会导致流量分布不均,尤其是对于维护长期连接的应用。
为了缓解连接池导致的不均匀分布,请在应用或客户端级别实施以下策略:
将客户端配置为使用多个连接:不要依赖单个长效连接,而是将客户端配置为打开并管理与负载均衡器的多个连接池。这样一来,负载均衡器就可以在可用的后端 Pod 之间分配新的连接尝试,从而改善整体总流量分配。
定期关闭并重新打开连接:对于自然会保持长期连接的应用,请将其或其客户端配置为定期关闭并重新打开连接。虽然这会带来重新建立连接的轻微开销,但为负载均衡器提供了新的机会,可将后续连接尝试分配给不同的、利用率较低的后端 Pod。对于连接终止和重新建立不会造成过大中断的服务,此方法尤其有效。
实现激进的连接排空:确保您的 Pod 已配置为安全关停和连接排空。当 Pod 正常终止(例如在部署或缩减期间)时,负载均衡器应停止向其发送新连接,并允许现有连接完成或排空。这样一来,流量便可以更顺畅地转移到其他 Pod,并有助于防止流量集中在终止的 Pod 上。
通过主动管理连接行为,您可以帮助负载平衡器更均匀地分配流量,即使是长期连接也是如此。
5 元组哈希会导致分配不均匀
如果您未明确配置会话亲和性,许多第 4 层负载平衡器都会采用此默认行为。如果许多连接来自同一客户端或使用相同的端口组合,则会导致分布不均匀。
如需解决由哈希处理导致的不平衡问题,请考虑以下事项:
使用第 7 层负载均衡:GKE Ingress 和 Gateway 在请求级别运行,因此可以将单个客户端的请求分发到多个后端 Pod。
调整客户端行为:将客户端配置为使用多个连接或更大的来源端口池。
Pod 在节点间的分布不均会导致分布不均
当 Pod 未均匀分布在各个节点上,且负载均衡器未使用容器原生负载均衡时,会出现此问题。具有更多 Pod 的节点会接收更多流量,这可能会导致某些节点过载,而其他节点未得到充分利用。
如果您使用 externalTrafficPolicy: Local,此问题尤为重要。
外部流量政策设置导致分配不均匀
服务上的 externalTrafficPolicy 设置会影响流量的路由方式。
- 集群:允许负载均衡器将流量分配到集群中的任何节点。使用
Cluster设置可在所有可用节点和 Pod 之间实现最均匀的分布。 - Local:仅将流量路由到运行在接收流量的同一节点上的 Pod。如果您未将 Pod 均匀分配到各个节点,则可能会导致分配不均。
节点亲和性导致分布不均匀
使用节点亲和性将 Pod 限制为仅在部分节点上运行可能会导致这些节点过载,尤其是在工作负载在这些节点之间分布不均衡的情况下。
确保您的 Pod 未固定到特定节点。