Node Affinity (节点亲和性) 和 Pod Affinity (Pod 亲和性) 的区别
在 Kubernetes 中,Node Affinity(节点亲和性) 和 Pod Affinity(Pod 亲和性) 都是用来控制 Pod 调度(即决定 Pod 运行在哪个节点上)的机制。
它们的核心区别在于 “参照物” 不同:
- Node Affinity:参照物是 Node(节点)。即“我(Pod)想去具有某些特征的节点”。
- Pod Affinity:参照物是 Running Pods(正在运行的 Pod)。即“我(Pod)想去那个已经运行了某某 Pod 的节点(或区域)”。
以下是详细的对比分析:
1. 核心概念对比
| 特性 | Node Affinity (节点亲和性) | Pod Affinity (Pod 亲和性) |
|---|---|---|
| 关注关系 | Pod 与 Node 的关系 | Pod 与 Pod 的关系 |
| 匹配依据 | Node 的 Label (标签) | 其他 Pod 的 Label (标签) |
| 典型逻辑 | “这个 Pod 需要运行在带有 gpu=true 标签的节点上。” |
“这个 Web Pod 需要运行在已经有 Redis Pod 的节点上。” |
| 拓扑域 (Topology) | 通常隐式指单个节点 | 必须显式指定 topologyKey (可以是同一节点、同一机架、同一可用区) |
| 性能开销 | 较低 (只检查节点标签) | 较高 (需要遍历节点上已有的 Pod,在大规模集群中会显著减慢调度速度) |
2. 详细解析
A. Node Affinity (节点亲和性)
它是 nodeSelector 的升级版,功能更强大。它允许你根据节点的属性(如 CPU 架构、操作系统、区域、自定义标签等)来限制 Pod 能调度到哪些节点。
- 应用场景:
- 将 AI 训练任务调度到带有 GPU 的节点。
- 将 IO 密集型应用调度到带有 SSD 的节点。
- 将 Pod 限制在特定的可用区(Zone)或机房。
- 语法示例:yaml
affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: # 硬策略 nodeSelectorTerms: - matchExpressions: - key: disktype operator: In values: - ssd
B. Pod Affinity (Pod 亲和性) & Anti-Affinity (反亲和性)
它允许你根据节点上已经运行的 Pod 的标签来约束新 Pod 的调度。通常包含“亲和性”(想在一起)和“反亲和性”(不想在一起)。
- 应用场景:
- 亲和性 (Affinity):为了低延迟,将 Web Server 和 Cache (Redis) 调度到同一个节点。
- 反亲和性 (Anti-Affinity):为了高可用 (HA),确保同一个应用的 3 个副本(Replica)分散在不同的节点上(避免单点故障)。
- 拓扑键 (topologyKey):
这是 Pod 亲和性中非常重要的概念。它定义了“在一起”的范围。kubernetes.io/hostname: 表示必须在同一个节点。topology.kubernetes.io/zone: 表示必须在同一个可用区(即使不在同一个节点)。
- 语法示例:yaml
affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: - backend-db topologyKey: kubernetes.io/hostname # 必须和 backend-db 在同一台机器
3. 硬策略 vs 软策略 (两者都支持)
无论是 Node Affinity 还是 Pod Affinity,都支持两种强度的规则:
- 硬策略 (Hard):
requiredDuringSchedulingIgnoredDuringExecution- 必须满足。如果找不到满足条件的节点,Pod 会一直处于 Pending 状态,无法启动。
- 软策略 (Soft):
preferredDuringSchedulingIgnoredDuringExecution- 尽量满足。如果找不到满足条件的节点,调度器也会退而求其次,把 Pod 调度到不满足条件的节点上。
4. 总结与最佳实践
- 如果你关心的是 硬件资源或物理位置(如:我要 SSD,我要 GPU,我要去美国东部机房),请使用 Node Affinity。
- 如果你关心的是 服务间的通信或高可用(如:我要离数据库近一点,或者我不能和我的克隆体在同一台机器上),请使用 Pod Affinity / Anti-Affinity。
⚠️ 注意事项:
尽量减少在大规模集群中使用复杂的 Pod Affinity 规则,因为调度器需要计算每个节点上所有 Pod 的逻辑关系,这会消耗大量的调度器计算资源,可能导致 Pod 启动变慢。而 Node Affinity 速度非常快。
右滑查看面试常问