你可以使用 拓扑分布约束(Topology Spread Constraints) 来控制 Pod 在集群内故障域之间的分布, 例如区域(Region)、可用区(Zone)、节点和其他用户自定义拓扑域。 这样做有助于实现高可用并提升资源利用率。
你可以将集群级约束设为默认值,或为个别工作负载配置拓扑分布约束。
假设你有一个最多包含二十个节点的集群,你想要运行一个自动扩缩的 工作负载,请问要使用多少个副本? 答案可能是最少 2 个 Pod,最多 15 个 Pod。 当只有 2 个 Pod 时,你倾向于这 2 个 Pod 不要同时在同一个节点上运行: 你所遭遇的风险是如果放在同一个节点上且单节点出现故障,可能会让你的工作负载下线。
除了这个基本的用法之外,还有一些高级的使用案例,能够让你的工作负载受益于高可用性并提高集群利用率。
随着你的工作负载扩容,运行的 Pod 变多,将需要考虑另一个重要问题。 假设你有 3 个节点,每个节点运行 5 个 Pod。这些节点有足够的容量能够运行许多副本; 但与这个工作负载互动的客户端分散在三个不同的数据中心(或基础设施可用区)。 现在你可能不太关注单节点故障问题,但你会注意到延迟高于自己的预期, 在不同的可用区之间发送网络流量会产生一些网络成本。
你决定在正常运营时倾向于将类似数量的副本调度 到每个基础设施可用区,且你想要该集群在遇到问题时能够自愈。
Pod 拓扑分布约束使你能够以声明的方式进行配置。
Pod API 包括一个 字段。这个字段的用法如下所示:
你可以运行 或参阅 Pod API 参考的调度一节, 了解有关此字段的更多信息。
你可以定义一个或多个 条目以指导 kube-scheduler 如何将每个新来的 Pod 与跨集群的现有 Pod 相关联。这些字段包括:
maxSkew 描述这些 Pod 可能被不均匀分布的程度。你必须指定此字段且该数值必须大于零。 其语义将随着 的值发生变化:
minDomains 表示符合条件的域的最小数量。此字段是可选的。域是拓扑的一个特定实例。 符合条件的域是其节点与节点选择器匹配的域。
特性门控为 Pod 拓扑分布启用 。自 v1.28 起, 特性门控默认被启用。 在早期的 Kubernetes 集群中,此特性门控可能被显式禁用或此字段可能不可用。
topologyKey 是节点标签的键。如果节点使用此键标记并且具有相同的标签值, 则将这些节点视为处于同一拓扑域中。我们将拓扑域中(即键值对)的每个实例称为一个域。 调度器将尝试在每个拓扑域中放置数量均衡的 Pod。 另外,我们将符合条件的域定义为其节点满足 nodeAffinityPolicy 和 nodeTaintsPolicy 要求的域。
whenUnsatisfiable 指示如果 Pod 不满足分布约束时如何处理:
labelSelector 用于查找匹配的 Pod。匹配此标签的 Pod 将被统计,以确定相应拓扑域中 Pod 的数量。 有关详细信息,请参考标签选择算符。
matchLabelKeys 是一个 Pod 标签键的列表,用于选择需要计算分布方式的 Pod 集合。 这些键用于从 Pod 标签中查找值,这些键值标签与 进行逻辑与运算,以选择一组已有的 Pod, 通过这些 Pod 计算新来 Pod 的分布方式。 和 中禁止存在相同的键。 未设置 时无法设置 。Pod 标签中不存在的键将被忽略。 null 或空列表意味着仅与 匹配。
借助 ,你无需在变更 Pod 修订版本时更新 。 控制器或 Operator 只需要将不同修订版的标签键设为不同的值。 调度器将根据 自动确定取值。例如,如果你正在配置一个 Deployment, 则你可以使用由 Deployment 控制器自动添加的、以 pod-template-hash 为键的标签来区分同一个 Deployment 的不同修订版。
字段是 1.27 中默认启用的一个 Beta 级别字段。 你可以通过禁用 特性门控来禁用此字段。
nodeAffinityPolicy 表示我们在计算 Pod 拓扑分布偏差时将如何处理 Pod 的 nodeAffinity/nodeSelector。 选项为:
如果此值为 nil,此行为等同于 Honor 策略。
是 1.26 中默认启用的一个 Beta 级别字段。 你可以通过禁用 特性门控来禁用此字段。
nodeTaintsPolicy 表示我们在计算 Pod 拓扑分布偏差时将如何处理节点污点。选项为:
如果此值为 null,此行为等同于 Ignore 策略。
是一个 Beta 级别字段,在 1.26 版本默认启用。 你可以通过禁用 特性门控来禁用此字段。
当 Pod 定义了不止一个 ,这些约束之间是逻辑与的关系。 kube-scheduler 会为新的 Pod 寻找一个能够满足所有约束的节点。
拓扑分布约束依赖于节点标签来标识每个节点所在的拓扑域。 例如,某节点可能具有标签:
为了简便,此示例未使用众所周知的标签键 和 。 但是,建议使用那些已注册的标签键,而不是此处使用的私有(不合格)标签键 和 。
你无法对不同上下文之间的私有标签键的含义做出可靠的假设。
假设你有一个 4 节点的集群且带有以下标签:
那么,从逻辑上看集群如下:
你应该为一个组中的所有 Pod 设置相同的 Pod 拓扑分布约束。
通常,如果你正使用一个工作负载控制器,例如 Deployment,则 Pod 模板会帮你解决这个问题。 如果你混合不同的分布约束,则 Kubernetes 会遵循该字段的 API 定义; 但是,该行为可能更令人困惑,并且故障排除也没那么简单。
你需要一种机制来确保拓扑域(例如云提供商区域)中的所有节点具有一致的标签。 为了避免你需要手动为节点打标签,大多数集群会自动填充知名的标签, 例如 。检查你的集群是否支持此功能。
假设你拥有一个 4 节点集群,其中标记为 的 3 个 Pod 分别位于 node1、node2 和 node3 中:
如果你希望新来的 Pod 均匀分布在现有的可用区域,则可以按如下设置其清单:
从此清单看, 意味着均匀分布将只应用于存在标签键值对为 的节点 (没有 标签的节点将被跳过)。如果调度器找不到一种方式来满足此约束, 则 字段告诉该调度器将新来的 Pod 保持在 pending 状态。
如果该调度器将这个新来的 Pod 放到可用区 ,则 Pod 的分布将成为 。 这意味着实际偏差是 2(计算公式为 ),这违反了 的约定。 为了满足这个示例的约束和上下文,新来的 Pod 只能放到可用区 中的一个节点上:
或者
你可以调整 Pod 规约以满足各种要求:
下面的例子建立在前面例子的基础上。假设你拥有一个 4 节点集群, 其中 3 个标记为 的 Pod 分别位于 node1、node2 和 node3 上:
可以组合使用 2 个拓扑分布约束来控制 Pod 在节点和可用区两个维度上的分布:
在这种情况下,为了匹配第一个约束,新的 Pod 只能放置在可用区 中; 而在第二个约束中,新来的 Pod 只能调度到节点 上。 该调度器仅考虑满足所有已定义约束的选项,因此唯一可行的选择是放置在节点 上。
多个约束可能导致冲突。假设有一个跨 2 个可用区的 3 节点集群:
如果你将 (来自上一个示例的清单)应用到这个集群,你将看到 Pod 保持在 状态。 出现这种情况的原因为:为了满足第一个约束,Pod 只能放置在可用区 中; 而在第二个约束中,Pod 只能调度到节点 上。 两个约束的交集将返回一个空集,且调度器无法放置该 Pod。
为了应对这种情形,你可以提高 的值或修改其中一个约束才能使用 。 根据实际情形,例如若你在故障排查时发现某个漏洞修复工作毫无进展,你还可能决定手动删除一个现有的 Pod。
如果 Pod 定义了 或 , 调度器将在偏差计算中跳过不匹配的节点。
假设你有一个跨可用区 A 到 C 的 5 节点集群:
而且你知道可用区 必须被排除在外。在这种情况下,可以按如下方式编写清单, 以便将 Pod 放置在可用区 上,而不是可用区 上。 同样,Kubernetes 也会一样处理 。
这里有一些值得注意的隐式约定:
只有与新来的 Pod 具有相同命名空间的 Pod 才能作为匹配候选者。
调度器会忽略没有任何 的节点。这意味着:
为集群设置默认的拓扑分布约束也是可能的。默认拓扑分布约束在且仅在以下条件满足时才会被应用到 Pod 上:
默认约束可以设置为调度方案中 插件参数的一部分。约束的设置采用如前所述的 API, 只是 必须为空。 选择算符是根据 Pod 所属的 Service、ReplicaSet、StatefulSet 或 ReplicationController 来设置的。
配置的示例可能看起来像下面这个样子:
如果你没有为 Pod 拓扑分布配置任何集群级别的默认约束, kube-scheduler 的行为就像你指定了以下默认拓扑约束一样:
此外,原来用于提供等同行为的 插件默认被禁用。
对于分布约束中所指定的拓扑键而言, 插件不会为不包含这些拓扑键的节点评分。 这可能导致在使用默认拓扑约束时,其行为与原来的 插件的默认行为不同。
如果你的节点不会同时设置 和 标签, 你应该定义自己的约束而不是使用 Kubernetes 的默认约束。
如果你不想为集群使用默认的 Pod 分布约束,你可以通过设置 参数为 , 并将 插件配置中的 参数置空来禁用默认 Pod 分布约束:
在 Kubernetes 中, Pod 间亲和性和反亲和性控制 Pod 彼此的调度方式(更密集或更分散)。
要实现更细粒度的控制,你可以设置拓扑分布约束来将 Pod 分布到不同的拓扑域下,从而实现高可用性或节省成本。 这也有助于工作负载的滚动更新和平稳地扩展副本规模。
有关详细信息,请参阅有关 Pod 拓扑分布约束的增强倡议的 动机一节。
当 Pod 被移除时,无法保证约束仍被满足。例如,缩减某 Deployment 的规模时,Pod 的分布可能不再均衡。
你可以使用 Descheduler 来重新实现 Pod 分布的均衡。
具有污点的节点上匹配的 Pod 也会被统计。 参考 Issue 80921。
该调度器不会预先知道集群拥有的所有可用区和其他拓扑域。 拓扑域由集群中存在的节点确定。在自动扩缩的集群中,如果一个节点池(或节点组)的节点数量缩减为零, 而用户正期望其扩容时,可能会导致调度出现问题。 因为在这种情况下,调度器不会考虑这些拓扑域,直至这些拓扑域中至少包含有一个节点。
你可以通过使用感知 Pod 拓扑分布约束并感知整个拓扑域集的集群自动扩缩工具来解决此问题。
某某自来水业务系统,是一套适合各种规模自来水公司的网络版自来水多种类业务管理软件。根据各大自来水公司存在的问题和需求自主...
某某自来水业务系统,是一套适合各种规模自来水公司的网络版自来水多种类业务管理软件。根据各大自来水公司存在的问题和需求自主...
某某自来水业务系统,是一套适合各种规模自来水公司的网络版自来水多种类业务管理软件。根据各大自来水公司存在的问题和需求自主...
某某自来水业务系统,是一套适合各种规模自来水公司的网络版自来水多种类业务管理软件。根据各大自来水公司存在的问题和需求自主...