3. 节点亲和性(Node Affinity)基础:requiredDuringSchedulingIgnoredDuringExecution 与 preferredDuringSchedulingIgnoredDuringExecution

节点亲和性(Node Affinity)是 Kubernetes 调度器将 Pod 绑定到特定节点的一种声明式规则。与简单的 nodeSelector 相比,Node Affinity 提供了更丰富的匹配表达式和更灵活的调度策略,是精细化节点池配置的核心工具。

3.1 为什么需要 Node Affinity?

在滚动升级节点池时,我们通常希望:

  • 强制绑定:某些关键 Pod 必须运行在特定硬件(如 GPU、SSD)或特定节点池上。
  • 倾向调度:在满足基本可用性的前提下,优先将 Pod 调度到性能更优或成本更低的节点池。
  • 避免冲突:防止 Pod 被调度到不兼容的节点(如操作系统版本、内核参数差异)。

Node Affinity 通过两种语义实现上述需求:requiredDuringSchedulingIgnoredDuringExecution(硬约束)和 preferredDuringSchedulingIgnoredDuringExecution(软约束)。

3.2 两种调度策略对比

特性 requiredDuringSchedulingIgnoredDuringExecution preferredDuringSchedulingIgnoredDuringExecution
语义 硬性要求,调度时必须满足 软性偏好,调度时尽量满足
调度失败行为 Pod 无法调度,Pending 状态 忽略偏好,调度到其他可用节点
执行阶段 仅在调度时检查 仅在调度时检查
运行时变更 忽略(不驱逐已有 Pod) 忽略(不驱逐已有 Pod)
权重支持 不支持 支持(weight 1-100)
典型场景 GPU 节点、合规节点、专用节点池 高性能节点优先、成本优化、区域分布
命名解读: 两个策略的后缀均为 IgnoredDuringExecution,意味着一旦 Pod 成功运行,即使节点标签发生变化,Kubernetes 也不会主动驱逐该 Pod。这是与 requiredDuringSchedulingRequiredDuringExecution(未来特性)的关键区别。

3.3 硬约束:requiredDuringSchedulingIgnoredDuringExecution

硬约束是调度器必须遵守的规则。如果没有任何节点满足条件,Pod 将一直处于 Pending 状态。其配置结构如下:

apiVersion: v1
kind: Pod
metadata:
  name: gpu-pod
spec:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: accelerator
            operator: In
            values:
            - nvidia-tesla-v100
            - nvidia-a100
  containers:
  - name: gpu-container
    image: nvidia/cuda:12.0-base

关键字段说明:

  • nodeSelectorTerms:多个条件之间是 OR 关系,满足任一即可。
  • matchExpressions:同一条件内的多个表达式是 AND 关系,必须全部满足。
  • operator:支持 In、NotIn、Exists、DoesNotExist、Gt、Lt。

3.4 软约束:preferredDuringSchedulingIgnoredDuringExecution

软约束为调度器提供偏好建议。调度器会计算每个候选节点的得分,得分越高越优先被选中。其配置结构如下:

apiVersion: v1
kind: Pod
metadata:
  name: performance-pod
spec:
  affinity:
    nodeAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
      - weight: 80
        preference:
          matchExpressions:
          - key: node-type
            operator: In
            values:
            - high-performance
      - weight: 20
        preference:
          matchExpressions:
          - key: zone
            operator: In
            values:
            - us-east-1a
  containers:
  - name: app
    image: nginx:1.25

权重计算逻辑:

  • 每个偏好规则独立计算,满足则累加对应 weight。
  • 所有满足规则的 weight 之和即为该节点的总分。
  • 调度器在所有可调度节点中选择总分最高的节点。
  • 如果所有节点都不满足任何偏好,Pod 仍会被调度到任意可用节点。

3.5 调度决策流程

Node Affinity 调度决策流程 Pod 创建请求 requiredDuringScheduling 检查 nodeSelectorTerms 满足 preferredDuringScheduling 计算权重得分 选择最高分节点 Pod 绑定到节点 Pod Pending 硬约束不满足 → Pod 无法调度;软约束不满足 → 仍可调度到其他节点

3.6 操作符详解

操作符 行为 示例
In 标签值在指定列表中 values: [ssd, nvme]
NotIn 标签值不在指定列表中 values: [hdd]
Exists 标签键存在(不关心值) key: gpu
DoesNotExist 标签键不存在 key: spot-instance
Gt 标签值大于指定数值(字符串比较) values: [4](vCPU > 4)
Lt 标签值小于指定数值(字符串比较) values: [8](内存 < 8GB)

3.7 实战建议与避坑

最佳实践:
  • 对关键业务 Pod 使用 requiredDuringScheduling 确保资源隔离。
  • 对弹性工作负载使用 preferredDuringScheduling 配合权重,实现成本与性能的平衡。
  • 避免在 requiredDuringScheduling 中使用过于严格的标签匹配,防止节点标签变更导致 Pod 大规模 Pending。
  • 结合 topologySpreadConstraints 使用,实现跨可用区的高可用部署。
常见陷阱:
  • 误将 nodeSelectorTerms 中的多个条件理解为 AND 关系(实际是 OR)。
  • 忘记给节点打标签,导致硬约束无法满足,Pod 一直 Pending。
  • 软约束权重设置过高(如 100),导致调度器过度倾斜,忽略其他调度策略。
  • 在滚动升级时,新旧节点池标签不一致,导致 Pod 调度到错误的节点池。

3.8 与 nodeSelector 的对比

特性 nodeSelector Node Affinity
表达能力 仅支持精确匹配 支持 In/NotIn/Exists/Gt/Lt 等
软约束 不支持 支持权重偏好
多条件组合 AND 关系 支持 OR + AND 组合
可读性 简单直观 配置稍复杂,但更灵活
推荐场景 简单标签匹配 复杂调度策略、节点池管理