Pod 间亲和性与反亲和性

Pod 间亲和性与反亲和性使你可以基于已经在节点上运行的 Pod 的标签来约束 Pod 可以调度到的节点,而不是基于节点上的标签。

Pod 间亲和性与反亲和性的规则格式为“如果 X 上已经运行了一个或多个满足规则 Y 的 Pod, 则这个 Pod 应该(或者在反亲和性的情况下不应该)运行在 X 上”。 这里的 X 可以是节点、机架、云提供商可用区或地理区域或类似的拓扑域Y 则是 Kubernetes 尝试满足的规则

  • 通过标签选择算符的形式来表达规则(Y),并可根据需要指定关联的命名空间列表。针对 Pod 标签的所有标签选择算符都要指定命名空间,Kubernetes 会在指定的命名空间内寻找标签。

  • 通过 topologyKey 来表达拓扑域(X)的概念,其取值是系统用来标示域的节点标签键。

注意:

Pod 间亲和性和反亲和性都需要相当的计算量,因此会在大规模集群中显著降低调度速度。

不建议在包含数百个节点的集群中使用这类设置。

Pod 间亲和性与反亲和性的类型

与节点亲和性类似,Pod 的亲和性与反亲和性也有两种类型:

  • requiredDuringSchedulingIgnoredDuringExecution

  • preferredDuringSchedulingIgnoredDuringExecution

例如,你可以使用 requiredDuringSchedulingIgnoredDuringExecution 亲和性来告诉调度器, 将两个服务的 Pod 放到同一个云提供商可用区内,因为它们彼此之间通信非常频繁。 类似地,你可以使用 preferredDuringSchedulingIgnoredDuringExecution 反亲和性来将同一服务的多个 Pod 分布到多个云提供商可用区中。

  • 要使用 Pod 间亲和性,可以使用 Pod 规约中的 .affinity.podAffinity 字段。

  • 对于 Pod 间反亲和性,可以使用 Pod 规约中的 .affinity.podAntiAffinity 字段。

简单示例

简单示例
apiVersion: v1
kind: Pod
metadata:
  name: with-pod-affinity
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: security
            operator: In
            values:
            - S1
        topologyKey: topology.kubernetes.io/zone
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchExpressions:
            - key: security
              operator: In
              values:
              - S2
          topologyKey: topology.kubernetes.io/zone
  containers:
  - name: with-pod-affinity
    image: registry.cn-hangzhou.aliyuncs.com/google_containers/pause:2.0

本示例定义了一条 Pod 亲和性规则和一条 Pod 反亲和性规则。

  • Pod 亲和性规则配置为 requiredDuringSchedulingIgnoredDuringExecution

  • Pod 反亲和性配置为 preferredDuringSchedulingIgnoredDuringExecution

亲和性规则规定,只有节点属于特定的 区域 且该区域中的其他 Pod 已打上 security=S1 标签时,调度器才可以将示例 Pod 调度到此节点上。

  • 例如,如果我们有一个具有指定区域(称之为 "Zone V")的集群,此区域由带有 topology.kubernetes.io/zone=V 标签的节点组成,那么只要 Zone V 内已经至少有一个 Pod 打了 security=S1 标签, 调度器就可以将此 Pod 调度到 Zone V 内的任何节点。

  • 相反,如果 Zone V 中没有带有 security=S1 标签的 Pod, 则调度器不会将示例 Pod 调度给该区域中的任何节点。

反亲和性规则规定,如果节点属于特定的 区域 且该区域中的其他 Pod 已打上 security=S2 标签,则调度器应尝试避免将 Pod 调度到此节点上。

  • 例如,如果我们有一个具有指定区域(我们称之为 "Zone R")的集群,此区域由带有 topology.kubernetes.io/zone=R 标签的节点组成只要 Zone R 内已经至少有一个 Pod 打了 security=S2 标签, 调度器应避免将 Pod 分配给 Zone R 内的任何节点

  • 相反,如果 Zone R 中没有带有 security=S2 标签的 Pod, 则反亲和性规则不会影响将 Pod 调度到 Zone R。

operator

可以针对 Pod 间亲和性与反亲和性为其 operator 字段使用 InNotInExistsDoesNotExist 等值。

topologyKey

原则上,topologyKey 可以是任何合法的标签键。出于性能和安全原因,topologyKey 有一些限制:

  • 对于 Pod 亲和性而言,在 requiredDuringSchedulingIgnoredDuringExecution preferredDuringSchedulingIgnoredDuringExecution 中,topologyKey 不允许为空

  • 对于 requiredDuringSchedulingIgnoredDuringExecution 要求的 Pod 反亲和性, 准入控制器 LimitPodHardAntiAffinityTopology 要求 topologyKey 只能是 kubernetes.io/hostname。如果你希望使用其他定制拓扑逻辑, 你可以更改准入控制器或者禁用之。

命名空间

除了 labelSelector topologyKey,你也可以指定 labelSelector 要匹配的命名空间列表,方法是在 labelSelector 和 topologyKey 所在层同一层次上设置 namespaces 如果 namespaces 被忽略或者为空,则默认为 Pod 亲和性/反亲和性的定义所在的命名空间。

也可以使用 namespaceSelector 选择匹配的命名空间,namespaceSelector 是对命名空间集合进行标签查询的机制。 亲和性条件会应用到 namespaceSelector 所选择的命名空间和 namespaces 字段中所列举的命名空间之上。

注意:

空的 namespaceSelector({})会匹配所有命名空间,而 null 或者空的 namespaces 列表以及 null 值 namespaceSelector 意味着“当前 Pod 的命名空间”。

最后更新于