概念定位
nodeAffinity 是 nodeSelector 的加强版:用 matchExpressions 写条件,支持 In、NotIn、Exists、DoesNotExist、Gt、Lt 等操作符,并且分成硬约束(required,不满足就不调度)与软偏好(preferred,按权重打分)。适用平台是 Kubernetes。字段名里的 IgnoredDuringExecution 说明它在 Pod 运行后不生效——节点标签变了也不会触发重新调度,这点在评估变更影响时必须记住。
基本信息
| 适用平台 | Kubernetes,Pod 级字段 spec.affinity.nodeAffinity |
|---|---|
| 硬约束 | requiredDuringSchedulingIgnoredDuringExecution |
| 软偏好 | preferredDuringSchedulingIgnoredDuringExecution,每项带 weight |
| 操作符 | In、NotIn、Exists、DoesNotExist、Gt、Lt |
典型使用场景
- 限定可用区:把服务固定到指定 zone,满足数据本地性或合规要求
- 绑定机型:只调度到带 GPU、SSD 或特定实例类型标签的节点
- 成本优化:用软偏好优先选低成本节点池,容量不足时再落到其他池
- 灰度迁移:新节点池打上新标签,用软偏好逐步引流,验证后改成硬约束
- 排除节点:用 NotIn 避开正在维护或有已知问题的节点
affinity 示例
affinity 示例
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values: [cn-hangzhou-b, cn-hangzhou-c]
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80
preference:
matchExpressions:
- key: disktype
operator: In
values: [ssd]核对与排查
核对与排查
kubectl get nodes -L topology.kubernetes.io/zone -L disktype # 节点标签现状
kubectl describe pod web-x | grep -i -A5 'Node-Selectors' # 解析后的约束
kubectl get events --field-selector reason=FailedScheduling --sort-by=.lastTimestamp | tail -3
kubectl get pod web-x -o jsonpath='{.spec.affinity.nodeAffinity}' # 与清单比对硬软约束对照
| 写法 | 不满足时 | 适用场景 |
|---|---|---|
| required | Pod 停在 Pending,事件里提示不匹配 | 合规与数据本地性等不能妥协的约束 |
| preferred(带 weight) | 仍会调度到其他节点 | 成本与性能偏好,需要留退路 |
| 多个 nodeSelectorTerms | 任一条满足即可通过 | 多套可接受方案 |
| 多个 matchExpressions | 同一 term 内需全部满足 | 组合条件,逐项校验 |
字段尾部的 IgnoredDuringExecution 表示 Pod 运行后节点标签变化不会触发重新调度,调整节点标签不会自动迁移存量 Pod。
nodeSelector 是 nodeAffinity 的简化写法,二者同时存在时都必须满足,维护时避免两处写重复约束。
落地时的核对清单
- 先在节点侧确认标签真的存在:kubectl get nodes -L <键> 一看便知,避免照着模板写约束
- 硬约束优先用 In 收敛取值范围,NotIn 组合过多时容易在扩容时突然全不匹配
- 软偏好给不同节点池分配不同权重,权重相同时调度结果会变得不确定
- 约束改动牵涉现有副本时,用滚动更新或重建让新模板生效,不要指望已运行 Pod 自己迁移