topologySpreadConstraints: 用于描述 Pod 要在什么拓扑结构上进行均衡打散,多个 topologySpreadConstraint 之间是 and 关系;
selector:用于描述需要满足的拓扑打散的一组 Pod 的列表
topologyKey: 作用在什么拓扑结构上;
maxSkew: 最大允许的不均衡数量;
whenUnsatisfiable: 当不满足 topologySpreadConstraint 的时候的策略,DoNotSchedule:表示作用于 filter 阶段,ScheduleAnyway:作用于 score 阶段。
下面举例描述下:
selector 选择的是所有 lable 符合 app=foo 的 pod,必须在 zone 级别是打散的,允许最大不均衡数为 1。
集群中有三个 zone,上图中 label 的值 app=foo 的 Pod 在 zone1 和 zone2 中都分配了一个 pod。
计算不均衡数量公式为:ActualSkew = count[topo] - min(count[topo])
首先,依据 selector 获取到符合条件的 Pod 列表
其次,会按照 topologyKey 去分组得到 count[topo]
如上图所示:
假设 maxSkew 为 1,如果分配到 zone1/zone2,skew 的值为2,大于前面设置的 maxSkew。这是不匹配的,所以只能分配到 zone3。如果分配到 zone3 的话,min(count[topo]) 为1,count[topo]为 1,那 skew 就等于 0,因此只能分配到 zone2。
假设 maxSkew 为 2,分配到 z1(z2),skew 的值为 2/1/0(1/2/0),最大值为 2,满足 <=maxSkew。那 z1/z2/z3 都是允许被选择的。
通过 EvenPodsSpread 可以实现一组 Pod 在某个 TopologyKey 上的均衡打散需求,如果必须要求每个 topo 上都均衡可以设 maxSkew 为1,当然这个描述缺乏了一些控制,例如必须分配在多少个 topologyValue 上的限制。
Priorities接下来看一下打分算法,打分算法主要解决的问题就是集群的碎片、容灾、水位、亲和、反亲和等。
按照类别可以分为四大类:
Node 水位
Pod 打散 (topp,service,controller)
Node 亲和&反亲和
Pod 亲和&反亲和
资源水位接下来介绍打分器相关的第一个资源水位。
节点打分算法跟资源水位相关的主要有四个,如上图所示。
资源水位公式的概念
Request:Node 已经分配的资源;Allocatable:Node 的可调度的资源
优先打散
把 Pod 分到资源空闲率最高的节点上,而非空闲资源最大的节点,公式:资源空闲率=(Allocatable - Request) / Allocatable,当这个值越大,表示分数越高,优先分配到高分数的节点。其中(Allocatable - Request)表示为Pod分配到这个节点之后空闲的资源数。
优先堆叠
把 Pod 分配到资源使用率最高的节点上,公式:资源使用率 = Request / Allocatable ,资源使用率越高,表示得分越高,会优先分配到高分数的节点。
碎片率
是指 Node 上的多种资源之间的资源使用率的差值,目前支持 CPU/Mem/Disk 三类资源, 假如仅考虑 CPU/Mem,那么碎片率的公式 = Abs[CPU(Request / Allocatable) - Mem(Request / Allocatable)] 。举一个例子,当 CPU 的分配率是 99%,内存的分配率是 50%,那么碎片率 = 99% - 50% = 50%,那么这个例子中剩余 1% CPU, 50% Mem,很难有这类规格的容器能用完 Mem。得分 = 1 - 碎片率,碎片率越高得分低。
指定比率
可以在 Scheduler 启动的时候,为每一个资源使用率设置得分,从而实现控制集群上 node 资源分配分布曲线。
Pod 打散Pod 打散为了解决的问题为:支持符合条件的一组 Pod 在不同 topology 上部署的 spread 需求。
SelectorSpreadPriority
用于实现 Pod 所属的 Controller 下所有的 Pod 在 Node 上打散的要求。实现方式是这样的:它会依据待分配的 Pod 所属的 controller,计算该 controller 下的所有 Pod,假设总数为 T,对这些 Pod 按照所在的 Node 分组统计;假设为 N (表示为某个 Node 上的统计值),那么对 Node上的分数统计为 (T-N)/T 的分数,值越大表示这个节点的 controller 部署的越少,分数越高,从而达到 workload 的 pod 打散需求。
ServiceSpreadingPriority
官方注释上说大概率会用来替换 SelectorSpreadPriority,为什么呢?我个人理解:Service 代表一组服务,我们只要能做到服务的打散分配就足够了。
EvenPodsSpreadPriority
用来指定一组符合条件的 Pod 在某个拓扑结构上的打散需求,这样是比较灵活、比较定制化的一种方式,使用起来也是比较复杂的一种方式。