×

您可以使用 Pod 拓扑分布约束来对 Pod 在节点、区域、地域或其他用户定义的拓扑域之间的放置进行细粒度控制。跨故障域分布 Pod 有助于实现高可用性和更有效的资源利用。

用例示例

  • 作为管理员,我希望我的工作负载能够在 2 到 15 个 Pod 之间自动缩放。我希望确保当只有两个 Pod 时,它们不会放置在同一个节点上,以避免单点故障。

  • 作为管理员,我希望将我的 Pod 均匀分布在多个基础设施区域中,以减少延迟和网络成本。我希望确保我的集群在出现问题时能够自我修复。

重要注意事项

  • OpenShift Dedicated 集群中的 Pod 由工作负载控制器(例如 Deployment、StatefulSet 或 DaemonSet)管理。这些控制器定义一组 Pod 的所需状态,包括它们如何在集群中的节点之间进行分布和缩放。您应该在组中的所有 Pod 上设置相同的 Pod 拓扑分布约束,以避免混淆。使用工作负载控制器(例如 Deployment)时,Pod 模板通常会为您处理此问题。

  • 混合不同的 Pod 拓扑分布约束可能会使 OpenShift Dedicated 的行为令人困惑,并使故障排除更加困难。您可以通过确保拓扑域中的所有节点都一致地标记来避免这种情况。OpenShift Dedicated 自动填充众所周知的标签,例如kubernetes.io/hostname。这有助于避免手动标记节点的需要。这些标签提供了必要的拓扑信息,确保集群中节点标记的一致性。

  • 由于约束而进行分布时,只有同一命名空间中的 Pod 才会相互匹配并分组。

  • 您可以指定多个 Pod 拓扑分布约束,但必须确保它们不会相互冲突。必须满足所有 Pod 拓扑分布约束才能放置 Pod。

了解倾斜度和 maxSkew

倾斜度是指跨不同的拓扑域(例如区域或节点)匹配指定标签选择器的 Pod 数量的差异。

通过获取该域中 Pod 的数量与调度 Pod 最少的域中 Pod 的数量之间的绝对差值来计算每个域的倾斜度。设置maxSkew值可以指导调度程序保持平衡的 Pod 分布。

示例倾斜度计算

假设您有三个区域(A、B 和 C),并且您希望将您的 Pod 均匀分布到这些区域。如果区域 A 有 5 个 Pod,区域 B 有 3 个 Pod,区域 C 有 2 个 Pod,要找到倾斜度,您可以从当前每个区域中的 Pod 数量中减去调度 Pod 数量最少的区域中的 Pod 数量。这意味着区域 A 的倾斜度为 3,区域 B 的倾斜度为 1,区域 C 的倾斜度为 0。

maxSkew 参数

maxSkew 参数定义了任何两个拓扑域之间 Pod 数量的最大允许差异或倾斜度。如果将 maxSkew 设置为 1,则任何拓扑域中的 Pod 数量与任何其他域的 Pod 数量之差不得超过 1。如果倾斜度超过 maxSkew,调度程序将尝试以减少倾斜度的方式放置新的 Pod,同时遵守约束条件。

使用之前的示例倾斜度计算,倾斜度值超过默认的 maxSkew1。调度程序将新的 Pod 放置在区域 B 和区域 C 中以减少倾斜度并实现更均衡的分布,确保没有拓扑域的倾斜度超过 1。

Pod 拓扑分布约束的示例配置

您可以指定哪些 Pod 要组合在一起,它们分布在哪些拓扑域中,以及可接受的倾斜度。

以下示例演示了 Pod 拓扑分布约束配置。

根据区域分配匹配指定标签的 Pod 的示例
apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  labels:
    region: us-east
spec:
  securityContext:
    runAsNonRoot: true
    seccompProfile:
      type: RuntimeDefault
  topologySpreadConstraints:
  - maxSkew: 1 (1)
    topologyKey: topology.kubernetes.io/zone (2)
    whenUnsatisfiable: DoNotSchedule (3)
    labelSelector: (4)
      matchLabels:
        region: us-east (5)
    matchLabelKeys:
      - my-pod-label (6)
  containers:
  - image: "docker.io/ocpqe/hello-pod"
    name: hello-pod
    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        drop: [ALL]
1 任何两个拓扑域之间 Pod 数量的最大差异。默认为 1,您不能指定 0 值。
2 节点标签的键。具有此键和相同值的节点被认为位于同一拓扑中。
3 如果 Pod 不满足分布约束,如何处理该 Pod。默认为 DoNotSchedule,这告诉调度程序不要调度该 Pod。设置为 ScheduleAnyway 以仍然调度 Pod,但调度程序优先考虑遵守倾斜度,以免使集群更加不平衡。
4 匹配此标签选择器的 Pod 在传播以满足约束时被计算并识别为一个组。请务必指定标签选择器,否则无法匹配任何 Pod。
5 如果您希望将来正确计算该 Pod,请确保此 Pod规范也设置其标签以匹配此标签选择器。
6 用于选择要计算其传播的 Pod 的 Pod 标签键列表。
演示单个 Pod 拓扑分布约束的示例
kind: Pod
apiVersion: v1
metadata:
  name: my-pod
  labels:
    region: us-east
spec:
  securityContext:
    runAsNonRoot: true
    seccompProfile:
      type: RuntimeDefault
  topologySpreadConstraints:
  - maxSkew: 1
    topologyKey: topology.kubernetes.io/zone
    whenUnsatisfiable: DoNotSchedule
    labelSelector:
      matchLabels:
        region: us-east
  containers:
  - image: "docker.io/ocpqe/hello-pod"
    name: hello-pod
    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        drop: [ALL]

前面的示例定义了一个带有单个 Pod 拓扑分布约束的 Pod规范。它匹配标有 region: us-east 的 Pod,分布在区域之间,指定倾斜度为 1,如果不满足这些要求,则不调度 Pod。

演示多个 Pod 拓扑分布约束的示例
kind: Pod
apiVersion: v1
metadata:
  name: my-pod-2
  labels:
    region: us-east
spec:
  securityContext:
    runAsNonRoot: true
    seccompProfile:
      type: RuntimeDefault
  topologySpreadConstraints:
  - maxSkew: 1
    topologyKey: node
    whenUnsatisfiable: DoNotSchedule
    labelSelector:
      matchLabels:
        region: us-east
  - maxSkew: 1
    topologyKey: rack
    whenUnsatisfiable: DoNotSchedule
    labelSelector:
      matchLabels:
        region: us-east
  containers:
  - image: "docker.io/ocpqe/hello-pod"
    name: hello-pod
    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        drop: [ALL]

前面的示例定义了一个带有两个 Pod 拓扑分布约束的 Pod规范。两者都匹配标有 region: us-east 的 Pod,指定倾斜度为 1,如果不满足这些要求,则不调度 Pod。

第一个约束根据用户定义的标签 node 分布 Pod,第二个约束根据用户定义的标签 rack 分布 Pod。必须满足这两个约束才能调度 Pod。