跳转至

SOP:Slurm 日志分离 + MpiDefault 配置

变更日期:2026-09-12|执行方式:真实集群实施(非模拟) 集群:Slurm 26.05.2(k8s-master-01 + k8s-node-01/02/03,configless 模式) 变更窗口:队列空载窗口(slurmdbd → slurmctld → slurmd 逐级重启) 结果:成功(终检全绿,端到端作业验证通过)


一、背景

1.1 变更前状态(实测取证)

# scontrol show config
SlurmctldLogFile      = (null)     ← 未指定日志文件
SlurmdLogFile         = (null)
SlurmctldSyslogDebug  = (null)
SlurmdSyslogDebug     = (null)
MpiDefault            = (null)     ← 未配置

# slurmdbd.conf 中无任何日志相关配置

后果: 1. Slurm 日志全部混入 syslog/journald,与系统日志、LSF 日志、kube 组件日志交织,排障检索困难 2. 日志随 journald 的 SystemMaxUse 策略被整体轮转/清理,无法长期留存 Slurm 审计线索 3. MpiDefault 未配置,用户运行 MPI 作业缺少明确的默认启动方式

1.2 变更目标

编号 目标 验收标准
G1 Slurm 日志独立落盘 /var/log/slurm/{slurmctld,slurmd,slurmdbd}.log 有完整日志
G2 不再向 syslog/journald 写 Slurm 日志 journald 中 Slurm 自身日志行数 = 0
G3 日志可控轮转,避免无限增长 logrotate 配置生效(weekly / 50M / 保留 8 份)
G4 配置 MpiDefault scontrol show config 显示 MpiDefault = pmi2

二、前置条件

项 要求 本集群实测
队列为空 重启 slurmd 会因 KillMode=control-group 连坐清杀节点作业 ✅ 作业数=0
日志目录存在且属主正确 /var/log/slurm 属主 slurm:slurm ✅ 四节点均存在
磁盘空间 日志需独立空间 ✅ 控制节点 29G 可用;计算节点 71~76G
SELinux 不应阻止写入 ✅ Disabled
配置备份 必须可回滚 ✅ 见第三章
时钟同步 munge 依赖 ✅ chronyd active,亚毫秒偏差

三、备份(变更前置,必须执行)

# 控制节点 k8s-master-01
cd /usr/local/slurm/etc
cp -a slurm.conf    "slurm.conf.bak.$(date +%Y%m%d)"
cp -a slurmdbd.conf "slurmdbd.conf.bak.$(date +%Y%m%d)"

# 校验备份与源文件一致
md5sum slurm.conf slurm.conf.bak.$(date +%Y%m%d) \
       slurmdbd.conf slurmdbd.conf.bak.$(date +%Y%m%d)

本次实际备份结果:

1cdcc770022d0d65f49d42a565e443de  slurm.conf                         (6593 B)
1cdcc770022d0d65f49d42a565e443de  slurm.conf.bak.20260912
de4d6b3a813945c185bdaab54ab2d251  slurmdbd.conf                      (259 B)
de4d6b3a813945c185bdaab54ab2d251  slurmdbd.conf.bak.20260912

四、变更清单(精确到参数与值)

4.1 /usr/local/slurm/etc/slurm.conf(控制节点,configless 会下发给计算节点)

在 # --- 日志级别 --- 段(SlurmdDebug=info 之后)插入:

# --- 日志文件(2026-09-12 新增:日志独立落盘,不再写 syslog)---
SlurmctldLogFile=/var/log/slurm/slurmctld.log
SlurmdLogFile=/var/log/slurm/slurmd.log
SlurmctldSyslogDebug=quiet
SlurmdSyslogDebug=quiet

在 --- 进程跟踪与任务插件 --- 段(TaskPlugin= 之后)插入:

# --- MPI 默认类型(2026-09-12 新增)---
# Slurm 侧编译支持的类型:none / cray_shasta / pmi2(未编译 pmix)
MpiDefault=pmi2

参数取值依据(重要):SlurmctldSyslogDebug / SlurmdSyslogDebug 的合法值为 quiet | fatal | error | info | verbose | debug | debug2..debug5,没有 none。 要实现"完全不写 syslog",正确值是 quiet(Log nothing)——依据 man slurm.conf。

4.2 /usr/local/slurm/etc/slurmdbd.conf(控制节点)

追加:

# --- 日志独立落盘(2026-09-12 新增)---
DebugLevel=info
LogFile=/var/log/slurm/slurmdbd.log
DebugLevelSyslog=quiet

参数名易错点(重要):slurmdbd.conf 用的是 DebugLevelSyslog, 与 slurm.conf 的 SlurmctldSyslogDebug 不是同一个名字; 写成 SyslogLevel 属于非法参数。同样没有 none 值,用 quiet。 修改后必须保持 600 slurm:slurm(文件含数据库明文口令)。

4.3 /etc/logrotate.d/slurm(四个节点:控制 + 三计算)

# Slurm 日志轮转(2026-09-12 新增)
# 说明:Slurm 不会在收到信号后重新打开日志文件,因此必须使用 copytruncate
#       (先复制再截断原文件),进程继续写同一 inode,无需重启服务。
/var/log/slurm/slurmctld.log
/var/log/slurm/slurmdbd.log
/var/log/slurm/slurmd.log
{
    weekly
    size 50M
    rotate 8
    copytruncate
    compress
    delaycompress
    missingok
    notifempty
    nodateext
}

为什么必须用 copytruncate:Slurm 不支持"收到信号后重新打开日志文件", 若用传统 create 模式(重命名旧文件+新建),Slurm 仍会继续写已被重命名的旧 inode, 导致新日志文件始终为空、旧文件持续增长。

4.4 systemd drop-in(拦截 stdout 通道,关键补充)

问题:slurmctld -D -s 中的 -D 语义是 "Run daemon in foreground, with logging copied to stdout"。 日志虽已写入 SlurmctldLogFile,但仍被复制到 stdout,而 systemd 默认 StandardOutput=journal 会把 stdout 收进 journald —— 于是 journald 中仍有 Slurm 日志副本。 实测证据:journalctl -o verbose 显示 _TRANSPORT=syslog 0 条(说明 quiet 已生效), 但 _TRANSPORT=stdout 38 条(stdout 通道残留)。

方案:用 systemd drop-in 丢弃 stdout 副本(不改原 unit,便于回滚):

# 控制节点
for u in slurmctld slurmdbd; do
  mkdir -p /etc/systemd/system/${u}.service.d
  cat > /etc/systemd/system/${u}.service.d/10-logfile-only.conf <<'EOF'
# 2026-09-12 日志分离:Slurm 以 -D 运行时会把日志复制到 stdout,
# 而 systemd 默认把 stdout 收进 journald,导致日志在 journal 中仍有副本。
# 日志已完整写入 SlurmctldLogFile/LogFile,故此处丢弃 stdout 副本。
[Service]
StandardOutput=null
EOF
done
systemctl daemon-reload

# 计算节点(三台各执行)
mkdir -p /etc/systemd/system/slurmd.service.d
cat > /etc/systemd/system/slurmd.service.d/10-logfile-only.conf <<'EOF'
# 2026-09-12 日志分离:丢弃 -D 产生的 stdout 副本(日志已写入 SlurmdLogFile)
[Service]
StandardOutput=null
EOF
systemctl daemon-reload

保留的排障通道:StandardError 未改动(仍进 journald), 因此服务启动阶段的 stderr 错误仍可在 journalctl 中看到,兼顾"日志分离"与"启动可排障"。


五、分步操作(执行顺序)

# Step 0 安全门禁:队列必须为空
export PATH=/usr/local/slurm/bin:$PATH
[ "$(squeue -h -o '%i' | wc -l)" -eq 0 ] || { echo "队列非空,中止"; exit 1; }

# Step 1 备份(见第三章)

# Step 2 预创建日志文件(权限按运行身份)
touch /var/log/slurm/slurmctld.log
chown slurm:slurm /var/log/slurm/slurmctld.log && chmod 640 /var/log/slurm/slurmctld.log
#   slurmdbd.log 已存在(slurm:slurm 600),沿用
#   slurmd.log 由 slurmd(root)首次启动时自动创建

# Step 3 改 slurm.conf / slurmdbd.conf(见第四章)

# Step 4 部署 logrotate(四节点)

# Step 5 部署 drop-in 并 daemon-reload(四节点)

# Step 6 重启服务(顺序不可颠倒)
systemctl restart slurmdbd   && sleep 8
systemctl restart slurmctld  && sleep 12
for n in k8s-node-01 k8s-node-02 k8s-node-03; do
  ssh "$n" "systemctl restart slurmd"
done

# Step 7 验证(见第六章)

为什么必须重启而不是 scontrol reconfigure: SlurmctldLogFile / SlurmdLogFile 属于启动期参数,reconfigure 不重建日志输出通道; 实测 reconfigure 可生效的是 SlurmctldDebug(级别),而非日志目标。


六、验证(实测结果)

6.1 参数生效

MpiDefault              = pmi2
SlurmctldLogFile        = /var/log/slurm/slurmctld.log
SlurmctldSyslogDebug    = quiet
SlurmdLogFile           = /var/log/slurm/slurmd.log
SlurmdSyslogDebug       = quiet

6.2 日志文件落盘(G1)

-rw-r----- 1 slurm slurm  2153 9月 12 12:25 /var/log/slurm/slurmctld.log
-rw------- 1 slurm slurm   ... 9月 12 12:25 /var/log/slurm/slurmdbd.log
-rw------- 1 root  root   2772 9月 12 12:27 /var/log/slurm/slurmd.log   (三节点)

6.3 已脱离 syslog(G2)—— 核心验收项

# 通道统计(journalctl -o verbose)
_TRANSPORT=syslog 条数: 0      ← SlurmctldSyslogDebug=quiet 生效
_TRANSPORT=stdout 条数: 38     ← drop-in 部署前残留
# drop-in 生效后(12:27:44 起)
slurmctld 自身日志行数 = 0
slurmd    自身日志行数 = 0
slurmdbd  自身日志行数 = 0

判定方法说明:journald 同时接收 syslog API 与进程 stdout 两条通道; 用 _TRANSPORT 字段可精确区分,避免"日志还在 journald"的误判。 残留的历史行(12:25~12:27)属于 drop-in 生效之前的旧进程,非新增。

6.4 端到端作业验证

提交:sbatch -p compile -n2 --mem=2048M --wrap "hostname; echo E2E_OK"   → JobId=438
结果:COMPLETED  ExitCode=0:0  NodeList=k8s-node-01

journald 增量:slurmctld = 0 ;slurmd = 0        ← 日志完全未进 journal
文件日志(控制节点):
  [2026-09-12T12:28:13.001] sched: Allocate JobId=438 NodeList=k8s-node-01 #CPUs=2 Partition=compile
  [2026-09-12T12:28:14.339] _job_complete: JobId=438 WEXITSTATUS 0
  [2026-09-12T12:28:14.340] _job_complete: JobId=438 done
文件日志(计算节点):
  [2026-09-12T12:28:13.769] Launching batch JobId=438 SLUID=sDJHM29Y03K800 for UID 2001
  [2026-09-12T12:28:13.981] [438.batch] task/cgroup: _memcg_initialize: job: alloc=2048MB mem.limit=3072MB
  [2026-09-12T12:28:14.345] [438.batch] done with step

附带收益:slurmd 日志中的 alloc=2048MB mem.limit=3072MB 第三次独立验证了 cgroup.conf 的 AllowedRAMSpace=150%(2048 × 1.5 = 3072),与阶段 1/6 的结论一致。

6.5 logrotate 校验(G3)

$ logrotate -d /etc/logrotate.d/slurm
rotating pattern: /var/log/slurm/slurmctld.log
considering log /var/log/slurm/slurmdbd.log
  log needs rotating          ← 该文件 105MB > 50M,下次运行时将轮转压缩
considering log /var/log/slurm/slurmd.log
  log does not exist -- skipping   ← 计算节点首次运行前正常跳过

七、回滚步骤(完整、可直接执行)

# R1 恢复配置(控制节点)
cd /usr/local/slurm/etc
cp -a slurm.conf.bak.20260912    slurm.conf
cp -a slurmdbd.conf.bak.20260912 slurmdbd.conf
#   权限复位(备份为 cp -a,权限已保留;仍显式确认更稳)
chown slurm:slurm slurmdbd.conf && chmod 600 slurmdbd.conf

# R2 移除 logrotate(四节点)
rm -f /etc/logrotate.d/slurm

# R3 移除 drop-in(四节点)
rm -rf /etc/systemd/system/slurmctld.service.d \
       /etc/systemd/system/slurmdbd.service.d
for n in k8s-node-01 k8s-node-02 k8s-node-03; do
  ssh "$n" "rm -rf /etc/systemd/system/slurmd.service.d"
done

# R4 重载并重启(顺序同正向)
systemctl daemon-reload
systemctl restart slurmdbd; sleep 8
systemctl restart slurmctld; sleep 12
for n in k8s-node-01 k8s-node-02 k8s-node-03; do ssh "$n" "systemctl restart slurmd"; done

# R5 验证回滚
scontrol show config | grep -iE "^MpiDefault|^SlurmctldLogFile|^SlurmdLogFile"
#   期望:三项均回到 (null)
journalctl -u slurmctld --since "1 min ago" | tail   # 日志重新出现于 journald

回滚无需删除日志文件:/var/log/slurm/*.log 保留不影响回滚后运行(不再被写入)。 如需彻底清理,确认服务已回滚后再删除。


八、风险说明

风险 等级 说明 缓解措施
重启 slurmd 导致节点作业被杀 高 KillMode=control-group 会连坐清杀 cgroup 内全部进程(阶段 5 F2 已实测) 强制"队列为空"门禁;生产建议先 DRAIN 等作业跑完
重启 slurmctld 中断调度 中 重启期间无法提交/调度 选低峰窗口;重启仅十余秒;StateSaveLocation 保证状态恢复
重启 slurmdbd 中断记账 低 调度不受影响,记账事件进 dbd.messages 缓冲,恢复后补传 观察 dbd.messages 是否清空
日志文件权限错 → 服务起不来 中 Slurm 对日志文件不可写会 fatal 预先创建并设定正确属主(slurm:slurm / root:root)
参数值非法 → 服务无法启动 高 本次实际发生,见第九章 改配置前必须查 man 页确认取值;改后立即 systemctl restart 并观察
完全停写 journal 后降低可观测性 中 journald 不再有 Slurm 日志,需改变排障习惯 保留 stderr→journal 通道;排障改用 /var/log/slurm/*.log
logrotate 配置错误 低 可能不轮转或误删日志 用 logrotate -d dry-run 校验后再启用

九、排错记录(本次实际踩坑,务必沉淀)

9.1 事故:SlurmctldSyslogDebug=none 非法 → slurmctld/slurmdbd 启动失败

现象:变更后执行 squeue 报错,slurmdbd 重启失败:

squeue: error: Invalid SlurmctldSyslogDebug none
squeue: fatal: Unable to process configuration file
systemctl restart slurmdbd  →  failed

根因:SlurmctldSyslogDebug 的合法取值不含 none。依据 man slurm.conf:

SlurmctldSyslogDebug
    quiet     Log nothing
    fatal     Log only fatal errors
    error     Log only errors
    info / verbose / debug / debug2..debug5

影响: - slurmctld 因配置 fatal,叠加 Restart=always 进入重启循环 - slurmdbd 同样解析 slurm.conf,直接 failed(其 unit 无 Restart) - 整个集群调度不可用(约 1 分钟窗口)

修复:none → quiet(SlurmctldSyslogDebug / SlurmdSyslogDebug 各一处),重启后恢复。

教训: 1. Slurm 参数取值必须查 man 页,不能凭直觉用 none/off 之类的通用词 2. 变更后立即验证服务状态,不要连续执行多步后再统一验证(本次因 set -e 在 systemctl is-active 返回非 0 时中断,反而缩短了故障暴露时间) 3. 单点集群改 slurm.conf 属高危操作,应先在测试配置上验证语法;slurm.conf 建议用 slurmctld -f <file> 之类做预检(本版本无 -t,可先在备用路径放置配置并临时启动验证)

9.2 事故:slurmdbd.conf 参数名写错(SyslogLevel vs DebugLevelSyslog)

现象:slurmdbd 即使修好 slurm.conf 后仍 failed。

根因:slurmdbd.conf 与 slurm.conf 的日志参数命名体系不同:

用途 slurm.conf slurmdbd.conf
日志级别(文件) SlurmctldDebug / SlurmdDebug DebugLevel
日志级别(syslog) SlurmctldSyslogDebug / SlurmdSyslogDebug DebugLevelSyslog
日志文件 SlurmctldLogFile / SlurmdLogFile LogFile

验证方法(本次采用):列出 man 页的合法参数名再比对——

man slurmdbd.conf | col -b | grep -E "^       [A-Z][A-Za-z]+$" | sort -u

修复:SyslogLevel=none → DebugLevelSyslog=quiet。

9.3 现象:日志已分离但 journald 仍有副本

根因:-D 参数把日志复制到 stdout,systemd 默认 StandardOutput=journal 收走。 判定:journalctl -o verbose 的 _TRANSPORT 字段可区分 syslog / stdout 通道。 修复:drop-in 设 StandardOutput=null(见 4.4)。


十、遗留问题与建议

项 说明 建议
OpenMPI 未编译 Slurm PMI 支持 MpiDefault=pmi2 已配置,但 OpenMPI 4.1.5 编译时未启用 --with-pmi=slurm,srun -n N ./prog 仍会报 OMPI was not built with SLURM's PMI support。详见 MPI与OpenMPI集成实测报告.md 如需 srun 直启 MPI,应单独立项重编译 OpenMPI(加 --with-pmi=slurm)
StateSaveLocation 写入慢 日志出现 Saving to StateSaveLocation took 615ms... Please check backing filesystem(本次变更前即存在) 检查 /var/spool/slurmctld 所在盘 IO;EDA 大集群建议独立 SSD
旧 slurmdbd.log 105MB 变更前遗留的 9月2日旧日志 下次 logrotate 自动轮转压缩;也可立即手动执行 logrotate -f /etc/logrotate.d/slurm
sched_min_age=30 疑似无效参数 SchedulerParameters 中的该项在 man 页中不存在(阶段 6 已记录) 建议清理,避免"以为配了"
日志级别为 info 生产排障期可临时调 debug(scontrol reconfigure 即可生效,无需重启) scontrol setdebug debug 临时提级,排障后 scontrol setdebug info

十一、变更后文件清单

文件 位置 说明
SOP_日志分离与MPI默认.md 本目录 本文档
apply_slurm_log_mpi.sh 本目录 正向变更可复现脚本
rollback_slurm_log_mpi.sh 本目录 回滚脚本
MPI与OpenMPI集成实测报告.md 本目录 MPI 四组对照实测与结论
slurm.conf.bak.20260912 控制节点 /usr/local/slurm/etc/ 配置备份(md5 1cdcc770...)
slurmdbd.conf.bak.20260912 控制节点 /usr/local/slurm/etc/ 配置备份(md5 de4d6b3a...)

来源:/home/rain/Documents/slurm/slurm_study/slurm_study_plan/运维变更_日志分离与MPI默认/SOP_日志分离与MPI默认.md | 最后更新:2026-09-12 12:29(由 build/sync.py 同步,请勿在站点侧修改)