GKE Autopilot中topologySpreadConstraints未按预期跨区调度Pod问题
问题根源分析
当前规则允许同区调度:
你为每个Deployment配置的拓扑扩散规则仅匹配自身Pod(labelSelector: matchLabels: app: some-microservice),当Deployment有2个Pod时,第一个Pod调度到europe-west1-b后,第二个Pod计算发现b区已有1个Pod,其他区(c/d)为0个,差值为1,刚好符合maxSkew: 1的限制,因此调度器允许将第二个Pod也放在b区,不会触发DoNotSchedule的限制。zone拓扑键无效:
GKE节点的可用区标签为标准的topology.kubernetes.io/zone,而非zone。使用不存在的拓扑键时,调度器无法识别节点的可用区属性,导致第二个Pod无法找到符合拓扑分布要求的节点,最终调度失败。
前置排查步骤
先确认三个可用区均存在符合要求的Spot节点:
kubectl get nodes -l cloud.google.com/gke-spot=true --show-labels | grep topology.kubernetes.io/zone
如果输出缺少europe-west1-c或europe-west1-d的节点,说明对应区没有Spot节点,Pod自然只能调度到有节点的b区。
解决方案
方案1:优先分散Pod(非强制)
将whenUnsatisfiable改为ScheduleAnyway,调度器会优先尝试将Pod分散到不同可用区,仅在无法满足时才会将Pod放在同区:
topologySpreadConstraints: - maxSkew: 1 topologyKey: topology.kubernetes.io/zone whenUnsatisfiable: ScheduleAnyway labelSelector: matchLabels: app: some-microservice
方案2:强制倾向跨区分布
如果希望尽可能让Pod跨区,可将maxSkew设为0并配合ScheduleAnyway(因为2个Pod无法在3个区实现完全均等分布,用DoNotSchedule会导致调度失败):
topologySpreadConstraints: - maxSkew: 0 topologyKey: topology.kubernetes.io/zone whenUnsatisfiable: ScheduleAnyway labelSelector: matchLabels: app: some-microservice
额外检查
通过kubectl describe pod <pod-name>查看Pod调度事件,确认没有其他规则(如节点亲和性、污点、优先级类)限制Pod只能调度至europe-west1-b区。
内容的提问来源于stack exchange,提问作者Stefano L

