本文发表已超过一年。较早的文章可能包含过时的内容。请检查页面中的信息自发布以来是否已变得不正确。

Kubernetes 1.27:更细粒度的 Pod 拓扑分布策略进入 Beta 阶段

在 Kubernetes v1.19 中,Pod 拓扑分布约束已正式发布 (GA)。

随着时间的推移,我们 - SIG 调度 - 收到了用户的反馈,因此,我们正在积极地通过三个 KEP 来改进拓扑分布功能。所有这些功能在 Kubernetes v1.27 中都已达到 Beta 版,并且默认启用。

这篇博文介绍了每个功能及其背后的用例。

KEP-3022:Pod 拓扑分布中的最小域

Pod 拓扑分布具有 maxSkew 参数来定义 Pod 可能分布不均的程度。

但是,没有办法控制我们应该在其上分布的域的数量。一些用户希望强制将 Pod 分布在最少数量的域上,如果当前没有足够的域,则让集群自动扩缩器配置它们。

Kubernetes v1.24 为 pod 拓扑分布约束引入了 minDomains 参数,作为 alpha 功能。通过 minDomains 参数,您可以定义最小域数。

例如,假设有 3 个节点具有足够的容量,并且新创建的 ReplicaSet 的 Pod 模板中具有以下 topologySpreadConstraints

...
topologySpreadConstraints:
- maxSkew: 1
  minDomains: 5 # requires 5 Nodes at least (because each Node has a unique hostname).
  whenUnsatisfiable: DoNotSchedule # minDomains is valid only when DoNotSchedule is used.
  topologyKey: kubernetes.io/hostname
  labelSelector:
    matchLabels:
        foo: bar

在这种情况下,3 个 Pod 将被调度到这 3 个节点,但是此副本集中的其他 2 个 Pod 将无法调度,直到有更多节点加入集群。

您可以想象,集群自动扩缩器会根据这些无法调度的 Pod 配置新节点,因此,副本最终会分布在 5 个节点上。

KEP-3094:在计算 podTopologySpread 倾斜时考虑污点/容忍

在此增强之前,当您部署配置了 podTopologySpread 的 pod 时,kube-scheduler 会考虑满足 Pod 的 nodeAffinity 和 nodeSelector 的节点进行过滤和评分,但不会关心节点污点是否被传入的 pod 容忍。 这可能导致具有不容忍污点的节点成为唯一用于分布的候选者,因此,如果 pod 不容忍污点,则该 pod 将卡在 Pending 状态。

为了允许更精细地决定在计算分布倾斜时考虑哪些节点,Kubernetes 1.25 在 topologySpreadConstraints 中引入了两个新字段来定义节点包含策略:nodeAffinityPolicynodeTaintPolicy

应用这些策略的清单如下所示

apiVersion: v1
kind: Pod
metadata:
  name: example-pod
spec:
  # Configure a topology spread constraint
  topologySpreadConstraints:
    - maxSkew: <integer>
      # ...
      nodeAffinityPolicy: [Honor|Ignore]
      nodeTaintsPolicy: [Honor|Ignore]
  # other Pod fields go here

nodeAffinityPolicy 字段指示 Kubernetes 如何处理 Pod 的 nodeAffinitynodeSelector 以进行 pod 拓扑分布。 如果为 Honor,则 kube-scheduler 会在计算分布倾斜时过滤掉与 nodeAffinity/nodeSelector 不匹配的节点。 如果为 Ignore,则将包括所有节点,无论它们是否与 Pod 的 nodeAffinity/nodeSelector 匹配。

为了向后兼容,nodeAffinityPolicy 默认为 Honor

nodeTaintsPolicy 字段定义 Kubernetes 如何考虑节点污点以进行 pod 拓扑分布。 如果为 Honor,则仅包含传入 pod 具有容忍的受污节点,将包含在分布倾斜的计算中。 如果为 Ignore,则 kube-scheduler 在计算分布倾斜时将完全不考虑节点污点,因此,还将包括具有 pod 不容忍污点的节点。

为了向后兼容,nodeTaintsPolicy 默认为 Ignore

该功能在 v1.25 中作为 alpha 功能引入。默认情况下,它是禁用的,因此,如果您想在 v1.25 中使用此功能,则必须显式启用功能门 NodeInclusionPolicyInPodTopologySpread。在接下来的 v1.26 版本中,关联的功能已升级到 beta 版,并且默认启用。

KEP-3243:在滚动升级后遵守 Pod 拓扑分布

Pod 拓扑分布使用字段 labelSelector 来标识将计算分布的 pod 组。 当将拓扑分布与 Deployments 一起使用时,通常的做法是使用 Deployment 的 labelSelector 作为拓扑分布约束中的 labelSelector。 但是,这意味着 Deployment 的所有 pod 都是分布计算的一部分,无论它们是否属于不同的修订版。 因此,当新的修订版推出时,分布将应用于来自旧的和新的 ReplicaSet 的 pod,因此,当新的 ReplicaSet 完全推出并且旧的 ReplicaSet 回滚时,我们剩下的实际分布可能与预期不符,因为来自较旧 ReplicaSet 的已删除 pod 会导致其余 pod 的分布倾斜。 为了避免此问题,过去用户需要在 Deployment 中添加修订版标签,并在每次滚动升级时手动更新它(包括 pod 模板上的标签和 topologySpreadConstraints 中的 labelSelector)。

为了使用更简单的 API 解决此问题,Kubernetes v1.25 在 topologySpreadConstraints 中引入了一个名为 matchLabelKeys 的新字段。 matchLabelKeys 是 pod 标签键的列表,用于选择将计算分布的 pod。 这些键用于查找正在调度的 Pod 的标签中的值,这些键值标签与 labelSelector 进行 AND 运算,以选择将为传入 pod 计算分布的现有 pod 组。

使用 matchLabelKeys,您无需在不同的修订版之间更新 pod.spec。 管理 rollouts 的控制器或操作员只需要为不同修订版的相同标签键设置不同的值。 调度程序将根据 matchLabelKeys 自动假定这些值。 例如,如果您正在配置 Deployment,则可以使用带有 pod-template-hash 键的标签,该标签由 Deployment 控制器自动添加,以区分单个 Deployment 中的不同修订版。

topologySpreadConstraints:
    - maxSkew: 1
      topologyKey: kubernetes.io/hostname
      whenUnsatisfiable: DoNotSchedule
      labelSelector:
        matchLabels:
          app: foo
      matchLabelKeys:
        - pod-template-hash

参与其中

这些功能由 Kubernetes SIG 调度管理。

请加入我们并分享您的反馈。我们期待收到您的来信!

如何了解更多?