2、调度策略基础:节点选择器(nodeSelector)、亲和性与反亲和性概念

Kubernetes 调度器(kube-scheduler)在将 Pod 绑定到合适节点时,除了默认的“资源足够”与“节点未污染”等硬性条件外,还提供了一系列节点选择与约束机制,用于控制 Pod 在集群中的分布位置。这些机制从简单到复杂依次为:nodeSelector、节点亲和性(nodeAffinity)、Pod 间亲和性(podAffinity)与 Pod 间反亲和性(podAntiAffinity)。

理解这三类策略的表达能力与生效阶段,是后续学习拓扑分布约束与抢占事件复核的基础。

2.1 节点选择器(nodeSelector)—— 最简的标签匹配

nodeSelector 是 Kubernetes 最早提供的节点选择方式,属于硬性约束(required)。它在 Pod 的 spec 中指定一个键值对映射,调度器只会将 Pod 调度到包含所有指定标签的节点上。

关键特征:
  • 仅支持精确匹配(key=value),不支持集合运算(In/NotIn/Exists)。
  • 多个标签之间是逻辑与(AND)关系,必须全部满足。
  • 如果集群中没有节点满足所有标签,Pod 将一直处于 Pending 状态。
特性 nodeSelector 适用场景
匹配方式 精确等值(key=value) 简单环境隔离(如:disk=ssd)
逻辑关系 AND(所有条件必须满足) GPU 节点绑定(gpu=nvidia)
灵活性 低,不支持运算符 快速原型或小型集群
apiVersion: v1
kind: Pod
metadata:
  name: ssd-pod
spec:
  nodeSelector:
    disk: ssd          # 仅调度到标签 disk=ssd 的节点
  containers:
  - name: app
    image: nginx

2.2 亲和性与反亲和性—— 更丰富的表达力

亲和性与反亲和性在 nodeSelector 的基础上引入了运算符(In、NotIn、Exists、DoesNotExist、Gt、Lt)和软约束/硬约束(requiredDuringSchedulingIgnoredDuringExecution vs preferredDuringSchedulingIgnoredDuringExecution)的概念,使调度策略更加灵活。

根据作用对象的不同,亲和性分为两类:

  • 节点亲和性(nodeAffinity):控制 Pod 与节点标签的关系。
  • Pod 间亲和性(podAffinity / podAntiAffinity):控制 Pod 与其他 Pod 的拓扑位置关系。
记忆口诀:“节点亲和看节点,Pod 亲和看邻居;硬约束必须满足,软约束尽量满足。”

2.3 节点亲和性(nodeAffinity)详解

节点亲和性允许使用表达式来匹配节点标签,并支持权重(weight)机制。其结构分为两个子字段:

字段 类型 说明
requiredDuringSchedulingIgnoredDuringExecution 硬约束 调度时必须满足,否则 Pod 不调度;运行期间节点标签变化不影响已运行 Pod
preferredDuringSchedulingIgnoredDuringExecution 软约束 调度时尽量满足,不满足仍可调度到其他节点;可设置 weight(1-100)
apiVersion: v1
kind: Pod
metadata:
  name: node-affinity-pod
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: topology.kubernetes.io/zone
            operator: In
            values:
            - us-east-1a
            - us-east-1b
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 80
        preference:
          matchExpressions:
          - key: instance-type
            operator: In
            values:
            - c5.large
  containers:
  - name: app
    image: nginx
注意:nodeSelectorTerms 下多个 matchExpressions 之间是OR关系(满足任一即可);而单个 matchExpressions 内的多个表达式是AND关系(必须全部满足)。这一逻辑与 nodeSelector 的纯 AND 不同,容易混淆。

2.4 Pod 间亲和性与反亲和性

Pod 间亲和性用于控制同一 Pod 与其他 Pod 在拓扑上的相对位置。它依赖 topologyKey 来定义“拓扑域”的粒度(如 kubernetes.io/hostname 表示节点级别,topology.kubernetes.io/zone 表示可用区级别)。

类型 作用 典型场景
podAffinity 将 Pod 调度到靠近某些 Pod 的拓扑域 Web 与缓存同节点/同可用区,降低延迟
podAntiAffinity 将 Pod 调度到远离某些 Pod 的拓扑域 避免同一应用多个副本部署在同一节点/可用区
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-anti-affinity
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - web
            topologyKey: kubernetes.io/hostname
      containers:
      - name: nginx
        image: nginx
关键设计原则:
  • Pod 间亲和性/反亲和性只对同一命名空间内的 Pod 生效(除非设置 namespaceSelector)。
  • topologyKey 不能为空,且对于反亲和性,topologyKey 不能是 kubernetes.io/hostname 以外的任意标签(除非集群配置了 MatchLabelKeys 等高级特性)。
  • 反亲和性如果设置为 required 且副本数超过拓扑域数量,会导致部分 Pod 无法调度(Pending)。
K8s 调度策略选择流程 Pod 调度请求 是否使用 nodeSelector? 是 精确标签匹配(AND) 否 节点亲和性评估 Pod 间亲和性/反亲和性评估 拓扑域约束(topologyKey) 节点评分与绑定 说明:调度器按 nodeSelector → 节点亲和性 → Pod 间亲和性顺序评估,最终综合评分选出最优节点

2.5 三种策略对比总结

维度 nodeSelector nodeAffinity podAffinity / podAntiAffinity
作用对象 节点标签 节点标签 其他 Pod 的标签
匹配能力 精确等值 In/NotIn/Exists/DoesNotExist/Gt/Lt In/NotIn/Exists/DoesNotExist
约束类型 仅硬约束 硬约束 + 软约束(带权重) 硬约束 + 软约束(带权重)
拓扑感知 无 无 依赖 topologyKey 定义拓扑域
典型用途 快速绑定专用节点 按实例类型、可用区精细调度 高可用分散、缓存就近部署
最佳实践建议:
  1. 优先使用 nodeAffinity 替代 nodeSelector,以获得更灵活的表达式支持。
  2. 对于高可用应用,务必使用 podAntiAffinity 并设置 topologyKey: kubernetes.io/hostname,避免同一应用多个副本落在同一节点。
  3. 软约束的 weight 值建议差异化设置(如 80/20),避免多个软约束权重相同导致调度器无法区分优先级。
  4. 避免在 requiredDuringScheduling 中使用过于严格的 Pod 间反亲和性,否则可能导致副本数无法满足调度需求。