我们前面说了 nodeSelector 是 Pod 选择节点的最简单方式,但它太死板(只能精确匹配 key=value),所以 Kubernetes 提供了更灵活的 Affinity(亲和性) 机制。
🔹 Affinity(亲和性)的含义
Affinity 就是 Pod 对节点或其它 Pod 的“亲近偏好”,用来控制 Pod 调度时的“去哪”的策略。
它分为两大类:
-
Node Affinity(节点亲和性)
-
Pod 选择节点的条件,比 nodeSelector 更强大
-
可以用表达式(In、NotIn、Exists、Gt、Lt 等)
-
有 软约束(preferred) 和 硬约束(required)
-
-
Pod Affinity / Anti-Affinity(Pod 间亲和 / 反亲和)
-
控制 Pod 和 Pod 之间的相对位置
-
Pod 亲和(Affinity):我想和某类 Pod 放在一起
-
Pod 反亲和(AntiAffinity):我想和某类 Pod 分开
-
🔹 Node Affinity 示例
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution: # 硬约束(必须满足)
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/e2e-az-name
operator: In
values:
- e2e-az1
- e2e-az2
preferredDuringSchedulingIgnoredDuringExecution: # 软约束(尽量满足)
- weight: 1
preference:
matchExpressions:
- key: another-node-label-key
operator: In
values:
- another-node-label-value
👉 解释:
-
required:Pod 必须调度到带有
e2e-az1或e2e-az2标签的节点,否则无法调度。 -
preferred:最好调度到
another-node-label-key=another-node-label-value的节点,但不强制。
🔹 Pod Affinity 示例
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- frontend
topologyKey: "kubernetes.io/hostname"
👉 解释:
- 这个 Pod 要和
app=frontend的 Pod 调度在 同一台节点(因为 topologyKey=hostname)。
🔹 Pod Anti-Affinity 示例
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- frontend
topologyKey: "kubernetes.io/hostname"
👉 解释:
- 这个 Pod 不能和
app=frontend的 Pod 调度在同一台节点上,常用于高可用部署(副本要分散开)。
🔹 总结
-
NodeSelector:最简单的节点选择器,只支持
key=value。 -
NodeAffinity:节点亲和性,支持更复杂的表达式,还能设置硬约束/软约束。
-
PodAffinity / PodAntiAffinity:Pod 与 Pod 的“亲近”或“远离”关系。
那我给你整理一张表,把 NodeSelector / NodeAffinity / PodAffinity / PodAntiAffinity / Taints & Tolerations 的区别和应用场景都放在一起,你一眼就能看出它们的定位。
🔹 Kubernetes 调度控制机制对比
| 特性 | NodeSelector | NodeAffinity | PodAffinity | PodAntiAffinity | Taints & Tolerations |
|---|---|---|---|---|---|
| 控制对象 | 节点 | 节点 | Pod ↔ Pod(想靠近) | Pod ↔ Pod(想远离) | 节点 ↔ Pod |
| 配置位置 | Pod | Pod | Pod | Pod | 节点 + Pod |
| 约束类型 | 硬约束 | 硬约束 / 软约束 | 硬约束 / 软约束 | 硬约束 / 软约束 | 排斥(NoSchedule、PreferNoSchedule、NoExecute) |
| 表达能力 | 仅支持 key=value | 支持表达式(In、NotIn、Exists、Gt、Lt 等) | 基于 labelSelector + 拓扑域(hostname/zone 等) | 基于 labelSelector + 拓扑域 | 通过 effect 控制调度 / 驱逐 |
| 常见用途 | 绑定 Pod 到某类节点(简单场景) | 更灵活地绑定 Pod 到节点(可用区、硬件类型) | 让相关 Pod 调度在一起(前后端放同机房/同节点) | 让副本 Pod 分散调度(高可用) | 节点限制 Pod 进入(隔离/专用节点/驱逐) |
| 默认行为 | 没匹配不上就调度失败 | required 不满足则失败,preferred 不满足则尽量避免 | 同上 | 同上 | 有污点时 Pod 默认不能调度过去,除非有容忍 |
| 方向性 | Pod 主动选择节点 | Pod 主动选择节点 | Pod 主动选择其他 Pod | Pod 主动远离其他 Pod | 节点主动拒绝 Pod |
🔹 使用场景对比
-
NodeSelector:简单粗暴,适合 开发测试环境。
-
NodeAffinity:生产常用,指定节点的标签条件(比如 GPU 节点、可用区分布)。
-
PodAffinity:适合需要 低延迟通信 的服务(如 Web + Cache 要部署在一起)。
-
PodAntiAffinity:适合 高可用分布(如多副本的数据库要分散到不同节点)。
-
Taints & Tolerations:适合 节点隔离、专用节点、故障驱逐。