跳转至

记账、配额实操与容量规划

执行日期:2026-09-11 | 集群:Slurm 26.05.2 + slurmdbd/MySQL 复现脚本:./phase6_lab.sh quota|capacity 相关文档:阶段6_进阶与对比.md | QOS抢占与优先级实操.md


一、记账体系与 TRES

1.1 关键配置(实测)

AccountingStorageType    = accounting_storage/slurmdbd
AccountingStorageHost    = k8s-master-01
AccountingStorageEnforce = associations,limits,qos
AccountingStorageTRES    = cpu,mem,energy,node,billing,fs/disk,vmem,pages,
                           license/ads,license/ams_sim,license/assura_drc,license/assura_lvs,
                           license/calibredrc,license/calibrelvs,license/calibreperc,
                           license/calibrexact,license/calibrexrc,license/ncsim

AccountingStorageEnforce 三个维度的实测含义:

维度 强制内容 实测表现
associations 未登记的 account/user 不能提交 未授权的 --qos= 直接拒绝
limits 限额强制生效 MaxTRESPU 生效(见第三节)
qos QOS 授权与限额强制 assoc 未授权 QOS → Invalid qos specification

1.2 TRES 与 License 打通验证

$ scontrol show licenses
LicenseName=ads@27000@k8s-master-02
    Total=8 Used=0 Free=8 Reserved=0 Remote=yes
    LastConsumed=0 LastDeficit=0 LastUpdate=2026-09-10T14:00:10
LicenseName=ams_sim@27000@k8s-master-02
    Total=8 Used=0 Free=8 Reserved=0 Remote=yes

这是本阶段确认的重要事实:Licenses= 与远程 FlexLM(k8s-master-02:27000)链路已真实打通, 14 项 EDA 工具 License 全部登记在 TRES 中且轮询正常(LastUpdate 分钟级)。 EDA 场景可基于此实现"License 感知调度"(QOS MaxTRESPU=license/ads=N 限额、--licenses=ads:2 申报)。

1.3 记账层次结构

Cluster(cluster)
 └── Account(root) ── dev ── teama ── teama1 ── teamb ── teamb1 ── teamc ── teamc1 ── it ── ops
      └── User(rain01/rain02/rain03/cloud01/cy01/david01/lws01/cq01/root)
           └── Partition(interactive/compile/regression/long)
                └── QOS(interactive/regression/normal/long)

实测 sacctmgr list assoc 摘要(17 条 association):

cluster|root|||normal|1
cluster|root|root||normal|1
cluster|dev|||interactive,long,normal,regression|1
cluster|teama|||interactive,long,normal,regression|1
cluster|teama|rain01||interactive,long,normal,regression|1
cluster|teama|rain02||interactive,long,normal,regression|1
cluster|teama|rain03||interactive,long,normal,regression|1
... (teama1/teamb/teamb1/teamc/teamc1/it/ops 同构)

注意 root 只授权 normal(唯一例外),业务用户均有 4 个 QOS。


二、sacctmgr 实操记录(含关键字陷阱)

2.1 备份(一切变更之前)

sacctmgr -i dump cluster file=/root/slurm_acct_backup_$(date +%Y%m%d).cfg
# 实测输出:逐条回显全部 account/user/QOS 定义,落盘 3153 字节
# 恢复参照:该文件可直接作为重建 association 的依据
ls -l /root/slurm_acct_backup_20260911.cfg

2.2 创建(本次实操命令与实测回显)

$ sacctmgr -i add qos t6lab Priority=30 MaxTRESPU=cpu=8 MaxJobsPU=2 MaxSubmitJobsPU=3
 Adding QOS(s)
  t6lab
 Settings
  Description              = t6lab
  MaxJobsPerUser           = 2
  MaxSubmitJobsPerUser     = 3
  MaxTRESPU                = cpu=8
  Priority                 = 30

$ sacctmgr -i add account t6lab Description="P6 lab temp" Organization=study
 Associations =
  C = cluster    A = t6lab

$ sacctmgr -i add user root account=t6lab
 Associations =
  C = cluster    A = t6lab                U = root

2.3 两个实测踩坑

坑 1:MaxSubmitPU 不是设置关键字

$ sacctmgr -i add qos t6lab MaxSubmitPU=3
 Unknown option: MaxSubmitPU=3        <- 整条命令中止,QOS 未被创建
列表显示字段 正确设置关键字
MaxSubmitPU MaxSubmitJobsPU
MaxJobsPU MaxJobsPU
MaxTRESPU MaxTRESPU=cpu=8

坑 2:授权 QOS 用 set qos= 会与 DefaultQOS 冲突

$ sacctmgr -i modify user where user=root account=t6lab set qos=t6lab
 Error with request: This request would make it so some associations would not have access to their default qos.
 Modified user associations...         <- 但 assoc 实际未更新(QOS 仍为 normal)

正确写法(追加):

$ sacctmgr -i modify user where user=root account=t6lab set qos+=t6lab
$ sacctmgr -n -P list assoc where account=t6lab format=Account,User,QOS,DefaultQOS
t6lab|root|normal,t6lab|normal

2.4 查询与删除

# 查询(推荐用 format= 精简输出)
sacctmgr -n -P list qos  format=Name,Priority,Preempt,PreemptMode
sacctmgr -n -P list assoc where account=t6lab format=User,QOS,DefaultQOS
scontrol show assoc_mgr qos=t6lab          # slurmctld 内存中解析后的实时视图(含计数器)

# 删除(顺序:先关联,再账号/QOS)
sacctmgr -i delete user rain01 account=t6lab
sacctmgr -i delete user root   account=t6lab
sacctmgr -i delete account t6lab
sacctmgr -i delete qos t6lab

scontrol show assoc_mgr 是排障利器:它显示 slurmctld 内存中的限额值与实时计数,例如 MaxJobsPU=2(4) 表示"限额 2 / 当前 4"。判断"限额没生效"时,先看这里确认数据是否真的加载了。


三、限额实验(含缺陷 D4)

3.1 生效的限额:MaxTRESPU(TRES 类)

# 排队端拦截
$ sbatch -A t6lab --qos=t6lab -p compile -n12 --mem=20000M --wrap "sleep 60"
Submitted batch job 416
    JOBID      NAME     USER   QOS  ST  CPUS   REASON
      416  T6B_12C     root  t6lab  PD    12   QOSMaxCpuPerUserLimit     <- 限额 cpu=8,请求 12

# 给出 QOS 加 DenyOnLimit 后,升级为提交端硬拒
$ sacctmgr -i modify qos t6lab set flags=DenyOnLimit
$ sbatch -A t6lab --qos=t6lab -p compile -n16 --mem=60000M --wrap "sleep 60"
sbatch: error: QOSMaxCpuPerUserLimit
sbatch: error: Batch job submission failed: Job violates accounting/QOS policy (job submit limit, user's size and/or time limits)
拦截路径 触发条件 表现
排队端 单作业 TRES 请求超 MaxTRESPU PD + REASON=QOSMaxCpuPerUserLimit
提交端 QOS 带 Flags=DenyOnLimit 立即失败 + Job violates accounting/QOS policy

3.2 未生效的限额:MaxJobsPU / MaxSubmitJobsPU / assoc MaxJobs(缺陷 D4)

实验设计:QOS t6lab 设 MaxJobsPU=2、MaxSubmitJobsPU=3;association 再设 MaxJobs=1;由普通用户 rain01 提交。

实测结果(全部未被拦截):

t6lab|30|2|3|cpu=8                <- QOS 限额已正确存储
rain01|normal,t6lab|normal        <- 授权正确
rain01|1||                        <- association MaxJobs=1 已存储

   421 T6A2_4 rain01 t6lab R 1     <- 第 4 个作业,MaxSubmitJobsPU=3 未拦截
   418 T6A2_2 rain01 t6lab R 1
   419 T6A2_3 rain01 t6lab R 1
   417 T6A2_1 rain01 t6lab R 1
   (MaxJobsPU=2 下 4 个作业同时 RUNNING)

scontrol show assoc_mgr 证明数据与计数均正确加载:

QOS=t6lab(7)
    PreemptMode=OFF   Priority=30
    User Limits
      rain01(2001)
        MaxJobsPU=2(4)  MaxJobsAccruePU=N(0)  MaxSubmitJobsPU=3(4)     <- 限额 2/3,计数 4/4
        MaxTRESPU=cpu=8(4),mem=N(8192),...

已排除的原因:

假设 验证 结论
限额未加载到 slurmctld scontrol show assoc_mgr 显示限额与计数均正确 排除
调度侧缓存陈旧 scontrol reconfigure 后重测 排除(仍不拦截)
root 特权豁免 改用普通用户 rain01(AdminLevel=None) 排除(同样不拦截)
缺少 DenyOnLimit 标志 给 QOS 加 Flags=DenyOnLimit 计数类仍不拦截(TRES 类被强化为硬拒)
关键字写错 sacctmgr list qos format=...MaxJobsPU... 回读为 2 排除

结论与建议:

  1. 本集群 TRES 类限额(cpu/mem)可靠可用,计数类限额(MaxJobsPU / MaxSubmitJobsPU / assoc MaxJobs)实测不生效;
  2. 生产上"限制并发/提交数"优先用 TRES 表达(如 MaxTRESPU=cpu=N),并加 Flags=DenyOnLimit 在提交端兜底;
  3. 计数类限额如需使用,必须先在目标版本做受控验证(本报告已提供完整验证方法);
  4. D4 的精确代码路径未定位,建议向 Slurm 社区确认是否为 26.05 的已知行为(本报告按"现象+证据+已排除项"如实记录,不做主观归因)。

3.3 临时实体的完整回滚(本次已执行)

scancel $(squeue -h -o "%i")
sacctmgr -i delete user rain01 account=t6lab
sacctmgr -i delete user root   account=t6lab
sacctmgr -i delete account t6lab
sacctmgr -i delete qos t6lab
# 校验
sacctmgr -n -P list qos format=Name,Priority,Preempt,PreemptMode    # 回到 4 个基线 QOS
sacctmgr -n -P list assoc where account=t6lab                       # 空
sacctmgr -n -P list account where name=t6lab                        # 空

四、记账报表实操

4.1 作业明细(sacct)

$ sacct -j 427 -X -o JobID,JobName%12,Partition,Account,User,State,Elapsed,AllocCPUS,ReqMem,MaxRSS,ExitCode,NodeList
JobID      JobName      Partition  Account  User    State      Elapsed  AllocCPUS  ReqMem  MaxRSS  ExitCode  NodeList
427        SLURM_SIDE   compile    teama    rain01  COMPLETED  00:00:27  2          1G              0:0       k8s-node-01

常用字段与含义(本集群已实测):

字段 含义 备注
AllocCPUS 实际分配 CPU 数 计费核心字段
ReqMem 申请内存 后缀 c=per-CPU,n=per-Node
MaxRSS 峰值常驻内存 需 JobAcctGather 配置
ExitCode 退出码 退出状态:信号 SEGV=0:11、命令不存在=127:0、OOM=0:125(阶段 5 已证实)
Elapsed 运行时长 —

4.2 聚合报表(sreport)

# 集群利用率(CPU 小时)
$ sreport cluster utilization start=2026-08-01 -t hours
  Cluster  Allocate   Down  PLND Dow   Idle   Planned  Reported
  cluster       124      7         0   9446        47      9625

注意:sreport account utilization 是无效写法,实测报 invalid keyword: account。 正确写法为报告类型:sreport cluster AccountUtilizationByUser / AccountUtilizationByQOS / UserUtilizationByAccount / UserUtilizationByWckey / Utilization / WCKeyUtilizationByUser。

# 用户用量排行
$ sreport user topusage start=2026-09-01 topcount=10
  Cluster  Login   Proper Name  Account  Partition   Used
  cluster  rain01  rain01       teama    eda         6669
  cluster  rain01  rain01       teama                673
  cluster  root    root         root                  82
# 公平份额
$ sshare -a -o "Account,User,RawShares,RawUsage,EffectvUsage,FairShare"
Account     User   RawShares  RawUsage  EffectvUsage  FairShare
root                       1     127447      1.000000
 root       root           1       4559      0.035776   0.555556
dev                        1     122887      0.964224
 teama                     1     122887      1.000000
  teama     rain01         1      33924      0.276064   0.111111
  teama     rain02         1          0      0.000000   0.333333

五、容量现状分析

5.1 物理容量

项 值 来源
计算节点 3 台(k8s-node-01/02/03) sinfo
单节点 CPU 16 核(CoresPerSocket=1 × Sockets=16,ThreadsPerCore=1) scontrol show node
单节点内存 32010 MB(约 31.3 GB) RealMemory
集群总容量 48 CPU / 96030 MB(约 93.8 GB) CfgTRES=cpu=16,mem=32010M
可用分区时限 interactive 4h / compile 24h(默认)/ regression 8h / long 72h scontrol show partition
特征标签 intel, centos7, skx-16c AvailableFeatures
GRES (null) —— 无 GPU scontrol show node

5.2 利用率实测(严重低载)

统计区间 Allocate Idle Planned Down 利用率
2026-08-01 ~ 09-11(含旧 EDA 分区时期) 124 CPU·h 9446 CPU·h 47 7 1.29%
2026-09-08 ~ 09-11(EDA 规范配置后) 13 CPU·h 3478 CPU·h 13 0 0.37%

注:sreport 的 Reported 合计(9625 / 3504 CPU·h)远小于理论值(48 CPU × 41 天 × 24h = 47232), 原因是期间发生过分区重构(旧 EDA 分区在 9/8 被 4 个新分区取代),历史数据跨了两套配置,报表口径不连续。 结论仍成立:当前集群处于严重低载状态(<1.5%)。

5.3 作业画像(2026-09-01 起,427 个已结束作业)

按分区分布:EDA(旧)=240  compile=134  long=23  interactive=15  regression=15
状态分布:  COMPLETED=292  CANCELLED=103  FAILED=27  OUT_OF_MEMORY=3  TIMEOUT=2
            (其中 "CANCELLED by 0"(50) 为本次阶段测试手动清理,非业务失败)
资源消耗:  总 129.4 CPU·h,平均时长 102.7 秒,最长 2604 秒(43 分钟)
排队情况:  平均排队 ≈ 0 秒(集群空闲,无排队压力)

作业形态特征:

  • 绝大多数是短作业(平均 103 秒,最长 43 分钟),与 interactive(4h) / regression(8h) 的时限设定严重不匹配
  • long(72h) 分区 23 个作业 —— 实际负载中缺少长时任务,该分区基本空转
  • 失败构成:FAILED 27 + OOM 3 + TIMEOUT 2 = 32(占 7.5%),主要来自阶段 4/5 的故意构造场景

5.4 容量缺陷 D3:DefMemPerCPU 吃掉一核

DefMemPerCPU = 2048 MB
RealMemory   = 32010 MB

默认可选核数 = floor(32010 / 2048) = 15 核(16 核需要 32768 MB > 32010 MB)

实测:

提交方式 结果
sbatch -N1 -n15(无 --mem) COMPLETED,ReqMem=30G,落在 k8s-node-02
sbatch -N1 -n16(无 --mem) FAILED:Batch job submission failed: Requested node configuration is not available
sbatch -N1 -n16 --mem=31000M COMPLETED,ReqMem=31000M,落在 k8s-node-01

影响量化:

  • 每节点 1 核(16-15)无法通过默认路径使用 → 集群 3/48 = 6.25% 的算力被配置浪费
  • EDA 工具常按核授权(如 16 核满节点跑一个 tool),此类作业100% 提交失败,用户被迫改写命令

修复建议(按优先级):

# 方案 1(推荐,最小改动):调整 DefMemPerCPU 到 2000,使 16×2000=32000 ≤ 32010
DefMemPerCPU=2000

# 方案 2:用户侧显式声明内存(已实测可行,但依赖规范约束)
sbatch -N1 -n16 --mem=31000M ...

# 方案 3:同时核对 MaxMemPerCPU,避免与 DefMemPerCPU 冲突

六、容量规划与生产最佳实践

6.1 容量规划建议

结论 依据 建议动作
算力严重过剩 利用率 0.37%~1.29% 承接更多 EDA 业务,或评估缩容(保留 3 节点以容纳多节点作业)
时限配置与真实负载错配 平均作业 103 秒 vs 分区时限 4h~72h 保留 interactive 4h;long 72h 可下调(当前空转);可增设 5~15 分钟的 fast 分区承接短作业
单节点可调度核数被内存默认值限制 D3:15/16 核可用 改 DefMemPerCPU=2000,回收 6.25% 算力
无 GPU GRES=(null) EDA 若引入 GPU 加速工具,需先规划节点与 gres.conf(阶段 3 已做模拟推演)
License 与算力解耦 14 项 FlexLM License 已联通,单工具 8 席 用 QOS MaxTRESPU=license/xxx 做 License 感知限额,避免"有核无 License"空跑
双调度器并存 LSF 20 slot/节点 vs Slurm 16 CPU/节点 迁移需按 6.2 做容量重估,不能 1:1 换算

6.2 生产最佳实践清单(含阶段 3/5/6 全部发现)

提交侧

  1. EDA 提交模板必须显式带 --qos=(否则按 D1 全部落 normal,分级失效);
  2. 满节点作业显式 --mem=(规避 D3),或先修 DefMemPerCPU;
  3. 短作业走 interactive/新增快速分区,长作业走 long,避免大作业占满长时限分区;
  4. License 作业申报 --licenses=<tool>:<n>,让调度器做 License 感知排队。

配置侧

  1. PreemptExemptTime=30min 对交互场景偏长,建议在 interactive QOS 上单独设更短值(QOS 级优先于全局);
  2. SchedulerParameters 中的 sched_min_age=30 疑似无效参数(man 页无此子项),建议清理,避免"以为配了";
  3. SchedulerParameters 含 defer:单作业提交不会立即调度,追求低延迟需评估是否移除;
  4. 抢占配置不能用配置值验收,必须做端到端抢占实测(D2 教训);
  5. 限额配置优先用 TRES 类(D4 教训),计数类须受控验证;
  6. StateSaveLocation 避免放在慢速存储(阶段 3 已记录)。

运维侧

  1. 变更前必备份(cp -a slurm.conf slurm.conf.bak.<date> + sacctmgr dump),本次已形成标准动作;
  2. QOS/association 变更后用 scontrol show assoc_mgr 复核数据是否真的加载;
  3. 节点维护先 DRAIN 后停服务(阶段 5 教训:systemctl stop slurmd 会因 KillMode=control-group 连坐清杀作业);
  4. munge 密钥纳入 CMDB 基线(md5 318fd0afb38e9279a68523a455d964b5),三节点一致性定期校验。

6.3 巡检清单(建议节奏)

每日

systemctl is-active slurmctld slurmdbd munge       # 服务存活
sinfo -o "%20P %6D %6t"                            # 分区与节点状态(有无 down/drain)
squeue -o "%.6i %.10P %.2t %r"                     # 队列健康(有无异常 PD 堆积)
sdiag | head -20                                   # 调度器循环是否正常
scontrol show licenses | grep -c "Free=0"          # License 是否耗尽

每周

sreport cluster utilization start=$(date -d '7 days ago' +%F) -t hours   # 利用率趋势
sreport user topusage start=$(date -d '7 days ago' +%F) topcount=10      # 用量排行
sshare -a                                                                # 公平份额与累计用量
sacct -S $(date -d '7 days ago' +%F) -X -o State -n | sort | uniq -c     # 失败率趋势
sacct -S $(date -d '7 days ago' +%F) -X -o JobID,Partition,QOS,State     # QOS 落点抽检(D1 防御)

每月

sacctmgr dump cluster file=/root/slurm_acct_backup_$(date +%Y%m%d).cfg   # 记账库备份
# 三节点 munge 一致性
for n in 01 02 03; do ssh k8s-node-$n "md5sum /etc/munge/munge.key"; done
# 配置基线一致性(与备份比对 md5)
md5sum /usr/local/slurm/etc/slurm.conf
# 抢占链路端到端验证(D2 防御,见 QOS抢占与优先级实操.md 第八节)

七、变更与回滚记录(本次实操)

变更 基线 已回滚 回滚命令
临时 QOS/account/assoc t6lab 不存在 是 sacctmgr -i delete qos t6lab / delete account t6lab / delete user <u> account=t6lab
QOS long PreemptMode suspend 是 sacctmgr -i modify qos long set preemptmode=suspend
slurm.conf PreemptExemptTime 00:30:00 是 cp -a /usr/local/slurm/etc/slurm.conf.bak.p6.preempt.20260911_120547 /usr/local/slurm/etc/slurm.conf && scontrol reconfigure

备份文件:

/root/slurm_acct_backup_20260911.cfg                                  # 记账库全量导出
/usr/local/slurm/etc/slurm.conf.bak.p6.20260911_120306                 # md5=1cdcc770022d0d65f49d42a565e443de
/usr/local/slurm/etc/slurm.conf.bak.p6.preempt.20260911_120547         # 含 PreemptExemptTime=00:30:00

终检:4 个基线 QOS 完整(normal 20/requeue、interactive 100 Preempt=long,normal/requeue、regression 50/cluster、long 10/suspend); t6lab 无残留;队列空;12 个 node-partition 组合全 idle;slurm.conf md5 与备份一致。


来源:/home/rain/Documents/slurm/slurm_study/slurm_study_plan/阶段6_进阶与对比/记账配额与容量规划.md | 最后更新:2026-09-11 12:31(由 build/sync.py 同步,请勿在站点侧修改)