3. 调度亲和性概念:节点亲和性、Pod亲和性、Pod反亲和性
在 Kubernetes 调度系统中,亲和性(Affinity)与反亲和性(Anti-Affinity)是比简单 nodeSelector 更灵活、表达能力更强的调度约束机制。它们允许调度器根据节点或 Pod 的标签(Label)做出精细化决策,是解决资源竞争、高可用部署、故障域隔离等场景的核心工具。
亲和性分为三大类:节点亲和性(nodeAffinity)、Pod 亲和性(podAffinity)和Pod 反亲和性(podAntiAffinity)。理解它们的区别与适用场景,是排查因资源竞争导致 CrashLoop 的前提。
3.1 三类亲和性对比总览
| 类型 | 作用对象 | 匹配依据 | 典型用途 | 调度阶段 |
|---|---|---|---|---|
| nodeAffinity | Pod → 节点 | 节点标签(node labels) | 将 Pod 调度到特定硬件(如 GPU)、可用区、机型 | 预选 + 优选 |
| podAffinity | Pod → Pod | 目标 Pod 的标签 + 拓扑域 | 将相关 Pod 调度到同一拓扑域(如同一节点、同一可用区) | 预选 |
| podAntiAffinity | Pod → Pod | 目标 Pod 的标签 + 拓扑域 | 将 Pod 分散到不同拓扑域,避免单点故障或资源争抢 | 预选 |
关键区别:nodeAffinity 关注“Pod 应该去哪些节点”;podAffinity 关注“Pod 应该和哪些 Pod 在一起”;podAntiAffinity 关注“Pod 应该远离哪些 Pod”。在资源竞争场景中,podAntiAffinity 是防止多个高负载 Pod 挤在同一节点上的主要手段。
3.2 节点亲和性(nodeAffinity)
节点亲和性允许你使用 In、NotIn、Exists、DoesNotExist、Gt、Lt 等操作符来定义调度规则。它分为两种模式:
- requiredDuringSchedulingIgnoredDuringExecution:硬约束,调度时必须满足,否则 Pod 无法被调度(Pending)。
- preferredDuringSchedulingIgnoredDuringExecution:软约束,调度器尽量满足,但不强制;权重越高,优先级越大。
apiVersion: v1
kind: Pod
metadata:
name: gpu-pod
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: accelerator
operator: In
values:
- nvidia-tesla-v100
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80
preference:
matchExpressions:
- key: zone
operator: In
values:
- us-east-1a
containers:
- name: gpu-container
image: nvidia/cuda:12.0-base
CrashLoop 关联:当节点资源(CPU、内存、磁盘 IO)被大量占用时,即使 nodeAffinity 硬约束满足,Pod 仍可能因资源竞争导致 OOMKilled 或健康检查失败。此时需要结合 podAntiAffinity 将同类 Pod 分散到不同节点。
3.3 Pod 亲和性(podAffinity)
Pod 亲和性用于将一组 Pod 调度到相同的拓扑域中。拓扑域由 topologyKey 指定,常见取值包括 kubernetes.io/hostname(同一节点)、topology.kubernetes.io/zone(同一可用区)。
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- cache
topologyKey: kubernetes.io/hostname
上述配置要求:当前 Pod 必须被调度到至少运行了一个 app=cache Pod 的节点上。如果没有任何节点满足,Pod 将处于 Pending 状态。
注意:podAffinity 会增加节点上的 Pod 密度。如果目标 Pod 本身是高资源消耗型,盲目使用 podAffinity 可能加剧资源竞争,导致新 Pod 启动后立即 CrashLoop。
3.4 Pod 反亲和性(podAntiAffinity)
Pod 反亲和性是解决资源竞争和高可用的核心工具。它确保同一组 Pod 不会集中部署在同一个拓扑域中。
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web-server
topologyKey: kubernetes.io/hostname
上述配置表示:尽量将 app=web-server 的 Pod 分散到不同节点上(软约束)。如果改为 requiredDuringSchedulingIgnoredDuringExecution,则强制每个节点最多只能运行一个该类型的 Pod。
CrashLoop 排查要点:当集群节点资源紧张时,如果多个高负载 Pod 因缺少反亲和性而挤在同一节点,会导致 CPU 节流、内存 OOM、磁盘 IO 争抢,进而触发健康检查失败和 CrashLoop。此时添加 podAntiAffinity 并配合
topologyKey: kubernetes.io/hostname 是最直接的修复手段。
3.5 亲和性调度决策流程(SVG)
下图展示了调度器在处理亲和性规则时的完整决策路径:
3.6 亲和性配置对比速查表
| 配置项 | nodeAffinity | podAffinity | podAntiAffinity |
|---|---|---|---|
| 匹配对象 | 节点标签 | Pod 标签 + topologyKey | Pod 标签 + topologyKey |
| 硬约束关键字 | requiredDuringScheduling... |
requiredDuringScheduling... |
requiredDuringScheduling... |
| 软约束关键字 | preferredDuringScheduling... |
preferredDuringScheduling... |
preferredDuringScheduling... |
| 常用 topologyKey | 不适用 | kubernetes.io/hostnametopology.kubernetes.io/zone |
kubernetes.io/hostnametopology.kubernetes.io/zone |
| 对资源竞争的影响 | 间接(选择资源充足的节点) | 可能加剧(将 Pod 聚拢) | 缓解(将 Pod 分散) |
| 典型 CrashLoop 场景 | 节点标签变更导致调度失败 | 目标 Pod 所在节点资源耗尽 | 缺少反亲和性导致节点过载 |
3.7 实战建议:资源竞争场景下的亲和性策略
- 优先使用 podAntiAffinity:对于无状态高负载服务(如 Web 服务器、数据处理 Pod),始终添加
preferredDuringScheduling级别的反亲和性,避免多个副本挤在同一节点。 - 谨慎使用 podAffinity:仅当 Pod 间有强通信依赖(如 sidecar 与主容器、缓存与计算)且通信延迟敏感时使用,同时确保目标节点有足够资源余量。
- nodeAffinity 配合资源预留:使用 nodeAffinity 将特定 Pod 调度到专用节点池,并结合
resources.requests和limits防止资源争抢。 - 监控拓扑域分布:使用
kubectl get pods -o wide检查 Pod 的节点分布,若发现多个高负载 Pod 集中在同一节点,立即评估是否缺少反亲和性配置。