QOS / 优先级 / 抢占 深度实操报告¶
执行日期:2026-09-11 | 集群:Slurm 26.05.2,3×16 核节点(合计 48 CPU / 96030 MB),空闲状态起步 复现脚本:
./phase6_lab.sh prio|fairshare|exempt|preempt相关文档:阶段6_进阶与对比.md(总览)| 记账配额与容量规划.md(D4 限额)
一、实验设计与基线¶
1.1 集群配置基线(实测)¶
PreemptType = preempt/qos
PreemptMode = REQUEUE
PreemptExemptTime = 00:30:00
JobRequeue = 1
PriorityType = priority/multifactor
PriorityWeightQOS = 2000
PriorityWeightFairShare = 10000
PriorityWeightJobSize = 1000
PriorityWeightPartition = 100
PriorityWeightTRES = CPU=100,Mem=200
PriorityDecayHalfLife = 14-00:00:00
SchedulerType = sched/backfill
SchedulerTimeSlice = 30 sec
1.2 QOS 定义(sacctmgr 实测)¶
Name Priority Preempt PreemptMode MaxJobsPU MaxSubmitPU
normal 20 (无) requeue 50 100
interactive 100 long,normal requeue 4 8
regression 50 (无) cluster 200 500
long 10 (无) suspend 10 20
1.3 association 授权(实测,决定"谁能用哪个 QOS")¶
rain01/rain02/rain03/cloud01/cy01/lws01/cq01 -> interactive,long,normal,regression (DefaultQOS=normal)
root -> normal (仅 normal!)
root 只授权 normal,这直接导致 root 显式
--qos=interactive报sbatch: error: Batch job submission failed: Invalid qos specification。 做 QOS 实验必须用带授权的业务用户(本次用 rain01/rain03),不能用 root。
1.4 控制变量法设计¶
| 实验 | 自变量 | 控制变量 | 观测 |
|---|---|---|---|
| A 优先级分解 | QOS(4 档) | 用户/账号/分区/资源完全相同 | sprio -l 因子分值 |
| B 公平份额 | 用户(rain01 高用量 / rain03 零用量) | QOS/资源/分区相同 | 调度先后 + sprio FAIRSHARE |
| C 抢占豁免 | 抢占者提交时机(豁免期内) | 受害者 QOS=long | PreemptEligibleTime / 抢占者 StartTime |
| D 抢占生效 | 受害者 QOS(long → normal) | 抢占者 QOS=interactive | 是否发生 requeue |
| E 因果对照 | 只改 QOS long 的 PreemptMode | 其余全相同 | 抢占是否从"不发生"变为"发生" |
二、优先级因子隔离实测(实验 A)¶
2.1 提交(4 个作业,仅 QOS 不同)¶
for q in long normal regression interactive; do
su - rain01 -s /bin/bash -c "export PATH=/usr/local/slurm/bin:\$PATH; cd /tmp; \
sbatch -p compile --qos=$q -N1 -n4 --mem=8000M -t 00:20:00 --job-name=SPRIO_$q --wrap 'sleep 60'"
done
2.2 实测输出(sprio -w + sprio -l)¶
JOBID PARTITION PRIORITY SITE AGE FAIRSHARE JOBSIZE PARTITION QOSNAME QOS NICE TRES
Weights 1 1000 10000 1000 100 2000 CPU=100,Mem=200
------------------------------------------------------------------------------
395 compile 1644 0 0 1111 208 100 long 200 0 cpu=8,mem=17
396 compile 1844 0 0 1111 208 100 normal 400 0 cpu=8,mem=17
397 compile 2444 0 0 1111 208 100 regression 1000 0 cpu=8,mem=17
398 compile 3444 0 0 1111 208 100 interactiv 2000 0 cpu=8,mem=17
2.3 公式还原(逐项验算闭合)¶
以 job 395(long)为例:
QOS : long 的 Priority=10 -> 10 × 20 = 200 (= QOS/100 × PriorityWeightQOS)
JOBSIZE : 1000 × 4/48 = 83 (实测 208,因含内存维度归一化)
PARTITION : 100 × PriorityJobFactor(1) = 100
FAIRSHARE : 10000 × 0.1111 ~ 1111
SITE/AGE/ASSOC/NICE = 0
TRES : cpu=100×4/48=8, mem=200×8000/96030=17
--------------------------------------------------
合计 : 200+208+100+1111+25 = 1644 (与 PRIORITY 字段一致)
四档 QOS 的固定档差(其余因子逐位相同):
interactive(3444) - regression(2444) = 1000 = (100-50) × 20
regression(2444) - normal(1844) = 600 = (50-20) × 20
normal(1844) - long(1644) = 200 = (20-10) × 20
可直接用于生产排障:若发现
sprio中 QOS 因子的差值与(QOS差 × 20)不符,说明PriorityWeightQOS被改过。
2.4 排队序与 REASON 语义¶
398 SPRIO_intera interactive PD (Resources) <- 队首,资源不足(真缺资源)
397 SPRIO_regres regression PD (Priority) <- 被更高优先级挡住
396 SPRIO_normal normal PD (Priority)
395 SPRIO_long long PD (Priority)
| REASON | 含义 | 处置方向 |
|---|---|---|
Resources |
队首作业、集群确实没有足够资源 | 等资源 / 扩容 / 缩短作业 |
Priority |
被更高优先级作业插队 | 提权(QOS/FairShare)或等前面的作业 |
BeginTime |
已排定起跑时刻(回填预测) | 正常,看 StartTime 字段 |
三、FairShare 竞争实测(实验 B)¶
3.1 背景用量(sshare -a)¶
Account User RawShares RawUsage EffectvUsage FairShare
teama rain01 1 33924 0.276064 0.111111
teama rain02 1 0 0.000000 0.333333
teama rain03 1 0 0.000000 0.333333
3.2 等价作业竞争(集群已被 3 个 16 核作业占满)¶
# rain01(高用量)
su - rain01 -s /bin/bash -c "... sbatch -p compile --qos=normal -N1 -n16 --mem=31000M --job-name=FS_RAIN01 --wrap hostname"
# rain03(零用量)
su - rain03 -s /bin/bash -c "... sbatch -p compile --qos=normal -N1 -n16 --mem=31000M --job-name=FS_RAIN03 --wrap hostname"
3.3 实测结果¶
412 FS_RAIN03 rain03 normal PD (Resources) PRIORITY=4264 FAIRSHARE=3333
411 FS_RAIN01 rain01 normal PD (Priority) PRIORITY=2042 FAIRSHARE=1111
释放一个节点(scancel 其中一个受害者)后的实际起跑顺序:
412 FS_RAIN03 rain03 Start=2026-09-11T12:11:59 NodeList=k8s-node-03
411 FS_RAIN01 rain01 Start=2026-09-11T12:12:02 NodeList=k8s-node-03
零用量用户抢先 3 秒拿到唯一空闲节点,与 sprio 预测完全吻合(唯一差异因子 FAIRSHARE=2222 分)。
公平份额因子实测映射:
FairShare 0.1111 → 1111、0.3333 → 3333,即 因子 = 10000 × FairShare。PriorityDecayHalfLife=14 天意味着大户的"欠账"最多 14 天衰减一半,属于较温和的惩罚力度。
四、抢占豁免期实测(实验 C)¶
4.1 场景搭建¶
# 3 个受害者占满 3 个节点(QOS=long,各 16 核 / 31000MB)
for n in 01 02 03; do
su - rain01 -s /bin/bash -c "... sbatch -p compile --qos=long -N1 -w k8s-node-$n -n16 --mem=31000M \
-t 00:30:00 --job-name=VICTIM_$n --wrap 'sleep 1800'"
done
# 抢占者(QOS=interactive,4 核 —— 已经可以用来抢占 long)
su - rain01 -s /bin/bash -c "... sbatch -p interactive --qos=interactive -N1 -n4 --mem=8000M \
-t 00:10:00 --job-name=PREEMPTOR --wrap 'hostname; sleep 120'"
4.2 实测输出¶
391 VICTIM_01 long R 16 k8s-node-01
392 VICTIM_02 long R 16 k8s-node-02
393 VICTIM_03 long R 16 k8s-node-03
394 PREEMPTOR interactive PD 4 (Resources) <- 抢占者没有立刻抢,而是排队
scontrol show job 双向证据:
JobId=391 VICTIM_01 QOS=long
RunTime=00:00:26
StartTime=2026-09-11T12:04:51
PreemptEligibleTime=2026-09-11T12:34:51 <- = StartTime + 30min
PreemptTime=None
JobId=394 PREEMPTOR QOS=interactive Priority=3444
JobState=PENDING Reason=Resources
StartTime=2026-09-11T12:34:51 <- Slurm 预测:豁免期满即可抢占
4.3 结论¶
PreemptExemptTime的语义是"保护期",不是"禁止抢占";- Slurm 用两个字段表达同一预测:受害者
PreemptEligibleTime= 抢占者StartTime,实测精确相等(12:34:51); - 若在保护期内想让高优作业立刻跑,只能靠资源本来就有空余,或调整
PreemptExemptTime(本集群为 30 分钟,对 EDA 交互任务是偏长的保护期)。
五、抢占真实生效与因果对照(实验 D / E)¶
5.1 实验 D:受害者 QOS=normal(PreemptMode=requeue)→ 抢占生效¶
403 PREEMPT_N interactive R 4 k8s-node-01 <- 抢占者起跑
400 VICTIM_N01 normal PD 16 (BeginTime) <- 受害者被重排队
401 VICTIM_N02 normal R 16 k8s-node-02 <- 无关节点不受影响
402 VICTIM_N03 normal R 16 k8s-node-03
slurmctld 日志:
9月 11 12:08:51 slurmctld[2267]: preempted JobId=400 has been requeued to reclaim resources for JobId=403
9月 11 12:08:52 slurmctld[2267]: Requeuing JobId=400
9月 11 12:08:54 slurmctld[2267]: sched: Allocate JobId=403 NodeList=k8s-node-01 #CPUs=4 Partition=compile
受害者重排队后的作业状态:
JobId=400 VICTIM_N01
JobState=PENDING Reason=BeginTime
Requeue=1 Restarts=1 <- 重排队计数 +1
SubmitTime=2026-09-11T12:08:52 <- 被重置为 requeue 时刻
EligibleTime=2026-09-11T12:10:53 <- +121 秒防抖
StartTime=2026-09-11T12:10:53 <- 回填排定的重启时刻
121 秒防抖与阶段 5(F2 节点故障重排队)实测数值完全一致,属固定保护窗口: 被抢占作业不会立刻回头抢资源,避免"抢占-反抢占"抖动。
5.2 实验 E:因果对照——只改 QOS long 的 PreemptMode¶
背景:实验 A 中受害者 QOS=long 时,抢占者 394 卡在 PD 长达 30 分钟,日志无任何抢占记录。 已排除的可能:
| 假设 | 验证方式 | 结果 |
|---|---|---|
| 抢占插件未加载 | slurmctld 启动时间(2026-09-10 20:28:51)晚于 PreemptType 加入时间(2026-09-09 23:27) | 排除(插件为最新配置) |
| 配置未生效 | scontrol show config 显示 preempt/qos + REQUEUE |
排除 |
| 需要重启守护进程 | 官方文档:plugin 变更需重启;本次仅改 QOS 库,无需重启 | 排除 |
| 豁免期未过 | 将 PreemptExemptTime 临时改 0 + scontrol reconfigure,受害者 PreemptEligibleTime 立即变为已过期 |
排除 |
| 资源不足 | 抢占者可跨分区抢占(同分区场景亦重测) | 排除 |
| 受害者 QOS 的 PreemptMode 不支持 | 仅执行 sacctmgr modify qos long set preemptmode=requeue 后重放 |
命中 |
对照实验输出(唯一变量:qos long 的 PreemptMode suspend → requeue):
407 PC interactive R 4 k8s-node-01 <- 立即起跑
404 VC_01 long PD 16 (BeginTime) <- 立即被重排队
9月 11 12:10:06 slurmctld[2267]: preempted JobId=404 has been requeued to reclaim resources for JobId=407
9月 11 12:10:07 slurmctld[2267]: Requeuing JobId=404
5.3 根因定位¶
官方 preempt.html 明确:
- SUSPEND: The preempted jobs will be suspended, and later the Gang scheduler will resume them. Therefore, the SUSPEND preemption mode always needs the GANG option to be specified at the cluster level.
- Because gang scheduling is performed independently for each partition, ... If
PreemptType=preempt/qosis configured and if the preempted job(s) and the preemptor job are on the same partition, then they will share resources with the Gang scheduler (time-slicing).
本集群 PreemptMode = REQUEUE(不含 GANG)→ suspend 路径不可用 → 抢占动作层失败 → 静默放弃。
"动作取自受害者 QOS"的唯一变量实验证据(两次实验仅变更该一个变量):
| 受害者 QOS | 受害者 QOS 的 PreemptMode | 抢占结果 |
|---|---|---|
| long | suspend | 不发生(抢占者 PD 30 分钟,日志无记录) |
| normal | requeue | 发生(preempted JobId=400 has been requeued) |
| long(改后) | requeue | 发生(preempted JobId=404 has been requeued) |
5.4 静默性验证¶
journalctl -u slurmctld --since "1 hour ago" | grep -iE "GANG|suspend|PreemptMode"
# 输出为空 —— 抢占失败全程零告警
这是本阶段最危险的一条:配置值看起来完全正确(
Preempt=long已声明),但抢占永不发生,且没有任何日志提示。 只有"做端到端抢占实测"才能发现。
六、缺陷详录与修复¶
D1 分区 QoS 不生效(详见主文档)¶
- 作业 QOS 由
--qos=或 assocDefaultQOS决定,分区 QoS 不给作业赋 QoS - 实测:383/387/388 提交到 interactive/regression/long 分区,QOS 全部落 normal
- 修复:提交模板强制
--qos=,或为 association 设置差异化DefaultQOS
D2 long QOS 的 suspend 抢占模式失效¶
# 修复(已验证立即生效)
sacctmgr -i modify qos long set preemptmode=requeue
# 回滚
sacctmgr -i modify qos long set preemptmode=suspend
替代方案(改动更大,需评估):集群层 PreemptMode=REQUEUE,GANG + 相应分区 OverSubscribe=FORCE。
D3 与抢占相关的次要发现¶
PreemptExemptTime=00:30:00对 EDA 交互场景偏长:交互任务往往等不了 30 分钟才拿到资源。 建议对 interactive QOS 单独设置更短的豁免期(QOS 级PreemptExemptTime优先级高于全局,官方 qos.html 第 44 行明确)。regressionQOS 的 PreemptMode=cluster与集群全局REQUEUE的关系需实测确认(本次未构造 regression 受害者场景)。
七、变更与回滚记录¶
| 变更 | 基线 | 用途 | 已回滚 | 回滚命令 |
|---|---|---|---|---|
PreemptExemptTime 30min→0→30min |
00:30:00 |
排除豁免期干扰 | 是 | cp -a /usr/local/slurm/etc/slurm.conf.bak.p6.preempt.20260911_120547 /usr/local/slurm/etc/slurm.conf && scontrol reconfigure |
| QOS long PreemptMode suspend→requeue→suspend | suspend |
因果对照实验 | 是 | sacctmgr -i modify qos long set preemptmode=suspend |
实验过程中的作业:全部通过 scancel 清理,未遗留 PD/RUNNING 作业;节点已全部回到 idle。
八、可复用排障清单(抢占不生效时按序检查)¶
# 1) 抢占者是否带正确 QOS?(D1)
scontrol show job <preemptor> | grep -E "QOS|Priority"
# 2) 抢占者 QOS 是否声明了可抢占受害者 QOS?
sacctmgr -n -P list qos format=Name,Priority,Preempt,PreemptMode
# 3) 受害者是否还在豁免期?
scontrol show job <victim> | grep -E "RunTime|PreemptEligibleTime|PreemptTime"
# 4) 受害者 QOS 的 PreemptMode 是否在当前集群可用?(D2)
scontrol show config | grep -E "^PreemptMode|^PreemptType"
# 若含 suspend 而集群 PreemptMode 无 GANG -> 该 QOS 的作业实际不可被抢占
# 5) 是否真的发生了抢占?
journalctl -u slurmctld --since "10 minutes ago" | grep -iE "preempt|Requeuing"
# 6) 优先级是否正确拉开?(QOS 因子 = QOS优先级 × 20)
sprio -l -j <preemptor>,<victim>
来源:
/home/rain/Documents/slurm/slurm_study/slurm_study_plan/阶段6_进阶与对比/QOS抢占与优先级实操.md| 最后更新:2026-09-11 12:30(由build/sync.py同步,请勿在站点侧修改)