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

Kubernetes 1.27:更细粒度的 Pod 拓扑分布策略达到 Beta

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

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

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

KEP-3022:Pod 拓扑分布中的 minDomains

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

但是,过去没有办法控制我们应该分布的域的数量。一些用户希望强制将 Pod 分布到最少数量的域上,如果当前域数量不足,则让集群自动伸缩器(cluster-autoscaler)来供应新的域。

Kubernetes v1.24 引入了 minDomains 参数作为 Pod 拓扑分布约束的 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 个节点上,但该 ReplicaSet 的另外 2 个 Pod 将处于不可调度状态,直到更多节点加入集群。

你可以想象集群自动伸缩器会根据这些不可调度的 Pod 来供应新节点,最终,副本将被分布在 5 个节点上。

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

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

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

应用这些策略的清单(manifest)如下所示:

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 组。在与 Deployment 一起使用拓扑分布时,通常的做法是使用 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 进行“与”运算,以选择将为传入 Pod 计算分布的现有 Pod 组。

有了 matchLabelKeys,你就不需要在不同修订版本之间更新 pod.spec。管理发布的控制器或操作员只需为不同修订版本设置相同标签键的不同值即可。调度器将根据 matchLabelKeys 自动假定这些值。例如,如果你正在配置一个 Deployment,你可以使用由 Deployment 控制器自动添加的、键为 pod-template-hash 的标签来区分单个 Deployment 中的不同修订版本。

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

参与进来

这些功能由 Kubernetes SIG Scheduling 管理。

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

我如何了解更多信息?