3. 调度亲和性原理:节点亲和性、Pod间亲和性与反亲和性
在 Kubernetes 集群中,调度器(kube-scheduler)负责将 Pod 分配到合适的节点。亲和性与反亲和性规则提供了比简单 nodeSelector 更灵活、更强大的调度控制能力。本章深入解析三种核心调度约束的 YAML 配置语义与运行机制,为后续治理集群故障排查与配置漂移审计奠定基础。
3.1 节点亲和性(nodeAffinity)
节点亲和性允许 Pod 根据节点上的标签(Label)选择目标节点,分为硬性要求(requiredDuringSchedulingIgnoredDuringExecution)和软性偏好(preferredDuringSchedulingIgnoredDuringExecution)两种策略。
| 策略类型 | 语义 | 调度行为 | 执行阶段 |
|---|---|---|---|
| required | 必须满足 | 找不到匹配节点则 Pod 处于 Pending | 调度时 |
| preferred | 尽量满足 | 不满足时仍可调度到其他节点,权重影响优先级 | 调度时 |
关键字段解析:
matchExpressions:支持In、NotIn、Exists、DoesNotExist、Gt、Lt操作符。weight(仅 preferred):1–100 整数,权重越高优先级越大。topologyKey:用于 podAffinity/podAntiAffinity,定义拓扑域。
apiVersion: v1
kind: Pod
metadata:
name: node-affinity-demo
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disk-type
operator: In
values:
- ssd
- nvme
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80
preference:
matchExpressions:
- key: zone
operator: In
values:
- az-a
运维提示:required 规则写错会导致 Pod 永久 Pending,排查时优先检查节点标签是否存在、值是否匹配。preferred 规则即使写错也不会阻塞调度,但可能造成负载不均。
3.2 Pod间亲和性(podAffinity)
Pod 间亲和性将一组 Pod 调度到相同的拓扑域(如同一个节点、同一个可用区),常用于降低网络延迟或满足数据本地性需求。
apiVersion: apps/v1
kind: Deployment
metadata:
name: cache-affinity
spec:
replicas: 3
selector:
matchLabels:
app: cache
template:
metadata:
labels:
app: cache
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- frontend
topologyKey: kubernetes.io/hostname
containers:
- name: cache
image: redis:7
| 参数 | 说明 | 常见值 |
|---|---|---|
labelSelector |
选择目标 Pod 的标签 | matchLabels / matchExpressions |
topologyKey |
定义“相同位置”的粒度 | kubernetes.io/hostname、topology.kubernetes.io/zone |
namespaces |
限定标签选择的范围(默认当前 ns) | default、kube-system |
配置漂移风险:podAffinity 的
topologyKey 一旦写错(如误用 kubernetes.io/hostname 代替 topology.kubernetes.io/zone),会导致 Pod 全部挤在同一节点,造成单点故障。审计时应重点核对 topologyKey 与业务容灾要求是否一致。
3.3 Pod间反亲和性(podAntiAffinity)
反亲和性强制或偏好 Pod 分散到不同拓扑域,是高可用部署的核心手段。典型场景:将同一 Deployment 的多个副本分布在不同节点或可用区。
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-ha
spec:
replicas: 5
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web
topologyKey: kubernetes.io/hostname
containers:
- name: nginx
image: nginx:1.25
required vs preferred 选择指南:
- required:副本数 ≤ 可用节点数时使用,保证分散;节点数不足时 Pod 会 Pending。
- preferred:副本数可能超过节点数时使用,尽量分散但不阻塞调度。
3.4 三种亲和性对比与审计要点
| 特性 | nodeAffinity | podAffinity | podAntiAffinity |
|---|---|---|---|
| 作用对象 | 节点标签 | Pod 标签 | Pod 标签 |
| 调度目标 | 绑定到特定节点 | 与目标 Pod 同拓扑域 | 与目标 Pod 不同拓扑域 |
| 典型用途 | GPU 节点、SSD 节点 | 缓存与前端同节点 | 多副本跨节点/跨可用区 |
| 配置漂移常见点 | 标签 key 拼写错误、values 遗漏 | topologyKey 粒度错误 | required 导致调度死锁 |
3.5 调度亲和性决策流程(SVG)
3.6 配置漂移审计清单
- 标签一致性检查:nodeAffinity 引用的节点标签是否真实存在?Pod 标签是否与 podAffinity 的 labelSelector 匹配?
- topologyKey 合理性:是否使用了正确的拓扑域?生产环境建议使用
topology.kubernetes.io/zone而非kubernetes.io/hostname实现可用区级容灾。 - required 规则数量:过多 required 规则会大幅缩小可调度节点池,建议每个 Pod 不超过 2 条 required 规则。
- preferred 权重分布:权重值是否集中在少数规则上?避免权重差异过大导致调度倾斜。
- 反亲和性副本数:required podAntiAffinity 的副本数是否超过目标拓扑域数量?超过会导致部分副本 Pending。
Helm 治理实践:在 Helm Chart 的 values.yaml 中暴露亲和性配置项,通过模板条件渲染 required/preferred,避免硬编码。审计时对比 values 与渲染后的 YAML,快速定位配置漂移。