From ac725258d2763d010da119a74ded77fe748bf86e Mon Sep 17 00:00:00 2001 From: Qiming Teng Date: Fri, 13 Nov 2020 12:06:26 +0800 Subject: [PATCH] [zh] Resync pod-topology-spread-constraints page --- .../pods/pod-topology-spread-constraints.md | 532 +++++++++++++----- 1 file changed, 381 insertions(+), 151 deletions(-) diff --git a/content/zh/docs/concepts/workloads/pods/pod-topology-spread-constraints.md b/content/zh/docs/concepts/workloads/pods/pod-topology-spread-constraints.md index 4e7a2c5536..0f27485b4a 100644 --- a/content/zh/docs/concepts/workloads/pods/pod-topology-spread-constraints.md +++ b/content/zh/docs/concepts/workloads/pods/pod-topology-spread-constraints.md @@ -1,64 +1,46 @@ --- -title: Pod 拓扑扩展约束 +title: Pod 拓扑分布约束 content_type: concept -weight: 50 +weight: 40 --- -{{< feature-state for_k8s_version="v1.16" state="alpha" >}} - - -可以使用*拓扑扩展约束*来控制 {{< glossary_tooltip text="Pods" term_id="Pod" >}} 在集群内故障域(例如地区,区域,节点和其他用户自定义拓扑域)之间的分布。这可以帮助实现高可用以及提升资源利用率。 +你可以使用 _拓扑分布约束(Topology Spread Constraints)_ 来控制 +{{< glossary_tooltip text="Pods" term_id="Pod" >}} 在集群内故障域 +之间的分布,例如区域(Region)、可用区(Zone)、节点和其他用户自定义拓扑域。 +这样做有助于实现高可用并提升资源利用率。 -## 先决条件 - -### 启用功能 - - - -确保 `EvenPodsSpread` 功能已开启(在 1.16 版本中该功能默认关闭)。 -阅读[特性门控](/zh/docs/reference/command-line-tools-reference/feature-gates/)了解如何开启该功能。 -`EvenPodsSpread` 必须在 {{< glossary_tooltip text="API 服务器" term_id="kube-apiserver" >}} **和** -{{< glossary_tooltip text="调度器" term_id="kube-scheduler" >}} 中都开启。 - - -### 节点标签 +## 先决条件 {#prerequisites} + +### 节点标签 {#node-labels} -拓扑扩展约束依赖于节点标签来标识每个节点所在的拓扑域。例如,一个节点可能具有标签:`node=node1,zone=us-east-1a,region=us-east-1` +拓扑分布约束依赖于节点标签来标识每个节点所在的拓扑域。 +例如,某节点可能具有标签:`node=node1,zone=us-east-1a,region=us-east-1` -假设你拥有一个具有以下标签的 4 节点集群: +假设你拥有具有以下标签的一个 4 节点集群: ``` NAME STATUS ROLES AGE VERSION LABELS @@ -73,28 +55,40 @@ Then the cluster is logically viewed as below: --> 然后从逻辑上看集群如下: -``` -+---------------+---------------+ -| zoneA | zoneB | -+-------+-------+-------+-------+ -| node1 | node2 | node3 | node4 | -+-------+-------+-------+-------+ -``` +{{}} +graph TB + subgraph "zoneB" + n3(Node3) + n4(Node4) + end + subgraph "zoneA" + n1(Node1) + n2(Node2) + end + + classDef plain fill:#ddd,stroke:#fff,stroke-width:4px,color:#000; + classDef k8s fill:#326ce5,stroke:#fff,stroke-width:4px,color:#fff; + classDef cluster fill:#fff,stroke:#bbb,stroke-width:2px,color:#326ce5; + class n1,n2,n3,n4 k8s; + class zoneA,zoneB cluster; +{{< /mermaid >}} -可以复用在大多数集群上自动创建和填充的[常用标签](/zh/docs/reference/kubernetes-api/labels-annotations-taints/),而不是手动添加标签。 +你可以复用在大多数集群上自动创建和填充的 +[常用标签](/zh/docs/reference/kubernetes-api/labels-annotations-taints/), +而不是手动添加标签。 -## Pod 的拓扑约束 +## Pod 的分布约束 {#spread-constraints-for-pods} ### API `pod.spec.topologySpreadConstraints` 字段定义如下所示: @@ -114,10 +108,19 @@ spec: -可以定义一个或多个 `topologySpreadConstraint` 来指示 kube-scheduler 如何将每个传入的 Pod 根据与现有的 Pod 的关联关系在集群中部署。字段包括: +你可以定义一个或多个 `topologySpreadConstraint` 来指示 kube-scheduler +如何根据与现有的 Pod 的关联关系将每个传入的 Pod 部署到集群中。字段包括: -- **maxSkew** 描述 pod 分布不均的程度。这是给定拓扑类型中任意两个拓扑域中匹配的 pod 之间的最大允许差值。它必须大于零。 -- **topologyKey** 是节点标签的键。如果两个节点使用此键标记并且具有相同的标签值,则调度器会将这两个节点视为处于同一拓扑中。调度器试图在每个拓扑域中放置数量均衡的 pod。 -- **whenUnsatisfiable** 指示如果 pod 不满足扩展约束时如何处理: - - `DoNotSchedule`(默认)告诉调度器不用进行调度。 - - `ScheduleAnyway` 告诉调度器在对最小化倾斜的节点进行优先级排序时仍对其进行调度。 -- **labelSelector** 用于查找匹配的 pod。匹配此标签的 pod 将被统计,以确定相应拓扑域中 pod 的数量。 +- **maxSkew** 描述 Pod 分布不均的程度。这是给定拓扑类型中任意两个拓扑域中 + 匹配的 pod 之间的最大允许差值。它必须大于零。取决于 `whenUnsatisfiable` 的 + 取值,其语义会有不同。 + - 当 `whenUnsatisfiable` 等于 "DoNotSchedule" 时,`maxSkew` 是目标拓扑域 + 中匹配的 Pod 数与全局最小值之间可存在的差异。 + - 当 `whenUnsatisfiable` 等于 "ScheduleAnyway" 时,调度器会更为偏向能够降低 + 偏差值的拓扑域。 +- **topologyKey** 是节点标签的键。如果两个节点使用此键标记并且具有相同的标签值, + 则调度器会将这两个节点视为处于同一拓扑域中。调度器试图在每个拓扑域中放置数量 + 均衡的 Pod。 +- **whenUnsatisfiable** 指示如果 Pod 不满足分布约束时如何处理: + - `DoNotSchedule`(默认)告诉调度器不要调度。 + - `ScheduleAnyway` 告诉调度器仍然继续调度,只是根据如何能将偏差最小化来对 + 节点进行排序。 +- **labelSelector** 用于查找匹配的 pod。匹配此标签的 Pod 将被统计,以确定相应 + 拓扑域中 Pod 的数量。 有关详细信息,请参考[标签选择算符](/zh/docs/concepts/overview/working-with-objects/labels/#label-selectors)。 -执行 `kubectl explain Pod.spec.topologySpreadConstraints` 命令了解更多关于 topologySpreadConstraints 的信息。 +你可以执行 `kubectl explain Pod.spec.topologySpreadConstraints` 命令以 +了解关于 topologySpreadConstraints 的更多信息。 -### 例子:单个拓扑扩展约束 +### 例子:单个 TopologySpreadConstraint -假设你拥有一个 4 节点集群,其中标记为 `foo:bar` 的 3 个 pod 分别位于 node1,node2 和 node3 中(`P` 表示 pod): +假设你拥有一个 4 节点集群,其中标记为 `foo:bar` 的 3 个 Pod 分别位于 +node1、node2 和 node3 中: -``` -+---------------+---------------+ -| zoneA | zoneB | -+-------+-------+-------+-------+ -| node1 | node2 | node3 | node4 | -+-------+-------+-------+-------+ -| P | P | P | | -+-------+-------+-------+-------+ -``` +{{}} +graph BT + subgraph "zoneB" + p3(Pod) --> n3(Node3) + n4(Node4) + end + subgraph "zoneA" + p1(Pod) --> n1(Node1) + p2(Pod) --> n2(Node2) + end + + classDef plain fill:#ddd,stroke:#fff,stroke-width:4px,color:#000; + classDef k8s fill:#326ce5,stroke:#fff,stroke-width:4px,color:#fff; + classDef cluster fill:#fff,stroke:#bbb,stroke-width:2px,color:#326ce5; + class n1,n2,n3,n4,p1,p2,p3 k8s; + class zoneA,zoneB cluster; +{{< /mermaid >}} -如果希望传入的 pod 均匀散布在现有的 pod 区域,则可以指定字段如下: +如果希望新来的 Pod 均匀分布在现有的可用区域,则可以按如下设置其规约: {{< codenew file="pods/topology-spread-constraints/one-constraint.yaml" >}} -`topologyKey: zone` 意味着均匀分布将只应用于存在标签对为 "zone:<any value>" 的节点上。 -`whenUnsatisfiable: DoNotSchedule` 告诉调度器,如果传入的 pod 不满足约束,则让它保持悬决状态。 +`topologyKey: zone` 意味着均匀分布将只应用于存在标签键值对为 +"zone:<any value>" 的节点。 +`whenUnsatisfiable: DoNotSchedule` 告诉调度器如果新的 Pod 不满足约束, +则让它保持悬决状态。 -如果调度器将传入的 pod 放入 "zoneA",pod 分布将变为 [3, 1],因此实际的倾斜为 2(3 - 1)。 -这违反了 `maxSkew: 1`。此示例中,传入的 pod 只能放置在 "zoneB" 上: +如果调度器将新的 Pod 放入 "zoneA",Pods 分布将变为 [3, 1],因此实际的偏差 +为 2(3 - 1)。这违反了 `maxSkew: 1` 的约定。此示例中,新 Pod 只能放置在 +"zoneB" 上: -``` -+---------------+---------------+ +---------------+---------------+ -| zoneA | zoneB | | zoneA | zoneB | -+-------+-------+-------+-------+ +-------+-------+-------+-------+ -| node1 | node2 | node3 | node4 | OR | node1 | node2 | node3 | node4 | -+-------+-------+-------+-------+ +-------+-------+-------+-------+ -| P | P | P | P | | P | P | P P | | -+-------+-------+-------+-------+ +-------+-------+-------+-------+ -``` +{{}} +graph BT + subgraph "zoneB" + p3(Pod) --> n3(Node3) + p4(mypod) --> n4(Node4) + end + subgraph "zoneA" + p1(Pod) --> n1(Node1) + p2(Pod) --> n2(Node2) + end + + classDef plain fill:#ddd,stroke:#fff,stroke-width:4px,color:#000; + classDef k8s fill:#326ce5,stroke:#fff,stroke-width:4px,color:#fff; + classDef cluster fill:#fff,stroke:#bbb,stroke-width:2px,color:#326ce5; + class n1,n2,n3,n4,p1,p2,p3 k8s; + class p4 plain; + class zoneA,zoneB cluster; +{{< /mermaid >}} + +或者 + +{{}} +graph BT + subgraph "zoneB" + p3(Pod) --> n3(Node3) + p4(mypod) --> n3 + n4(Node4) + end + subgraph "zoneA" + p1(Pod) --> n1(Node1) + p2(Pod) --> n2(Node2) + end + + classDef plain fill:#ddd,stroke:#fff,stroke-width:4px,color:#000; + classDef k8s fill:#326ce5,stroke:#fff,stroke-width:4px,color:#fff; + classDef cluster fill:#fff,stroke:#bbb,stroke-width:2px,color:#326ce5; + class n1,n2,n3,n4,p1,p2,p3 k8s; + class p4 plain; + class zoneA,zoneB cluster; +{{< /mermaid >}} -可以调整 pod 规格以满足各种要求: +你可以调整 Pod 规约以满足各种要求: -- 将 `maxSkew` 更改为更大的值,比如 "2",这样传入的 pod 也可以放在 "zoneA" 上。 -- 将 `topologyKey` 更改为 "node",以便将 pod 均匀分布在节点上而不是区域中。 - 在上面的例子中,如果 `maxSkew` 保持为 "1",那么传入的 pod 只能放在 "node4" 上。 +- 将 `maxSkew` 更改为更大的值,比如 "2",这样新的 Pod 也可以放在 "zoneA" 上。 +- 将 `topologyKey` 更改为 "node",以便将 Pod 均匀分布在节点上而不是区域中。 + 在上面的例子中,如果 `maxSkew` 保持为 "1",那么传入的 Pod 只能放在 "node4" 上。 - 将 `whenUnsatisfiable: DoNotSchedule` 更改为 `whenUnsatisfiable: ScheduleAnyway`, - 以确保传入的 Pod 始终可以调度(假设满足其他的调度 API)。 - 但是,最好将其放置在具有较少匹配 Pod 的拓扑域中。 - (请注意,此优先性与其他内部调度优先级(如资源使用率等)一起进行标准化。) + 以确保新的 Pod 始终可以被调度(假设满足其他的调度 API)。 + 但是,最好将其放置在匹配 Pod 数量较少的拓扑域中。 + (请注意,这一优先判定会与其他内部调度优先级(如资源使用率等)排序准则一起进行标准化。) -### 例子:多个拓扑扩展约束 +### 例子:多个 TopologySpreadConstraints - 下面的例子建立在前面例子的基础上。假设你拥有一个 4 节点集群,其中 3 个标记为 `foo:bar` 的 -Pod 分别位于 node1,node2 和 node3 上(`P` 表示 Pod): +Pod 分别位于 node1、node2 和 node3 上: -``` -+---------------+---------------+ -| zoneA | zoneB | -+-------+-------+-------+-------+ -| node1 | node2 | node3 | node4 | -+-------+-------+-------+-------+ -| P | P | P | | -+-------+-------+-------+-------+ -``` +{{}} +graph BT + subgraph "zoneB" + p3(Pod) --> n3(Node3) + n4(Node4) + end + subgraph "zoneA" + p1(Pod) --> n1(Node1) + p2(Pod) --> n2(Node2) + end + + classDef plain fill:#ddd,stroke:#fff,stroke-width:4px,color:#000; + classDef k8s fill:#326ce5,stroke:#fff,stroke-width:4px,color:#fff; + classDef cluster fill:#fff,stroke:#bbb,stroke-width:2px,color:#326ce5; + class n1,n2,n3,n4,p1,p2,p3 k8s; + class p4 plain; + class zoneA,zoneB cluster; +{{< /mermaid >}} -可以使用 2 个拓扑扩展约束来控制 pod 在 区域和节点两个维度上进行分布: +可以使用 2 个 TopologySpreadConstraint 来控制 Pod 在 区域和节点两个维度上的分布: {{< codenew file="pods/topology-spread-constraints/two-constraints.yaml" >}} -在这种情况下,为了匹配第一个约束,传入的 pod 只能放置在 "zoneB" 中;而在第二个约束中, -传入的 Pod 只能放置在 "node4" 上。然后两个约束的结果加在一起,因此唯一可行的选择是放置在 "node4" 上。 +在这种情况下,为了匹配第一个约束,新的 Pod 只能放置在 "zoneB" 中;而在第二个约束中, +新的 Pod 只能放置在 "node4" 上。最后两个约束的结果加在一起,唯一可行的选择是放置 +在 "node4" 上。 -多个约束可能导致冲突。假设有一个跨越 2 个区域的 3 节点集群: +多个约束之间可能存在冲突。假设有一个跨越 2 个区域的 3 节点集群: + +{{}} +graph BT + subgraph "zoneB" + p4(Pod) --> n3(Node3) + p5(Pod) --> n3 + end + subgraph "zoneA" + p1(Pod) --> n1(Node1) + p2(Pod) --> n1 + p3(Pod) --> n2(Node2) + end + + classDef plain fill:#ddd,stroke:#fff,stroke-width:4px,color:#000; + classDef k8s fill:#326ce5,stroke:#fff,stroke-width:4px,color:#fff; + classDef cluster fill:#fff,stroke:#bbb,stroke-width:2px,color:#326ce5; + class n1,n2,n3,n4,p1,p2,p3,p4,p5 k8s; + class zoneA,zoneB cluster; +{{< /mermaid >}} -``` -+---------------+-------+ -| zoneA | zoneB | -+-------+-------+-------+ -| node1 | node2 | nod3 | -+-------+-------+-------+ -| P P | P | P P | -+-------+-------+-------+ -``` 如果对集群应用 "two-constraints.yaml",会发现 "mypod" 处于 `Pending` 状态。 这是因为:为了满足第一个约束,"mypod" 只能放在 "zoneB" 中,而第二个约束要求 -"mypod" 只能放在 "node2" 上。pod 调度无法满足两种约束。 +"mypod" 只能放在 "node2" 上。Pod 调度无法满足两种约束。 -为了克服这种情况,可以增加 `maxSkew` 或修改其中一个约束,让其使用 +为了克服这种情况,你可以增加 `maxSkew` 或修改其中一个约束,让其使用 `whenUnsatisfiable: ScheduleAnyway`。 -### 约定 +### 约定 {#conventions} 这里有一些值得注意的隐式约定: -- 只有与传入 pod 具有相同命名空间的 pod 才能作为匹配候选者。 +- 只有与新的 Pod 具有相同命名空间的 Pod 才能作为匹配候选者。 - 没有 `topologySpreadConstraints[*].topologyKey` 的节点将被忽略。这意味着: - 1. 位于这些节点上的 pod 不影响 `maxSkew` 的计算。 + 1. 位于这些节点上的 Pod 不影响 `maxSkew` 的计算。 在上面的例子中,假设 "node1" 没有标签 "zone",那么 2 个 Pod 将被忽略, 因此传入的 Pod 将被调度到 "zoneA" 中。 - 2. 传入的 Pod 没有机会被调度到这类节点上。 + + 2. 新的 Pod 没有机会被调度到这类节点上。 在上面的例子中,假设一个带有标签 `{zone-typo: zoneC}` 的 "node5" 加入到集群, 它将由于没有标签键 "zone" 而被忽略。 -注意,如果传入 Pod 的 `topologySpreadConstraints[*].labelSelector` 与自身的标签不匹配,将会发生什么。 -在上面的例子中,如果移除传入 Pod 的标签,Pod 仍然可以调度到 "zoneB",因为约束仍然满足。 -然而,在调度之后,集群的不平衡程度保持不变。zoneA 仍然有 2 个带有 {foo:bar} 标签的 Pod, -zoneB 有 1 个带有 {foo:bar} 标签的 Pod。 -因此,如果这不是你所期望的,建议工作负载的 `topologySpreadConstraints[*].labelSelector` -与其自身的标签匹配。 +- 注意,如果新 Pod 的 `topologySpreadConstraints[*].labelSelector` 与自身的 + 标签不匹配,将会发生什么。 + 在上面的例子中,如果移除新 Pod 上的标签,Pod 仍然可以调度到 "zoneB",因为约束仍然满足。 + 然而,在调度之后,集群的不平衡程度保持不变。zoneA 仍然有 2 个带有 {foo:bar} 标签的 Pod, + zoneB 有 1 个带有 {foo:bar} 标签的 Pod。 + 因此,如果这不是你所期望的,建议工作负载的 `topologySpreadConstraints[*].labelSelector` + 与其自身的标签匹配。 +- 如果新 Pod 定义了 `spec.nodeSelector` 或 `spec.affinity.nodeAffinity`,则 + 不匹配的节点会被忽略。 -- 如果传入的 pod 定义了 `spec.nodeSelector` 或 `spec.affinity.nodeAffinity`,则将忽略不匹配的节点。 + 假设你有一个跨越 zoneA 到 zoneC 的 5 节点集群: - 假设有一个从 zonea 到 zonec 的 5 节点集群: + {{}} + graph BT + subgraph "zoneB" + p3(Pod) --> n3(Node3) + n4(Node4) + end + subgraph "zoneA" + p1(Pod) --> n1(Node1) + p2(Pod) --> n2(Node2) + end - ``` - +---------------+---------------+-------+ - | zoneA | zoneB | zoneC | - +-------+-------+-------+-------+-------+ - | node1 | node2 | node3 | node4 | node5 | - +-------+-------+-------+-------+-------+ - | P | P | P | | | - +-------+-------+-------+-------+-------+ - ``` + classDef plain fill:#ddd,stroke:#fff,stroke-width:4px,color:#000; + classDef k8s fill:#326ce5,stroke:#fff,stroke-width:4px,color:#fff; + classDef cluster fill:#fff,stroke:#bbb,stroke-width:2px,color:#326ce5; + class n1,n2,n3,n4,p1,p2,p3 k8s; + class p4 plain; + class zoneA,zoneB cluster; + {{< /mermaid >}} - 你知道 "zoneC" 必须被排除在外。在这种情况下,可以按如下方式编写 yaml,以便将 "mypod" 放置在 "zoneB" 上,而不是 "zoneC" 上。同样,`spec.nodeSelector` 也要一样处理。 + {{}} + graph BT + subgraph "zoneC" + n5(Node5) + end - {{< codenew file="pods/topology-spread-constraints/one-constraint-with-nodeaffinity.yaml" >}} + classDef plain fill:#ddd,stroke:#fff,stroke-width:4px,color:#000; + classDef k8s fill:#326ce5,stroke:#fff,stroke-width:4px,color:#fff; + classDef cluster fill:#fff,stroke:#bbb,stroke-width:2px,color:#326ce5; + class n5 k8s; + class zoneC cluster; + {{< /mermaid >}} + + + 而且你知道 "zoneC" 必须被排除在外。在这种情况下,可以按如下方式编写 yaml, + 以便将 "mypod" 放置在 "zoneB" 上,而不是 "zoneC" 上。同样,`spec.nodeSelector` + 也要一样处理。 + + {{< codenew file="pods/topology-spread-constraints/one-constraint-with-nodeaffinity.yaml" >}} + + +### 集群级别的默认约束 {#cluster-level-default-constraints} + +为集群设置默认的拓扑分布约束也是可能的。默认拓扑分布约束在且仅在以下条件满足 +时才会应用到 Pod 上: + +- Pod 没有在其 `.spec.topologySpreadConstraints` 设置任何约束; +- Pod 隶属于某个服务、副本控制器、ReplicaSet 或 StatefulSet。 + + +你可以在 [调度方案(Schedulingg Profile)](/zh/docs/reference/scheduling/config/#profiles) +中将默认约束作为 `PodTopologySpread` 插件参数的一部分来设置。 +约束的设置采用[如前所述的 API](#api),只是 `labelSelector` 必须为空。 +选择算符是根据 Pod 所属的服务、副本控制器、ReplicaSet 或 StatefulSet 来设置的。 + +配置的示例可能看起来像下面这个样子: + +```yaml +apiVersion: kubescheduler.config.k8s.io/v1beta1 +kind: KubeSchedulerConfiguration + +profiles: + - pluginConfig: + - name: PodTopologySpread + args: + defaultConstraints: + - maxSkew: 1 + topologyKey: topology.kubernetes.io/zone + whenUnsatisfiable: ScheduleAnyway +``` + +{{< note >}} + +默认调度约束所生成的评分可能与 +[`SelectorSpread` 插件](/zh/docs/reference/scheduling/config/#scheduling-plugins). +所生成的评分有冲突。 +建议你在为 `PodTopologySpread` 设置默认约束是禁用调度方案中的该插件。 +{{< /note >}} + + +#### 内部默认约束 {#internal-default-constraints} + +{{< feature-state for_k8s_version="v1.19" state="alpha" >}} + + +当你启用了 `DefaultPodTopologySpread` 特性门控时,原来的 +`SelectorSpread` 插件会被禁用。 +kube-scheduler 会使用下面的默认拓扑约束作为 `PodTopologySpread` 插件的 +配置: + +```yaml +defaultConstraints: + - maxSkew: 3 + topologyKey: "kubernetes.io/hostname" + whenUnsatisfiable: ScheduleAnyway + - maxSkew: 5 + topologyKey: "topology.kubernetes.io/zone" + whenUnsatisfiable: ScheduleAnyway +``` + + +此外,原来用于提供等同行为的 `SelectorSpread` 插件也会被禁用。 + + +{{< note >}} +如果你的节点不会 **同时** 设置 `kubernetes.io/hostname` 和 +`topology.kubernetes.io/zone` 标签,你应该定义自己的约束而不是使用 +Kubernetes 的默认约束。 + +插件 `PodTopologySpread` 不会为未设置分布约束中所给拓扑键的节点评分。 +{{< /note >}} ## 与 PodAffinity/PodAntiAffinity 相比较 -在 Kubernetes 中,与 "Affinity" 相关的指令控制 pod 的调度方式(更密集或更分散)。 +在 Kubernetes 中,与“亲和性”相关的指令控制 Pod 的调度方式(更密集或更分散)。 -- 对于 `PodAffinity`,可以尝试将任意数量的 pod 打包到符合条件的拓扑域中。 -- 对于 `PodAntiAffinity`,只能将一个 pod 调度到单个拓扑域中。 +- 对于 `PodAffinity`,你可以尝试将任意数量的 Pod 集中到符合条件的拓扑域中。 +- 对于 `PodAntiAffinity`,只能将一个 Pod 调度到某个拓扑域中。 -"EvenPodsSpread" 功能提供灵活的选项来将 pod 均匀分布到不同的拓扑域中,以实现高可用性或节省成本。 -这也有助于滚动更新工作负载和平滑扩展副本。 -有关详细信息,请参考[动机](https://github.com/kubernetes/enhancements/blob/master/keps/sig-scheduling/20190221-pod-topology-spread.md#motivation)。 +要实现更细粒度的控制,你可以设置拓扑分布约束来将 Pod 分布到不同的拓扑域下, +从而实现高可用性或节省成本。这也有助于工作负载的滚动更新和平稳地扩展副本规模。 +有关详细信息,请参考 +[动机](https://github.com/kubernetes/enhancements/blob/master/keps/sig-scheduling/20190221-pod-topology-spread.md#motivation)文档。 - -## 已知局限性 - -1.16 版本(此功能为 alpha)存在下面的一些限制: - - -- `Deployment` 的缩容可能导致 pod 分布不平衡。 -- pod 匹配到污点节点是允许的。参考 [Issue 80921](https://github.com/kubernetes/kubernetes/issues/80921)。 +## 已知局限性 +- Deployment 缩容操作可能导致 Pod 分布不平衡。 +- 具有污点的节点上的 Pods 也会被统计。 + 参考 [Issue 80921](https://github.com/kubernetes/kubernetes/issues/80921)。 + +## {{% heading "whatsnext" %}} + + +- [博客: PodTopologySpread介绍](https://kubernetes.io/blog/2020/05/introducing-podtopologyspread/) + 详细解释了 `maxSkew`,并给出了一些高级的使用示例。