这篇文章已超过一年。较旧的文章可能包含过时内容。请检查页面中的信息自发布以来是否已不再准确。

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

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

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

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

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

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

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

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 个节点上,但这个 ReplicaSet 中的另外 2 个 Pod 将保持不可调度,直到更多节点加入集群。

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

KEP-3094:在计算 Pod 拓扑分布偏斜时考虑污点/容忍度

在此增强功能之前,当你部署配置了 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 中使用此特性,必须显式启用 feature gate NodeInclusionPolicyInPodTopologySpread。在随后的 v1.26 版本中,该关联特性升级到 Beta 并默认启用。

KEP-3243:滚动升级后尊重 Pod 拓扑分布

Pod 拓扑分布使用 labelSelector 字段来标识用于计算分布的 Pod 组。在使用 Deployment 进行拓扑分布时,通常的做法是将 Deployment 的 labelSelector 用作拓扑分布约束中的 labelSelector。然而,这意味着 Deployment 的所有 Pod,无论是否属于不同的修订版本,都参与分布计算。因此,当推出新修订版本时,分布将应用于新旧 ReplicaSets 中的 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。管理 rollout 的控制器或 Operator 只需为不同的修订版本设置相同标签键的不同值。调度器将根据 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 管理。

请加入我们并分享你的反馈。我们期待你的参与!

我如何了解更多?