该优选策略的目标是使属于同一个服务(service或者Replication Controllers)的pod尽量均匀的分布在各个节点上或者zone上。在k8s 1.18版本中默认开启。在该优选策略的实现中,使用的是DefaultPodTopologySpread
打分插件。
接下来一起看下DefaultPodTopologySpread
打分插件的打分(算法)逻辑。
算法逻辑
DefaultPodTopologySpread
插件的算法逻辑包括了三个部分:
- preScore 准备阶段
- Score 统计阶段
- NormalizeScore 分数计算阶段
preScore
打分前的准备阶段。对于该插件,在准备阶段中,主要的工作是依据pod,并结合service、Replication Controllers, ReplicaSets 和 StatefulSets推导出的selector。用于在Score阶段,过滤出节点上与pod(待调度)同一个的其他pods对象。
Score
打分的统计阶段。对于该优选策略,统计节点会给node上的pods做统计,统计的匹配条件是被调度pod的namespace和preScore推导出的selector,方法是遍历当前node节点上所有的pods,如果符合匹配条件,count 。
经过这个阶段后,集群中所有的node都会得到一个统计值(count或者sores[i].Socre)。
代码逻辑如下:
NormalizeScore
分数计算阶段,在该阶段,会计算出所有node的分数(在调度过程中起作用的分数值)。
1 第一步 获取以下三个值:
maxCountByZone
: 某个zone下的Count(来自Score阶段)最大的值。maxCountByNodeName
:某个node上的Count(来自Score阶段)最大的值。countsByZone
:以zone为单位的count计数。
2 第二步:
首先:所有节点的打分都会有一个初始化值MaxNodeScore
(默认数值是100)
然后:开始为节点的打分,计算方法如下:
代码语言:go复制# socres[i].Score 表示某个节点的count计数
fScore = MaxNodeScoreFloat64 * (float64(maxCountByNodeName-scores[i].Score) / maxCountByNodeNameFloat64)
3 第三步
判断集群中的节点是否有使用zone,如果有使用zone,再给zone打分,最后结合节点的打分和zone的打分来给出一个最终得分(就是当前候选节点的score得分)。计算方法如下:
其中,在最后打分环节,zone的权重(zoneWeighting)为2/3,node的权重(nodeWeighting)是1/3。
代码语言:javascript复制# zone分数的初始值也是100
zoneScore := MaxNodeScoreFloat64
# 计算出单个zone的分数
zoneScore = MaxNodeScoreFloat64 * (float64(maxCountByZone-countsByZone[zoneID]) / maxCountByZoneFloat64)
# 根据节点的打分和zone的打分,计算出node的最后得分
fScore = (fScore * (1.0 - zoneWeighting)) (zoneWeighting * zoneScore)
经过上面的三个阶段,SelectorSpreadPriority
优选策略就完成了对所有节点的打分。
举例说明
接下来一个测试deployment为例,进一步熟悉一下SelectorSpreadPriority
打分的过程,具体场景描述如下:
节点 | node4000101 | node4000102 | node4000201 |
---|---|---|---|
所属zone | sh-40001 | sh-40001 | sh-40002 |
副本数量 | 1 | 2 | 1 |
统计分数count(node维度) | 1 | 2 | 1 |
统计分数count(zone维度) | 3 | 3 | 1 |
补充:创建deployment时,也有创建对应的service。并且暂不考虑其他具有相同seleter服务的情况。
场景1 多扩容一个pod副本
比如,当前测试deployment的副本数为4,在场景1中把测试deployment的副本数扩容到5。
- maxCountByZone : 3
- maxCountByNodeName:2
打分结果如下:
由上图可以得出,node4000101的打分是16,node4000102的打分是0,node4000201的打分是61,所以在考虑其他策略打分一样的情况下,新扩容的pod会被调度到node4000201这个节点上。