k8s问题集锦之有趣的SelectorSpread
# 问题描述
日常巡检发现有应用存在堆叠问题, 具体就是一个node上部署了太多某一个应用的pod,
为了降低业务风险, 于是申请了一些新node, 想将这个应用pod进行打散,
然后诡异的事情发生了, 这边从问题节点逐步驱逐堆叠应用pod, 理论上新的空node的权重应该是最高的, 应该会在新的空node上平均分布, 结果新的pod却在别的老节点上重新堆叠了起来, 完全没有走到新的空node上
换姿势尝试了n次结果都一样, 非常有趣
# 排查过程
1. 检查Predicate预选日志
结果正常, 新加入的节点都在预选阶段筛选出的节点列表中, 是符合我预期的
2. 检查Priority优选日志
初步发现问题, 发现新的空节点优选评分居然比堆叠的老节点低
简单描述一下出现分数差异的默认优选算法
BalancedResourceAllocation: 资源最均衡算法(cpu,内存,volume)
LeastRequestedPriority: 空闲资源最多算法
这两个算法结果的差异是符合我直觉的, 空闲的新节点分数高一些
SelectorSpreadPriority: 节点均衡算法(node上分布最少的同类pod,数量越少分越高)
这个算法结果出现了比较大的差异, 空节点的分数只有3分, 而存在pod的老节点分数居然有8分, 而这个差异导致了最终优选结果偏向老节点,以防万一,我试了多次, 依然是这个结果, 不免让人觉得十分有趣
3. 查看SelectorSpreadPriority具体算法过程, 定位到问题
根据文档和源码总结出如下的
当前节点分数 =
(100*(节点最大pod数 - 当前节点pod数) / 节点最大pod数) * 1/3 +
(100*(区域最大pod数 - 当前区域pod数) / 区域最大pod数) * 2/3
其中可以看出 节点pod数分布只占总体评分权重的三分之一, 而区域zone的pod数占三分之二, 所以问题就出在这个地方
如下 我模拟一个算法的简单场景,
区域 | zone1 |
zone1 |
zone2 |
节点 |
node1 |
node2 |
node3 |
pod数 |
10 |
0 |
3 |
分数 |
100(10-10)/10 + 100(10-10)/10 =0*1/3+0*2/3 =0 |
100(10-0)/10 + 100(10-10)/10 =100*1/3+0*2/3 =30 |
100(10-3)/10 + 100(10-3)/10 =100*1/3+0*2/3 =70 |
如上可以看到node2节点可能明明没有应用pod 但是最终的权重可能反而不如node3.
而通过后续查看发现我们集群节点分布也正符合这个分布逻辑, 新的空节点所在的zone分布了太多应用pod, 2/3的权重足够把空节点分数拉下来
所以出现这种空节点反而调度不上去的有趣现象, 至于为啥出现这种问题, 后面有机会再单独出文章说明一下
# 问题总结
k8s还是太博大精深了, 之前关于预选优选的默认调度原理和代码只是粗读, 只有个大体的逻辑概念, 看来对于核心的预选优选算法还是得花点功夫精读细读一下, 不然又要拉胯, 还去好为人师, 太尴尬了 -_-
扫码关注我
天府云计算架构茶话会