关于topology-spread-constraints的一些随记

来自三线的随记

k8s中有个特性叫做 topology-spread-constraints,利用此特性能做到将pod尽量均匀分布在不同节点或者拓扑域上(根据topologyKey决定)

简单解释:

maxSkew意思是

同一个拓扑域中,假设拓扑域 key 就是节点名,部分节点有污点或者计算资源已被其他pod请求占用到了上限,且maxSkew假设为1

假设拓扑域中有ABCD四个节点,pod需要4个副本,A节点有污点

这时候节点BCD能各调度一个pod,但是A节点由于有污点,所以禁止调度到A节点,这时候第四个pod只能调度到BCD节点,但是BCD已经有一个pod了,这时候A节点没有同一服务的任何pod,所以此时集群的maxSkew为1

同时因为有DoNotSchedule,导致这种情况下,第四个pod不允许调度到BCD节点,因为调度上去以后maxskew会变成 2

利用这个特性能够比配置 强反亲和 或 弱反亲和 来实现POD尽可能在一个拓扑域打散分布有效(强反亲和固定同拓扑域中只能有一个副本,弱反亲和没办法尽力打散,会受到很多其他因素影响调度)


但是在使用的时候,如果是deployment类型pod,需要注意要把 pod-template-hash 作为 key 添加到 topologySpreadConstraints 的 matchLabelKeys 中(matchLabelKeys: # optional; beta since v1.27)

否则会造成,多副本的 deployment 在 rolling update 的时候(delete pod 没办法,算是一个小的难受点),terminating pod 也会被纳入计算,进而导致即使在DoNotSchedule模式下,POD 副本数依然不是绝对均匀


同样需要注意,在 k8s v1.26 中,topology-spread-constraint 还引入了 nodeAffinityPolicy 等配置,会影响Skew的计算结果(默认为Honor: only nodes matching nodeAffinity/nodeSelector are included in the calculations.)

小声补充: 其实大多数情况下不应该追求绝对均匀(即不开启 DoNotSchedule),否则当k8s集群某些业务节点Not-Ready被打上污点以后,会导致被驱逐的pod无法满足拓扑约束进而无法被调度(除非把 nodeTaintsPolicy 也给配置用上,同样是自k8s 1.26启用,在计算skew的时候忽略有污点无法调度的节点[默认为不忽略] )


https://kubernetes.io/docs/concepts/scheduling-eviction/topology-spread-constraints/