把 Pod 引导到目标节点
调度引导有三层工具:nodeSelector 是最简单的硬条件,只做标签等值匹配;nodeAffinity 支持硬条件(required)与软条件(preferred),并可用 In、NotIn、Exists 等运算符表达复杂匹配;Pod 之间的亲和与反亲和用来让同类副本分散到不同节点或机架。再往上一层是 topologySpreadConstraints,按拓扑域做均匀分布,是更直观的新一代方案。
基本信息
| nodeSelector | key: value 形式的硬条件,最易用也最不灵活 |
|---|---|
| nodeAffinity.required | 硬条件,支持 In/NotIn/Exists 等运算符与多组 matchExpressions |
| nodeAffinity.preferred | 软条件:满足更好,不满足也能调度,可用 weight 排优先级 |
| podAntiAffinity | preferred 常用于让同类副本跨节点分散,规避单点故障 |
| topologySpreadConstraints | 按 zone 或 node 等拓扑域均匀分布,可设 maxSkew 控制偏差 |
| 重要语义 | 带 IgnoredDuringExecution 的条件只在调度时判断,运行中节点标签变化不会驱逐已有 Pod |
典型使用场景
- 把 GPU、本地 SSD 或大内存类工作负载引导到对应规格的节点池
- 让同一 Deployment 的副本分散到不同节点,避免单节点故障造成整业务中断
- 把日志采集与监控 Agent 这类 DaemonSet 限定到特定节点组
- 跨可用区均匀分布,降低单个 AZ 故障的影响面
- 把测试与灰度负载限制在专用节点,避免影响生产服务的资源水位
组合示例
组合示例
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution: # 硬条件:必须有 ssd 标签
nodeSelectorTerms:
- matchExpressions:
- key: disktype
operator: In
values: [ssd]
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution: # 软反亲和:尽量分散
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels: { app: web }
topologyKey: kubernetes.io/hostname # 以节点为分散维度
几种方式对比
| 方式 | 条件性质 | 典型用途 | 失效表现 |
|---|---|---|---|
| nodeSelector | 硬条件 | 简单标签匹配 | 无匹配节点时 Pod 一直 Pending |
| nodeAffinity.required | 硬条件,支持运算符 | 复杂组合匹配 | 同样 Pending,事件里提示节点不满足 |
| nodeAffinity.preferred | 软条件 | 尽量满足但可退让 | 效果被稀释,但不阻塞调度 |
| podAntiAffinity | 软或硬 | 副本跨节点分散 | 硬反亲和且节点不足时多余副本 Pending |
| topologySpreadConstraints | 按域均衡 | 多可用区或跨节点均匀分布 | maxSkew 设置过严会限制可调度性 |
硬条件写太死会把 Pod 卡成 Pending:关键业务用 preferred 保底可调度,再叠加 PodDisruptionBudget 保障可用性。调度失败时 kubectl describe pod 的事件与调度器日志是主要线索,配置本身看不出问题。
硬反亲和在节点数少于副本数时会让多余副本永久 Pending,扩缩容与节点故障恢复都会被卡住。生产更常用软反亲和保证分散倾向,再用 PDB 兜住同时不可用的副本数量。