3. 调度策略核心概念:节点亲和性、Pod亲和性/反亲和性、污点与容忍度
在 Kubernetes 集群中,调度器(kube-scheduler)负责将 Pod 分配到合适的节点。默认的“轮询”或“资源余量”策略无法满足复杂生产环境的需求。本章深入解析三大核心调度原语:节点亲和性、Pod 亲和性/反亲和性以及污点与容忍度。理解这些概念是进行调度策略调优与配置漂移审计的基础。
3.1 节点亲和性(Node Affinity)
节点亲和性允许你根据节点上的标签(Label)来约束 Pod 可以调度到哪些节点。它替代了早期的 nodeSelector,提供了更丰富的匹配逻辑。
| 类型 | 语义 | 调度阶段 | 典型场景 |
|---|---|---|---|
requiredDuringSchedulingIgnoredDuringExecution |
硬约束:必须满足规则,否则 Pod 无法调度 | 调度时 | Pod 必须运行在具有 SSD 磁盘的节点上 |
preferredDuringSchedulingIgnoredDuringExecution |
软约束:尽量满足规则,不满足时仍可调度到其他节点 | 调度时 | Pod 优先调度到可用区 A,但可用区 B 也可接受 |
审计要点: 检查
requiredDuringScheduling 规则是否过于严格,导致节点故障时 Pod 无法重新调度。同时,注意 IgnoredDuringExecution 意味着节点标签在 Pod 运行后发生变化,不会影响已运行的 Pod,这是常见的配置漂移来源。
3.1.1 节点亲和性配置示例
apiVersion: v1
kind: Pod
metadata:
name: node-affinity-pod
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: disk-type
operator: In
values:
- ssd
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 50
preference:
matchExpressions:
- key: topology.kubernetes.io/zone
operator: In
values:
- us-east-1a
containers:
- name: nginx
image: nginx:1.25
3.2 Pod 亲和性(Pod Affinity)与反亲和性(Pod Anti-Affinity)
Pod 亲和性/反亲和性基于已经在节点上运行的 Pod 的标签来决策调度,而非节点本身的标签。这对于微服务架构中的“就近部署”或“故障隔离”至关重要。
- Pod 亲和性: 将 Pod 调度到与特定 Pod 相同的拓扑域(如节点、可用区)中。例如,将缓存服务和数据库服务调度到同一节点以减少网络延迟。
- Pod 反亲和性: 将 Pod 调度到与特定 Pod 不同的拓扑域中。例如,将同一应用的不同副本分散到不同节点或可用区,以提高可用性。
| 属性 | Pod 亲和性 | Pod 反亲和性 |
|---|---|---|
| 拓扑键(topologyKey) | 必须指定,用于定义“域”的范围 | 必须指定,用于定义“域”的范围 |
| 调度约束 | required / preferred | required / preferred |
| 性能影响 | 较低,通常用于优化 | 较高,尤其是 required 规则,可能大幅限制调度 |
| 典型误用 | 忘记设置 topologyKey 导致调度范围过小 |
设置过于严格的反亲和性导致 Pod 无法调度 |
性能警告: 使用
requiredDuringScheduling 的 Pod 反亲和性时,如果集群中节点数量少于 Pod 副本数,会导致部分 Pod 一直处于 Pending 状态。审计时应关注此类配置是否与集群规模匹配。
3.2.1 Pod 反亲和性配置示例
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web
topologyKey: kubernetes.io/hostname
containers:
- name: nginx
image: nginx:1.25
3.3 污点(Taints)与容忍度(Tolerations)
污点与容忍度是一对“排斥-吸引”机制。污点标记在节点上,用于排斥不匹配的 Pod;容忍度标记在 Pod 上,允许 Pod 调度到具有特定污点的节点。
- 污点效果(Effect):
NoSchedule:不调度新的 Pod 到该节点(除非有容忍度)。PreferNoSchedule:尽量不调度,但不强制。NoExecute:不仅不调度新 Pod,还会驱逐节点上已有的、没有对应容忍度的 Pod。
- 容忍度操作符(Operator):
Equal:容忍度必须与污点的 key、value、effect 完全匹配。Exists:只要污点的 key 和 effect 匹配即可,忽略 value。
审计与调优关联: 在 Prometheus 监控中,如果发现大量 Pod 处于 Pending 状态,应首先检查节点污点与 Pod 容忍度的匹配情况。配置漂移常表现为运维人员手动添加污点后,未同步更新相关 Pod 的容忍度。
3.3.1 污点与容忍度配置示例
# 给节点添加污点
# kubectl taint nodes node1 dedicated=gpu:NoSchedule
# Pod 容忍度配置
apiVersion: v1
kind: Pod
metadata:
name: gpu-pod
spec:
tolerations:
- key: "dedicated"
operator: "Equal"
value: "gpu"
effect: "NoSchedule"
containers:
- name: cuda-container
image: nvidia/cuda:12.0-base
3.4 核心概念关系图
下图展示了调度器在决策时如何综合评估节点亲和性、Pod 亲和性/反亲和性以及污点与容忍度。调度器首先过滤掉不满足硬约束的节点,然后对剩余节点进行打分,最终选择最优节点。
3.5 配置漂移审计对照表
在 Prometheus 驱动的审计体系中,以下配置项是漂移检测的重点。任何与基线不符的变更都应触发告警。
| 资源类型 | 审计字段 | 漂移风险 | Prometheus 检测指标 |
|---|---|---|---|
| Node | spec.taints |
手动添加/删除污点导致调度行为异常 | kube_node_spec_taint{key="..."} |
| Pod / Deployment | spec.affinity.nodeAffinity |
节点标签变更后,Pod 仍被调度到不合适的节点 | kube_pod_annotations{annotation="scheduler.alpha.kubernetes.io/node-selector"} |
| Pod / Deployment | spec.tolerations |
容忍度被移除或修改,导致 Pod 被驱逐 | kube_pod_status_reason{reason="TaintToleration"} |
| Pod / Deployment | spec.affinity.podAntiAffinity |
反亲和性规则被放宽,导致 Pod 集中部署 | kube_pod_affinity_term{type="podAntiAffinity"} |
最佳实践: 建议将调度策略配置(亲和性、容忍度)作为 GitOps 的一部分进行版本管理。任何手动
kubectl taint 或 kubectl label 操作都应视为配置漂移事件,并触发审计流程。