节点亲和性类型:requiredDuringScheduling 与 preferredDuringScheduling
在 Kubernetes 调度器中,节点亲和性(Node Affinity)通过两种语义类型控制 Pod 与节点的匹配关系:requiredDuringSchedulingIgnoredDuringExecution(硬约束)和 preferredDuringSchedulingIgnoredDuringExecution(软约束)。这两种类型决定了调度器在 Pod 调度阶段的行为,以及在节点运行时状态变化后的处理策略。
核心概念对比
| 特性 | requiredDuringSchedulingIgnoredDuringExecution | preferredDuringSchedulingIgnoredDuringExecution |
|---|---|---|
| 调度阶段行为 | 强制匹配:节点必须满足所有规则,否则 Pod 无法调度 | 偏好匹配:调度器优先选择满足规则的节点,但不强制 |
| 执行阶段行为 | 忽略:节点标签变更后,已运行的 Pod 不受影响 | 忽略:节点标签变更后,已运行的 Pod 不受影响 |
| 调度失败后果 | Pod 处于 Pending 状态,无法被调度 | Pod 仍可调度到不满足规则的节点 |
| 权重机制 | 不支持权重,所有规则必须同时满足 | 支持权重(weight),用于计算节点优先级 |
| 典型场景 | 合规性要求、GPU 节点绑定、数据本地化 | 性能优化、负载均衡、成本控制 |
requiredDuringSchedulingIgnoredDuringExecution 详解
该类型是调度器的硬性约束。调度器在决策时必须确保目标节点满足所有 matchExpressions 中定义的规则。如果没有任何节点满足条件,Pod 将一直处于 Pending 状态,直到出现符合条件的节点或规则被修改。
配置示例
apiVersion: v1
kind: Pod
metadata:
name: gpu-workload
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: accelerator
operator: In
values:
- nvidia-tesla-v100
- nvidia-a100
- key: gpu-count
operator: Gt
values:
- "2"
containers:
- name: cuda-container
image: nvidia/cuda:12.0-base
上述配置要求节点必须同时满足:标签 accelerator 的值为 nvidia-tesla-v100 或 nvidia-a100,且 gpu-count 的值大于 2。两个条件使用逻辑与(AND)组合。
preferredDuringSchedulingIgnoredDuringExecution 详解
该类型是软性偏好。调度器会尝试将 Pod 调度到满足规则的节点上,但如果所有节点都不满足,Pod 仍然可以被调度到其他节点。每个偏好规则可以设置 weight(权重,范围 1-100),调度器会计算所有满足规则的节点得分,得分高的节点优先被选中。
权重计算机制
调度器对每个节点执行以下计算:
- 遍历所有
preferredDuringScheduling规则 - 如果节点满足某条规则,则累加该规则的权重值
- 所有规则检查完毕后,将总分归一化到 0-100 范围
- 得分最高的节点被选中
配置示例
apiVersion: v1
kind: Pod
metadata:
name: web-server
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80
preference:
matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- us-east-1a
- us-east-1b
- weight: 20
preference:
matchExpressions:
- key: node-type
operator: NotIn
values:
- spot-instance
containers:
- name: nginx
image: nginx:1.25
此配置优先将 Pod 调度到 us-east-1a 或 us-east-1b 可用区(权重 80),同时避免 spot-instance 节点(权重 20)。如果所有节点都不在首选可用区,Pod 仍可调度到其他区域。
调度决策流程对比
运算符支持
两种亲和性类型都支持以下运算符,用于构建灵活的匹配规则:
| 运算符 | 行为 | 示例 |
|---|---|---|
In |
标签值在指定集合中 | values: [ssd, nvme] |
NotIn |
标签值不在指定集合中 | values: [spot] |
Exists |
节点存在该标签键(不检查值) | key: gpu |
DoesNotExist |
节点不存在该标签键 | key: legacy |
Gt |
标签值大于指定数值(字符串比较) | values: [4] |
Lt |
标签值小于指定数值(字符串比较) | values: [8] |
组合使用策略
在实际生产环境中,requiredDuringScheduling 和 preferredDuringScheduling 通常组合使用,形成硬约束 + 软优化的调度策略:
apiVersion: v1
kind: Pod
metadata:
name: production-service
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: security-level
operator: In
values:
- high
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 70
preference:
matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- us-west-2a
- us-west-2b
- weight: 30
preference:
matchExpressions:
- key: node-lifecycle
operator: NotIn
values:
- preemptible
containers:
- name: app
image: myapp:1.0
常见陷阱与注意事项
- 多个 nodeSelectorTerms 是 OR 关系:如果
nodeSelectorTerms数组中有多个条目,只要满足其中任意一个即可调度。 - 单个 term 内的 matchExpressions 是 AND 关系:同一个
nodeSelectorTerm下的所有表达式必须同时满足。 - 权重差异不宜过小:如果多个 preferred 规则的权重值接近,调度结果可能不够稳定,建议权重差异至少 20 以上。
- 避免过度约束:过多的 required 规则可能导致集群资源利用率下降,建议只在关键场景使用硬约束。
- 标签命名规范:使用
topology.kubernetes.io/*等标准前缀,避免自定义标签冲突。
kubectl describe pod 查看调度事件,或使用 descheduler 组件在集群资源变化时重新平衡 Pod。
两种类型的适用场景矩阵
| 场景 | 推荐类型 | 原因 |
|---|---|---|
| GPU/FPGA 等专用硬件 | required | 没有特定硬件 Pod 无法运行 |
| 数据合规(数据驻留) | required | 必须部署在特定地理区域 |
| 跨可用区高可用 | preferred | 优先分散,但不强制 |
| 成本优化(优先使用 spot) | preferred | 优先使用低成本节点,但允许 fallback |
| 安全隔离(敏感工作负载) | required | 必须运行在隔离节点上 |
| 负载均衡(均匀分布) | preferred | 通过权重引导分布,不阻塞调度 |