vlambda博客
学习文章列表

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还是太博大精深了, 之前关于预选优选的默认调度原理和代码只是粗读, 只有个大体的逻辑概念, 看来对于核心的预选优选算法还是得花点功夫精读细读一下, 不然又要拉胯, 还去好为人师, 太尴尬了 -_-


扫码关注我

天府云计算架构茶话会