4. Pod间亲和性(podAffinity):拓扑键、拓扑域、跨Pod调度约束

Pod间亲和性(podAffinity)与反亲和性(podAntiAffinity)是Kubernetes调度系统中用于控制Pod与Pod之间相对位置的核心规则。与节点亲和性(nodeAffinity)不同,Pod间亲和性不关心Pod被调度到哪台具体节点,而是关心“与哪些Pod靠在一起”或“远离哪些Pod”。

4.1 核心概念:拓扑键与拓扑域

Pod间亲和性的调度决策依赖于两个关键抽象:拓扑键(topologyKey)和拓扑域(topology domain)。

概念 定义 示例值 说明
拓扑键 节点标签的Key,用于划分拓扑域 kubernetes.io/hostname 每个节点拥有唯一值,形成最小拓扑域
拓扑域 共享同一拓扑键值的节点集合 zone-a(所有topology.kubernetes.io/zone=zone-a的节点) 域的大小取决于拓扑键的粒度
调度约束 Pod必须/尽量与目标Pod位于同一拓扑域 requiredDuringScheduling 硬约束或软约束
关键理解:拓扑键决定了“以什么粒度来分组节点”。使用 kubernetes.io/hostname 意味着“同一台节点”;使用 topology.kubernetes.io/zone 意味着“同一个可用区”。拓扑域是拓扑键值相同的所有节点的集合。

4.2 调度约束类型

Pod间亲和性支持两种调度约束,与节点亲和性一致:

  • requiredDuringSchedulingIgnoredDuringExecution:硬约束。调度器必须满足该规则,否则Pod无法被调度。
  • preferredDuringSchedulingIgnoredDuringExecution:软约束。调度器尽量满足,但不强制。
注意:“IgnoredDuringExecution”意味着一旦Pod运行后,即使后续Pod的标签发生变化,也不会驱逐已运行的Pod。Kubernetes目前不支持“RequiredDuringExecution”模式。

4.3 Pod间亲和性(podAffinity)工作原理

当使用podAffinity时,调度器会:

  1. 在集群中查找所有满足labelSelector匹配条件的Pod。
  2. 获取这些Pod所在的节点。
  3. 根据topologyKey确定这些节点所属的拓扑域。
  4. 将待调度Pod调度到这些拓扑域内的任意节点上。
Pod间亲和性调度流程(podAffinity) 待调度Pod labelSelector 匹配目标Pod 获取目标Pod 所在节点 确定 拓扑域 拓扑域:topology.kubernetes.io/zone = zone-a Node-1 hostname: node-1 Node-2 hostname: node-2 Node-3 hostname: node-3 目标Pod (app=web) 待调度Pod 调度到同一拓扑域 内的任意节点

4.4 Pod间反亲和性(podAntiAffinity)

podAntiAffinity 与 podAffinity 的配置结构完全相同,但语义相反:它要求待调度Pod不要与目标Pod位于同一拓扑域。常用于将同一应用的多个副本分散到不同节点或可用区,实现高可用。

典型场景:将Nginx的3个副本分散到3个不同的可用区。使用 podAntiAffinity + topologyKey: topology.kubernetes.io/zone + requiredDuringScheduling,确保每个可用区最多运行1个Nginx Pod。

4.5 配置示例与参数解析

以下是一个完整的Pod间亲和性配置示例:

apiVersion: v1
kind: Pod
metadata:
  name: web-consumer
  labels:
    app: consumer
spec:
  affinity:
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - web
        topologyKey: topology.kubernetes.io/zone
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 100
        podAffinityTerm:
          labelSelector:
            matchLabels:
              app: consumer
          topologyKey: kubernetes.io/hostname
  containers:
  - name: nginx
    image: nginx:1.25
字段 路径 说明
labelSelector podAffinity[].podAffinityTerm 选择目标Pod的标签匹配规则,支持 matchLabels 和 matchExpressions
topologyKey podAffinity[].podAffinityTerm 定义拓扑域的节点标签Key
namespaces podAffinity[].podAffinityTerm 可选,限定目标Pod所在的命名空间,默认与待调度Pod同命名空间
weight preferredDuringScheduling 软约束的权重值,范围1-100,越高优先级越大

4.6 拓扑键选择策略

拓扑键的选择直接影响调度结果的分布粒度:

拓扑键 粒度 适用场景 注意事项
kubernetes.io/hostname 节点级 将Pod调度到同一台节点(亲和)或分散到不同节点(反亲和) 节点故障会导致所有同节点Pod不可用
topology.kubernetes.io/zone 可用区级 将Pod调度到同一可用区(低延迟)或分散到不同可用区(高可用) 需要集群已配置可用区标签
topology.kubernetes.io/region 区域级 跨区域亲和或反亲和 区域间网络延迟较高
自定义标签 自定义 按机架、GPU池、专用硬件分组 需要运维确保标签一致性
避坑指南:
  • podAntiAffinity 配合 requiredDuringScheduling + topologyKey: kubernetes.io/hostname 时,如果集群节点数少于Pod副本数,会导致部分Pod无法调度。
  • 不要将 topologyKey 设置为空字符串,Kubernetes会拒绝该配置。
  • 对于大规模集群,大量Pod间反亲和规则会增加调度器的计算开销,建议使用 preferred 而非 required。

4.7 与节点亲和性的对比

维度 节点亲和性(nodeAffinity) Pod间亲和性(podAffinity)
匹配对象 节点标签 Pod标签
调度依据 节点自身属性(机型、区域、GPU等) 集群中已运行的其他Pod的位置
拓扑域 隐式,通过节点标签分组 显式,通过 topologyKey 定义
典型场景 将Pod调度到SSD节点或特定区域 将Web Pod与Cache Pod部署在同一节点
配置复杂度 较低 较高,需考虑拓扑域和标签选择器

4.8 实践建议

  • 优先使用软约束:在非关键场景下,使用 preferredDuringScheduling 避免调度失败。
  • 合理选择拓扑键粒度:对于高可用场景,使用 topology.kubernetes.io/zone;对于本地缓存亲和场景,使用 kubernetes.io/hostname。
  • 组合使用亲和与反亲和:例如,要求Web Pod与Redis Pod在同一节点(亲和),但Web Pod的多个副本分散到不同节点(反亲和)。
  • 监控调度失败事件:使用 kubectl describe pod <pod-name> 查看调度事件,排查亲和性规则是否导致Pod Pending。