<aside> ⏰

本文主要介绍调度器中的调度插件 PodTopologySpread 的工作原理。

</aside>

Pod 拓扑分布约束

在 k8s 集群调度中,“亲和性”相关的概念本质上都是控制 Pod 如何被调度——**堆叠或是打散。**目前 k8s 提供了 podAffinity 以及 podAntiAffinity 两个特性对 Pod 在不同拓扑域的分布进行了一些控制,podAffinity 可以将无数个 Pod 调度到特定的某一个拓扑域,这是堆叠的体现;podAntiAffinity 则可以控制一个拓扑域只存在一个 Pod,这是打散的体现。但这两种情况都太极端了,在不少场景下都无法达到理想的效果,例如为了实现容灾和高可用,将业务 Pod 尽可能均匀的分布在不同可用区就很难实现。

PodTopologySpread 特性的提出正是为了对 Pod 的调度分布提供更精细的控制,以提高服务可用性以及资源利用率,PodTopologySpread 由 EvenPodsSpread 特性门所控制,在 v1.16 版本第一次发布,并在 v1.18 版本进入 beta 阶段默认启用。再了解这个插件是如何实现之前,我们首先需要搞清楚这个特性是如何使用的。

使用规范

在 Pod 的 Spec 规范中新增了一个 topologySpreadConstraints 字段:

spec:
  topologySpreadConstraints:
  - maxSkew: <integer>
    topologyKey: <string>
    whenUnsatisfiable: <string>
    labelSelector: <object>

由于这个新增的字段是在 Pod spec 层面添加,因此更高层级的控制 (Deployment、DaemonSet、StatefulSet) 也能使用 PodTopologySpread 功能。

让我们结合上图来理解 topologySpreadConstraints 中各个字段的含义和作用:

下面我们用两个实际的示例来进一步说明。

单个 TopologySpreadConstraint

假设你拥有一个 4 节点集群,其中标记为 foo:bar 的 3 个 Pod 分别位于 node1、node2 和 node3 中:

如果希望新来的 Pod 均匀分布在现有的可用区域,则可以按如下设置其约束: