3、节点亲和性(nodeAffinity):requiredDuringSchedulingIgnoredDuringExecution 与 preferredDuringSchedulingIgnoredDuringExecution 详解
节点亲和性是 Kubernetes 调度器将 Pod 绑定到特定节点集合的核心策略之一。与简单的 nodeSelector 精确匹配不同,nodeAffinity 提供了丰富的表达式匹配能力,支持硬性约束和软性偏好两种语义,分别对应 requiredDuringSchedulingIgnoredDuringExecution 和 preferredDuringSchedulingIgnoredDuringExecution 规则。
3.1 两种调度语义对比
| 特性 | requiredDuringSchedulingIgnoredDuringExecution | preferredDuringSchedulingIgnoredDuringExecution |
|---|---|---|
| 语义类型 | 硬性约束(Hard Constraint) | 软性偏好(Soft Preference) |
| 调度行为 | 必须满足所有匹配规则,否则 Pod 无法调度 | 尽量满足,若不满足则调度到其他可用节点 |
| 权重支持 | 不支持权重,规则必须全部满足 | 支持权重(weight 1-100),权重越高优先级越大 |
| 执行阶段 | 仅在调度时检查(Scheduling) | 仅在调度时评分(Scheduling) |
| 运行时忽略 | 节点标签变更后,已运行 Pod 不受影响(IgnoredDuringExecution) | 节点标签变更后,已运行 Pod 不受影响(IgnoredDuringExecution) |
| 典型场景 | GPU 节点、合规节点、专用硬件节点 | 可用区均衡、机型偏好、成本优化 |
关键理解:两种规则的 "IgnoredDuringExecution" 后缀意味着:一旦 Pod 成功运行在某个节点上,即使该节点的标签后续发生变化导致不再匹配亲和性规则,Kubernetes 也不会主动驱逐该 Pod。这种设计保证了运行时的稳定性,避免因标签变更引发大规模 Pod 迁移。
3.2 requiredDuringSchedulingIgnoredDuringExecution 硬性约束
该规则使用 matchExpressions 定义一组条件,调度器必须全部满足才能将 Pod 绑定到节点。支持的操作符包括 In、NotIn、Exists、DoesNotExist。
apiVersion: v1
kind: Pod
metadata:
name: gpu-inference-pod
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: accelerator
operator: In
values:
- nvidia-tesla-v100
- nvidia-a100
- key: node-type
operator: In
values:
- gpu-worker
containers:
- name: inference
image: nvidia/cuda:12.0-base
调度逻辑说明:
nodeSelectorTerms列表中的多个条目是或(OR)关系,满足任意一个条目即可。- 每个条目内的
matchExpressions列表是与(AND)关系,必须全部满足。 - 上例中 Pod 只能调度到同时满足
accelerator In (nvidia-tesla-v100, nvidia-a100)和node-type In (gpu-worker)的节点。
3.3 preferredDuringSchedulingIgnoredDuringExecution 软性偏好
该规则通过 preference 和 weight 定义一组偏好条件。调度器会为每个候选节点计算加权得分,得分最高的节点优先被选中。若没有节点满足偏好,Pod 仍可调度到其他节点。
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 5
template:
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80
preference:
matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- us-east-1a
- weight: 20
preference:
matchExpressions:
- key: instance-type
operator: In
values:
- c5.large
containers:
- name: nginx
image: nginx:1.25
评分机制说明:
- 每个偏好规则独立计算,满足则累加对应权重,不满足则加 0。
- 上例中,节点若同时位于
us-east-1a可用区且为c5.large实例类型,得分为 80 + 20 = 100。 - 若仅满足可用区条件,得分为 80;仅满足实例类型,得分为 20;均不满足得分为 0。
- 调度器在所有候选节点中选择得分最高的节点,得分相同时按其他调度策略(如资源均衡)进一步决策。
3.4 节点亲和性调度决策流程
3.5 组合使用与最佳实践
在实际生产环境中,requiredDuringScheduling 和 preferredDuringScheduling 通常组合使用,形成"硬约束兜底 + 软偏好优化"的调度策略。
apiVersion: apps/v1
kind: Deployment
metadata:
name: ai-training-job
spec:
replicas: 3
template:
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: node-role.kubernetes.io/gpu
operator: Exists
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 70
preference:
matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- us-west-2a
- weight: 30
preference:
matchExpressions:
- key: gpu-memory
operator: Gt
values:
- "80"
containers:
- name: trainer
image: pytorch/pytorch:2.0.0-cuda11.7
组合策略解读:
- 硬约束:Pod 必须调度到带有
node-role.kubernetes.io/gpu标签的节点,确保 GPU 资源可用。 - 软偏好 1(权重 70):优先选择
us-west-2a可用区,实现可用区亲和,减少跨区网络延迟。 - 软偏好 2(权重 30):优先选择 GPU 显存大于 80GB 的节点,提升大模型训练性能。
- 兜底逻辑:若
us-west-2a区没有满足条件的节点,Pod 仍可调度到其他可用区的 GPU 节点,不会阻塞训练任务。
3.6 常见避坑指南
| 问题场景 | 错误示例 | 正确做法 |
|---|---|---|
| 操作符误用 | 使用 In 匹配不存在的标签值 |
使用 Exists 检查标签是否存在,或确保标签值准确 |
| 权重设置过高 | 所有偏好权重设为 100,导致调度器无法区分优先级 | 按业务重要性分配差异化权重(如 80/20 或 70/30) |
| 硬约束过于严格 | 同时要求多个稀有标签,导致 Pod 长时间 Pending | 使用 nodeSelectorTerms 的 OR 关系提供多个备选条件 |
| 忽略运行时变更 | 期望节点标签变更后自动迁移 Pod | 使用 descheduler 或自定义控制器处理运行时重调度 |
| 标签命名冲突 | 使用 kubernetes.io/hostname 等系统标签做亲和性 |
使用自定义标签(如 workload-type、gpu-class)避免与系统标签混淆 |
性能注意:当集群规模较大(超过 500 节点)且
preferredDuringScheduling 规则较多时,调度器的评分计算会增加调度延迟。建议将偏好规则控制在 3-5 条以内,权重值使用 10 的倍数便于调试。
3.7 节点亲和性与 nodeSelector 的演进关系
nodeSelector 是 Kubernetes 早期提供的简单节点选择机制,仅支持精确的键值对匹配。节点亲和性在此基础上进行了全面升级:
- 表达能力:从精确匹配扩展到
In、NotIn、Exists、DoesNotExist、Gt、Lt六种操作符。 - 语义维度:从单一硬约束扩展到硬约束 + 软偏好双维度。
- 组合能力:支持 AND/OR 逻辑组合,实现复杂的调度策略。
- 扩展性:节点亲和性是调度框架的一部分,可与 Pod 间亲和性、拓扑分布约束协同工作。
在实际 YAML 编写中,nodeSelector 仍可作为一种简写形式存在,但官方推荐使用 nodeAffinity 替代,以获得更灵活的调度控制能力。