12.6 抢占、优先级与排队

一句话

抢占是 “用低优任务的命换高优任务的 SLO”:它必须配优先级、配额与可重跑三件套,否则只是把 “排队” 变成 “反复被杀再重试”,成本更高、体验更差。

抢占的四种动作

动作 做法 成本 适用
驱逐(Evict) 杀掉低优 Pod,腾出资源 任务从头再来 无状态、可重跑
暂停(Pause/Freeze) 冻结进程(cgroup freezer) 占用磁盘/内存快照 短时抢占、可恢复
迁移(Migrate) 活迁移到其他节点 网络与停机 有状态、支持迁移
降级(Throttle) 限 CPU/内存,不驱逐 低优变慢 可容忍变慢的服务

K8s 的默认抢占是 驱逐:高优 Pod 进入 Pending 时,调度器找可驱逐的低优 Pod,删除后重排。

实测:不抢占 vs 抢占

模拟 8 个槽位、200 个时间片、低优任务持续占满、高优任务随机到达:

策略 高优未获资源次数 低优被抢占次数
不抢占 192 0
抢占 0 192

数字很直白:不抢占时高优任务几乎全部在等(192/200);抢占把它压到 0,代价是 192 次低优任务被踢——抢占不是 “减少总工作量”,而是 “重新分配等待”。

高优等待 ↓ 的代价 = 低优重跑次数 ↑
只有当 “高优等待的成本 > 低优重跑的成本” 时,抢占才划算

代码:优先级与抢占策略(K8s)

apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata: {name: critical}
value: 1000000
preemptionPolicy: PreemptLowerPriority   # 允许抢占;Never 则只排队
globalDefault: false
---
apiVersion: v1
kind: Pod
spec:
  priorityClassName: critical
  terminationGracePeriodSeconds: 10       # 被驱逐时给多少时间收尾
kubectl get events --field-selector reason=Preempted   # 看谁被抢占、被谁抢占
kubectl describe pod <pending-pod> | grep -A3 "Preempt"

反模式

反模式 后果
没有 PriorityClass,全部同优先级 抢占无处发生,关键任务照样排队
给所有任务都设高优先级 等于没优先级,抢占变成互杀
低优任务不可重跑却被驱逐 数据丢失/任务失败,需要人工补偿
抢占不做 PDB 保护 一次性驱逐整个服务,可用性归零
不设 terminationGracePeriodSeconds 进程被 SIGKILL,未落盘数据丢失
抢占后不重排 高优拿到了资源,低优永远排在后面
没有 “抢占次数” 监控 低优被反复踢,吞吐下降却无人知

三条铁律

🔑 抢占是 “转移等待”,不是 “消除等待”;先算两侧成本。

🔑 被抢占方必须可重跑/可恢复,否则抢占就是制造故障。

🔑 优先级要分层且稀缺:只有少数级别,才有区分度。

自检

Q1 为什么 “给所有任务都设高优先级” 等于没有优先级?

▸ 答案:因为抢占的前提是 “存在可被抢占的低优任务”。当所有任务同级时,调度器没有 “可牺牲” 的对象,抢占退化成普通排队——优先级只有在 “有低优可让路” 时才起作用。

Q2 幂等重跑与抢占是什么关系?

▸ 答案:抢占会让任务中途消失,重新调度后从头执行。若任务不幂等(如重复扣款、重复发消息),重跑就会产生副作用。所以 “可抢占” 的前提是 “任务可安全重跑”——要么幂等,要么有检查点/断点续传。

Q3 PDB(PodDisruptionBudget)在抢占里起什么作用?

▸ 答案:它限制 “自愿中断时一次能驱逐多少”,保证服务不至于全灭。抢占属于自愿中断,调度器会尊重 PDB;没有 PDB 时,一次抢占可能把整个 Deployment 的副本全踢掉,瞬间不可用。

Q4 为什么 “暂停(freeze)” 比 “驱逐” 更贵?

▸ 答案:因为暂停要保留进程的内存与状态:内存不能释放、快照要落盘(或留在内存),恢复时还要考虑 “暂停期间外部状态已变”。它适合 “秒级抢占、很快恢复” 的场景;长时间暂停会拖垮节点。

Q5 抢占会不会导致 “低优任务永远排不上”?

▸ 答案:会,如果没有额外保护。常见缓解:配额保证(低优也有最小份额)、抢占频率限制(同一任务短时间内不被反复抢占)、老化(等待越久优先级越高)。没有这些,低优任务会被高优 “持续挤出去”。

Q6 如何量化 “抢占是否值得”?

▸ 答案:算两笔账:高优等待的损失(SLO 违约、业务损失/分钟)× 等待时间,对比低优重跑的损失(重算成本、被浪费的进度)× 被抢占次数。前者更大就抢占,反之用排队 + 扩容更划算。

Q7 在线服务与离线任务混部时,抢占该怎么设?

▸ 答案:离线任务设低优先级 + 可抢占,在线服务设高优先级 + 不抢占;同时给离线任务最小配额(避免被饿死)与弹性借用(在线空闲时离线用满)。这就是 “混部” 的标准做法(见 39.1 成本模型与单位经济)。

关联