×

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

使用案例示例

  • 作为管理员,我希望我的工作负载能够自动在两个到十五个 Pod 之间进行扩展。我希望确保当只有两个 Pod 时,它们不会部署在同一个节点上,以避免单点故障。

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

重要注意事项

  • 在 AWS 集群上的 Red Hat OpenShift 服务中的 Pod 由部署、有状态集或守护进程集等_工作负载控制器_管理。这些控制器定义了一组 Pod 的所需状态,包括它们如何在集群中的节点上进行分布和扩展。您应该为一组中的所有 Pod 设置相同的 Pod 拓扑分布约束,以避免混淆。使用工作负载控制器(例如部署)时,Pod 模板通常会为您处理此问题。

  • 混合不同的 Pod 拓扑分布约束会使 AWS 上的 Red Hat OpenShift 服务的行为令人困惑,并使故障排除更加困难。您可以通过确保拓扑域中的所有节点都一致地标记来避免这种情况。AWS 上的 Red Hat OpenShift 服务会自动填充众所周知的标签,例如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,同时遵守约束。

使用前面的偏差计算示例,偏差值超过了默认的maxSkew值 1。调度程序将新 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。默认值为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 必须满足这两个约束才能被调度。