跳转至

Slurm 26.05 集群 RUNBOOK

面向日常运维与值班:拿着就能做。所有命令均为可直接粘贴的整行(含完整路径), 关键命令后附预期输出;输出不符时给出下一步动作。 本次部署的变更档案见同目录 SOP.md;排障过程见 INCIDENT-20260918-slurm-26.05部署排障.md。 本文档不含任何凭据原文,只说明"从哪里取"。

目录

一、服务概览

Slurm 是集群作业调度系统,负责把用户提交的计算任务分配到计算节点上执行。

组件构成

组件 角色 运行位置 端口
slurmctld 控制器(调度大脑),一主一备 .16 主 / .17 备 6817
slurmdbd 记账守护,向 MariaDB 写入作业与账户数据 .16 6819
slurmd 计算节点守护,拉起作业步骤 .18 / .19 / .20 6818
munged 认证服务(所有节点),提供免密的集群内互信 全部 6 台 unix socket
slurm-cluster-health.timer 巡检自愈,每 15 分钟检查节点并尝试恢复 .16(主控) —
sssd / oddjobd 经 LDAP 解析并认证业务用户;首次登录自动创建家目录 全部 6 台 出向 LDAP 389
Lmod 环境模块系统(module load),管理 EDA 工具版本、许可证与路径 全部 6 台 —

节点清单

主机名 IP 角色 规格
slurm-master-01 192.168.31.16 主控 + 记账 4C / 3G
slurm-master-02 192.168.31.17 备控 2C / 1G
slurm-work-01 192.168.31.18 计算(兼编译节点) 8C / 15G
slurm-work-02 192.168.31.19 计算 8C / 15G
slurm-work-03 192.168.31.20 计算 8C / 15G
hpc-submit 192.168.31.28 作业提交(纯客户端,不跑 daemon) 8C / 15G

hpc-submit 只装 Slurm 客户端命令、munge、LDAP 认证与共享盘挂载,不承载作业, 因此不挂 Lustre 与本地 scratch。纳管与卸载见 4.12。

外部依赖

依赖 地址 不可用时的后果
MariaDB(k8s Pod) 192.168.31.10:3306 slurmdbd 起不来 → 记账不可用;已有作业不受影响,但新作业可能因 QOS/Fairshare 校验失败
NFS 共享存储 宿主机 192.168.31.249:/data/nfs/slurm-state → /mnt/slurm-shared 主控无法读写 StateSaveLocation → slurmctld 停止响应,调度中断
NFS 家目录 宿主机 192.168.31.249:/data/nfs/home → /home(soft 挂载) 用户读写家目录报 I/O 错误(不会卡住登录);Slurm 调度与已提交作业不受影响
LDAP 192.168.31.10:389 新的登录/会话无法解析用户(已缓存凭据的会话不受影响);Slurm 侧账户与用户关联不受影响
NFS modulefiles 宿主机 192.168.31.249:/data/nfs/modulefiles → /opt/modulefiles(soft 挂载) module avail / module load 报 I/O 错误;已加载的模块在当次会话内仍生效,Slurm 调度与作业不受影响
Lustre 共享临时层 192.168.31.21@tcp:/edafs → /mnt/lustre(1 MDT + 1 OST,295G;三台计算节点已挂载,fstab defaults,nofail) 跨节点临时数据不可用;Slurm 调度不受影响,但依赖 /mnt/lustre 的作业会失败
本地 scratch 各计算节点 /dev/vdb → /local_scratch(xfs,noatime,50G/节点) 节点本地临时目录不可写($TMPDIR);Slurm 调度与其它作业不受影响

重要性等级

核心(P1):调度中断直接影响全部用户提交作业。主控故障时备控可接管,但 slurmdbd 与 NFS 均为单点。

共享存储单点:容量与故障预案

容量水位(2026-10-07 实测):

存储 位置 容量 已用 水位 单点
NFS /data —— /home、/projects、/tools、/pdk、/opt/modulefiles、/data/nfs/lsf、slurm-state .249:/dev/sdb1 1.8 T 654 G 38% 是(宿主机)
NFS k8s(/srv/nfs/k8s、k8s-hdd) .249:/dev/sda3(/) 220 G 161 G 77% ⚠️ 是(k8s 共用,勿动)
Lustre MDT .21 edafs-MDT0000 11.1 G 1.6 M 1% 是(MGS/MDS 同机)
Lustre OST .22 edafs-OST0000 294.4 G 1.4 M 1% 是(单 OST)
本地 scratch 各计算节点 /dev/vdb 50 G/台 389 M 1% 否(节点私有)

⚠️ 最紧的是 .249 的 /(220 G / 77%),k8s 与 NFS 元数据同盘;/data 尚宽裕(可用 1.1 T)。 slurm-state 仅 164 K,容量风险可忽略。MDT 虽 1% 但总量仅 11.1 G,大量小文件(典型 EDA 工程树)前须先评估。

故障预案(判定 → 止血 → 恢复;未演练项已标注):

故障 判定 处理
宿主机 .249 或 nfs-server 不可用 各节点 /home、/opt/modulefiles 读写报 I/O 错误(soft 挂载,不卡登录);slurmctld 日志报 StateSaveLocation 不可写、随后停止响应 先恢复 .249 的 nfs-server;确认 NFS 恢复后再按 4.2 恢复 slurmctld。禁止在 NFS 不可用时强启 slurmctld(会以不一致的 state 启动)
NFS /data 空间耗尽 df -h /data 100% 清理 /data/nfs/{home,projects} 下大文件;临时数据优先落 Lustre/scratch。不得动 /srv/nfs/k8s-hdd
Lustre MGS/MDS(.21)不可用 /mnt/lustre 读写失败;客户端 mnt-lustre.mount 落 failed 重启 .21 上的 mgs/mds;客户端由机制 B 自愈(.16 上 slurm-cluster-health.timer,15 min 内自动 reset-failed+start)。无 HA,故障期间元数据操作全停
OSS(.22)不可用 /mnt/lustre 读写报错 重启 .22 上的 ost;单 OST ⇒ 数据无法访问,只能等其恢复
本地 scratch 满 节点 df -h /local_scratch 100% scratch-gc timer(每日 03:30)自动清 -mtime +30;如需立即清理手工执行 GC 脚本(注意 users/*/virtuoso 已被排除,勿手删)
存储服务端(.21/.22/.249)未接 LDAP 服务端新增 EDA 用户需手工同步(双轨身份) 长期应接入同一 SSSD/LDAP 域;当前为已知限制

处置动作若涉及改配置/改挂载,按 C 类流程执行(备份 → 变更 → 验证 → 幂等复跑)。

二、接入与凭据

地址与端口

用途 地址
Slurm 客户端命令 登录后直接用 sinfo / squeue / sbatch(/etc/profile.d/slurm-path.sh 已把 /usr/local/slurm/{bin,sbin} 加进 PATH);非登录 shell 或脚本里用绝对路径 /usr/local/slurm/bin/<命令>
集群配置(configless) slurm-master-01:6817,slurm-master-02:6817
记账数据库 192.168.31.10:3306,库 slurm_acct_db
LDAP(用户与账户源) ldap://192.168.31.10:389,基准 dc=rainchen,dc=com

账号清单

账号 用途 位置
SSH root 部署与运维登录(5 台已免密) 部署机 /home/rain/.ssh/ 密钥
DB slurm slurmdbd 连接 MariaDB 的专用账号 密码见 config/slurm_deploy.yaml 的 database.password
DB root 仅用于建库/建号/授权 同上,database.admin_password
系统 slurm Slurm 守护进程运行用户(固定 uid/gid 64030) 由部署器创建
系统 munge munged 运行用户 由 munge 包创建
LDAP 用户 业务用户,5 台节点均可解析与登录(su - <用户> / ssh <用户>@<节点>) LDAP dc=rainchen,dc=com;账户层级见 4.4
LDAP bind 账号 sssd 与用户同步脚本连接 LDAP 用 cn=admin,dc=rainchen,dc=com;密码见 yaml 的 user_mgmt.ldap.password

凭据取用

# 查看 DB 应用账号密码(文件权限 600,仅 root/属主可读)
cd /home/rain/Documents/slurm_ins
grep -E '^\s*(user|password):' config/slurm_deploy.yaml

禁止把凭据粘贴进工单、聊天或本文档;排障需要临时登录时用 MYSQL_PWD 或临时 cnf 文件。

客户端接入示例

集群使用 configless 模式,计算节点不需要本地 slurm.conf;若要在新机器上作为提交客户端接入:

# 安装 slurm 客户端包后,仅需指定配置来源即可
export SLURM_CONF_SERVER=slurm-master-01:6817,slurm-master-02:6817
sinfo            # 预期正常列出分区与节点

三、日常速查表

目的 命令
看集群与节点状态 /usr/local/slurm/bin/sinfo -N -o '%N %T %C'
看队列 /usr/local/slurm/bin/squeue
看主备是否都在 /usr/local/slurm/bin/scontrol ping
看服务状态(主控) systemctl is-active munge slurmdbd slurmctld
看服务状态(计算) systemctl is-active munge slurmd
重启主控 systemctl restart slurmctld(备控会自动接管再回切)
让配置生效(不改服务) /usr/local/slurm/bin/scontrol reconfigure
看主控日志 journalctl -u slurmctld -n 50 --no-pager
手工巡检一次健康 /usr/bin/python3 /usr/local/bin/cluster_health_check.py --status
恢复被 DRAIN 的节点 /usr/local/slurm/bin/scontrol update NodeName=<节点> State=RESUME
查历史作业 /usr/local/slurm/bin/sacct -S today
查 QoS /usr/local/slurm/bin/sacctmgr -n show qos format=Name,Priority,MaxWall
更新部署(幂等) .venv/bin/python main.py --config config/slurm_deploy.yaml
补装/修复节点基础环境(不改 Slurm 服务) .venv/bin/python main.py --config config/slurm_deploy.yaml --node-env
验证 LDAP 用户可用 ssh root@192.168.31.16 "getent passwd cy01; su - cy01 -c 'id -u'"(预期输出 4001)
看 /home 是否共享挂载 for ip in 16 17 18 19 20; do ssh root@192.168.31.$ip "findmnt -n -o SOURCE /home"; done
看 sssd 状态 ssh root@192.168.31.16 "systemctl is-active sssd oddjobd; authselect current \| head -4"
清 sssd 缓存(LDAP 改用户后不生效时) ssh root@192.168.31.16 "sss_cache -E && systemctl restart sssd"
看可用模块 module avail(简写 ml av);搜全层级用 module spider <关键词>
加载 / 卸载模块 module load <模块> / module unload <模块>;清空全部用 module purge
看模块会改哪些变量(不改环境) module show <模块>
复用/修复环境模块 .venv/bin/python main.py --config config/slurm_deploy.yaml --module-env
模块列表不刷新时 module --ignore_cache avail(清缓存:rm -rf ~/.cache/lmod)
手工触发一次 LDAP 用户同步 ssh root@192.168.31.16 "/usr/bin/python3 /usr/local/bin/slurm_user_sync.py"
看用户同步日志 ssh root@192.168.31.16 "tail -50 /var/log/slurm_user_sync.log"
看用户同步定时任务 ssh root@192.168.31.16 "systemctl list-timers slurm-user-sync.timer"
提交节点是否就绪 ssh root@192.168.31.28 "systemctl is-active munge; findmnt -rno TARGET -t nfs,nfs4 \| wc -l"(预期 active 与 5)
从提交节点查集群 ssh root@192.168.31.28 'su - cy01 -s /bin/bash -c "sinfo -h -o \"%P %N %T\""'
纳入/移除提交节点(不改集群服务) .venv/bin/python main.py --config config/slurm_deploy.yaml --submit-node(移除加 --rollback)

四、日常操作

4.1 状态检查

/usr/local/slurm/bin/sinfo -N -o '%N %T %C %m'

预期(5 行含控制节点则说明有异常,正常应只有 3 个计算节点):

NODELIST     STATE  CPUS(A/I/O/T)  REAL_MEMORY
slurm-work-01 idle   0/8/0/8       15000
slurm-work-02 idle   0/8/0/8       15000
slurm-work-03 idle   0/8/0/8       15000

STATE 出现 drain/down/inval 时的处置见 八、故障处置。

4.2 启动 / 停止 / 重启

按依赖顺序操作,顺序不可颠倒:

# 全量启动:slurmdbd → slurmctld → slurmd
systemctl start slurmdbd                                   # .16
systemctl start slurmctld                                  # .16,然后 .17
systemctl start slurmd                                     # .18 ~ .20

# 全量停止:反向
systemctl stop slurmd slurmctld slurmdbd                   # 高危:停服会中断正在运行的作业调度

只重启 slurmctld 不会影响正在运行的作业;作业状态保存在 StateSaveLocation 中。

4.3 扩缩容(增删计算节点)

新增一个计算节点(以 .21 为例)的完整流程:

# 1. 在 config/slurm_deploy.yaml 的 nodes.compute 下追加一项
#    - hostname: "slurm-work-04"
#      ip: "192.168.31.21"
#      role: ["slurmd"]
#      cpus: 8           # 可省略:留空则由部署器探测真机(nproc)
#      memory_mb: 15000  # 可省略:留空则取物理内存 × auto_detect.memory_ratio(默认 0.95)

# 2. 新节点加免密(在部署机执行)
ssh-copy-id root@192.168.31.21

# 3. 跑一次部署:实现体会装包、分发产物、补齐运行库、写 /etc/hosts 与服务、起 slurmd
cd /home/rain/Documents/slurm_ins
.venv/bin/python main.py \
  --config config/slurm_deploy.yaml

# 4. 验证
/usr/local/slurm/bin/sinfo -N -o '%N %T' | grep slurm-work-04      # 预期 idle

下线节点:

/usr/local/slurm/bin/scontrol update NodeName=slurm-work-04 State=DRAIN Reason="maintenance"   # 先排空
/usr/local/slurm/bin/squeue -w slurm-work-04            # 预期无作业
# 再从 yaml 的 nodes.compute 删除该项并重跑部署,最后在新节点上停用服务:
systemctl disable --now slurmd munge                    # 高危:停服

4.4 用户与账户同步(LDAP)

集群的账户与用户由定时任务从 LDAP 自动同步,通常无需人工干预。

项 位置 / 命令
同步脚本 /usr/local/bin/slurm_user_sync.py(勿手工修改,由部署器维护)
运行配置 /etc/slurm-usermgmt/config.json
LDAP 凭据 /etc/slurm-usermgmt/ldap.pass(权限 600)
同步日志 /var/log/slurm_user_sync.log
定时任务 slurm-user-sync.timer,默认每日 03:30(带最长 10 分钟随机延迟)

账户层级由 LDAP 的 DN 结构决定:

frontend ─┬─ design   ← rain01 / rain02 / rain03
          └─ dv       ← cloud01
analog   ─┬─ custom   ← cy01
          └─ layout   ← david01
it       ─┬─ cad      ← lws01
          └─ sre      ← cq01
backend  ─┬─ pnr      (暂无用户)
          └─ signoff  (暂无用户)
# 手工触发一次同步(新增员工后想立即生效,不必等定时任务)
ssh root@192.168.31.16 "/usr/bin/python3 /usr/local/bin/slurm_user_sync.py"
# 预期日志:账户已存在/创建…,用户关联同步完成:新建 N,跳过 M,失败 0

# 查看某用户的关联
/usr/local/slurm/bin/sacctmgr -n -P show assoc user=rain01 format=User,Account,DefaultAccount

# 查看账户层级(Organizaton 列即父账户)
/usr/local/slurm/bin/sacctmgr -n -P show account format=Account,Org | sort

新员工入职:在 LDAP 中把用户加入对应小组(设置 gidNumber),等定时任务执行或手工触发同步即可。 若用户不属于任何 LDAP 小组且未配置 default_account,同步会跳过并告警,此时需在 LDAP 侧补组。

员工离职:从 LDAP 删除该用户后,同步会清理其 Slurm 关联。清理带三重保护——受保护用户 (root/slurm/munge 及排除列表)、有运行中作业的用户跳过、LDAP 返回用户数低于阈值时整体跳过。 默认已启用(remove_enabled: true);若要临时停用清理,把该项改为 false 后重跑 --user-mgmt 即可。

账户以 LDAP 为唯一来源:原有的 EDA 业务账户(engineering / verification / synthesis / physical,按"工种"划分)已于 2026-09-20 移除;配置 sacctmgr.accounts 里也不再定义,避免下次部署时被重建。当前仅保留管理账户 root(供 root 用户提交作业), 其余账户全部来自 LDAP 同步。

移除前的账户配置已备份:/var/backups/slurm/accounts_before_ldap_only_<时间戳>.txt。 需要恢复 EDA 账户时按该文件重建,并在 sacctmgr.accounts 中重新定义。

4.5 日志查看

日志 位置 / 命令
主控(Slurm 自身日志) /var/log/slurm/slurmctld.log 或 journalctl -u slurmctld
记账 /var/log/slurm/slurmdbd.log 或 journalctl -u slurmdbd
计算节点 journalctl -u slurmd
作业 Prolog/Epilog /var/log/slurm/prolog.log、/tmp/slurm_prolog_*.log(按 jobid)
巡检守护 journalctl -u slurm-cluster-health.service -n 50 --no-pager
巡检脚本自身日志 /var/log/slurm_cluster_health.log
# 查最近 10 分钟的报错(通用)
journalctl -u slurmctld --since '10 min ago' --no-pager | grep -iE 'error|fatal|denied|timeout'

4.6 进入节点排障

ssh root@192.168.31.18                          # 计算节点
systemctl status slurmd -l --no-pager           # 看启动失败原因
cat /var/spool/slurmd/conf-cache/slurm.conf | head   # configless 拉到的配置(验证与主控一致)

4.7 节点基础环境(命令 PATH / LDAP 用户 / 共享家目录)

三项能力由部署器统一维护(--node-env,全新部署时由主流程阶段 2 一并完成):

能力 落地物 查看方式
命令 PATH /etc/profile.d/slurm-path.sh bash -lc 'command -v sinfo' → /usr/local/slurm/bin/sinfo
LDAP 认证 /etc/sssd/sssd.conf(600)+ authselect sssd with-mkhomedir + sssd/oddjobd getent passwd cy01
共享家目录 /home ← 192.168.31.249:/data/nfs/home(fstab 持久化 + use_nfs_home_dirs on) findmnt -o SOURCE /home
# 验证 LDAP 用户可用(5 台都应成功)
ssh root@192.168.31.16 "getent passwd cy01"
#    预期:cy01:*:4001:4000:cy01:/home/cy01:/bin/csh
ssh root@192.168.31.16 "su - cy01 -c 'id'"
#    预期:uid=4001(cy01) gid=4000(custom) groups=4000(custom) ...

# 验证家目录在各节点是同一份
for ip in 16 17 18 19 20; do echo -n "192.168.31.$ip: "; \
  ssh root@192.168.31.$ip "findmnt -n -o SOURCE /home"; done
#    预期:5 行均为 192.168.31.249:/data/nfs/home

常用维护动作:

# 重装/修复(幂等:已就绪则零变更、全跳过,不重启 Slurm 服务)
cd /home/rain/Documents/slurm_ins
.venv/bin/python main.py \
  --config config/slurm_deploy.yaml --node-env

# LDAP 侧改了用户(改组、改 loginShell)后立即生效
ssh root@192.168.31.16 "sss_cache -E && systemctl restart sssd"

# 看 sssd 是否已连上 LDAP
ssh root@192.168.31.16 "systemctl status sssd --no-pager -l | head -12"

# 卸载三项能力(不删软件包与 NFS 上的家目录内容)
.venv/bin/python main.py \
  --config config/slurm_deploy.yaml --node-env --rollback

两个易踩的点:① 新增/修改 LDAP 用户后若节点上不生效,先 sss_cache -E 清缓存; ② /home 是 soft 方式的 NFS 挂载,宿主机 192.168.31.249 不可达时读写家目录会报 I/O 错误 (不会像 hard 那样把登录卡死);排障顺序是先看 findmnt -o SOURCE,OPTIONS /home 的源与选项, 再看宿主机 sudo exportfs -v。

4.8 环境模块(Lmod)使用

集群用 Lmod 管理 EDA 工具的环境,采用"工具家族分层":先加载家族,才看得到该家族下的工具。

家族入口 加载后可见的工具树
cadence /opt/modulefiles/cadence 下的 Cadence 工具
synopsys /opt/modulefiles/synopsys 下的 Synopsys 工具
siemens /opt/modulefiles/siemens 下的 Siemens 工具
pdk /opt/modulefiles/pdk 下的工艺库
slurm 集群 Slurm 命令(sinfo / squeue / sbatch …)
module avail                     # 只显示当前环境可见的模块
module spider vcs                # 全层级搜索(avail 看不到时用它)
module load synopsys             # 先加载家族
module avail                     # 此时出现 vcs/2023.12 等
module load vcs/2023.12          # 再加载具体工具
module show vcs/2023.12          # 只看它会设哪些变量,不实际加载
module -t list                   # 当前已加载的模块
module purge                     # 清空

作业脚本的标准写法(关键:作业脚本是非 login shell,module 函数默认不存在):

#!/bin/bash
#SBATCH -J sim -N 1 -o /home/%u/sim_%j.out
source /etc/profile.d/zzz_site_lmod.sh     # 必须:一行即可拿到 module 命令
module load synopsys/vcs/2023.12           # 生产脚本写全版本号,保证可复现
vcs -full64 ...

三条使用约定:

  1. 生产脚本必须写全版本号(vcs/2023.12 而非 vcs)—— 不写版本会跟随系统默认变化,破坏可复现性
  2. 不要写 module load xxx | head 之类:管道会让 module 在子 shell 中执行,加载静默失效
  3. 同族工具不能同时加载:加载 cadence 会自动替换掉 synopsys(Lmod 会给出提示); pdk 与工具不同族,可以共存

csh/tcsh 用户(集群 LDAP 默认 loginShell 是 /bin/csh)

csh 的登录入口是 /etc/csh.login,它只加载 /etc/profile.d/*.csh,不读 *.sh。 站点侧因此另有一份 zzz_site_lmod.csh(九台均就位,2026-09-27 变更 lmod_csh_profile_20260927 补齐):

# csh 登录视角(务必 env -i 清环境:sshd 会话自带 BASH_ENV 与站点 MODULEPATH,不清会假通过)
ssh root@192.168.31.28 "env -i HOME=/root USER=root PATH=/usr/bin:/bin /bin/csh \
  -c 'source /etc/csh.login >& /dev/null; echo \$MODULEPATH'"
#    预期:首项为 /opt/modulefiles/Core

# 真实用户视角
ssh root@192.168.31.28 'su - rain01 -c "module -t avail"'
#    预期:cadence / pdk / siemens / site / slurm/26.05.2 / synopsys

csh 作业脚本(非 login shell)同样首行 source /etc/profile.d/zzz_site_lmod.csh —— 该文件第一步会自行 source /etc/profile.d/modules.csh 取得 module 命令。

症状:csh 用户 module avail 只剩 lmod / settarg(家族入口全不可见)。 先查九台 /etc/profile.d/zzz_site_lmod.csh 是否存在、SHA256 是否一致, 处置与重下发见 lmod_csh_profile_20260927/docs/SOP.md 第 5–7 章。

维护侧:模块内容来自共享目录 /opt/modulefiles(宿主机 NFS),由部署器生成,不要手工编辑。 新增或调整工具模块时,改 config/slurm_deploy.yaml 的 module_env.families 后重跑:

cd /home/rain/Documents/slurm_ins
.venv/bin/python main.py \
  --config config/slurm_deploy.yaml --module-env

工具本体尚未安装时,module load 会明确报错"工具尚未安装或路径待配置:/opt/eda/...", 而不是静默加载成功 —— 看到该提示说明 install_dir 还没填成真实路径。

4.9 本地 scratch(/local_scratch)

计算节点各有一块 50G 独立虚拟盘挂载在 /local_scratch(xfs,noatime),用于作业本地临时数据, 不备份、易失,用于卸载共享文件系统(NFS / Lustre)的元数据压力。 作业环境变量由 /etc/profile.d/eda_scratch.sh 提供(导出 LOCAL_SCRATCH、TMPDIR)。

# 查看挂载与容量(单节点)
ssh root@192.168.31.18 "df -h /local_scratch | tail -1; findmnt -no SOURCE,OPTIONS /local_scratch"
#    预期:/dev/vdb 50G 挂到 /local_scratch,参数含 noatime

# 三台一起看
for h in 18 19 20; do echo -n ".$h: "; ssh root@192.168.31.$h "df -h /local_scratch | tail -1"; done

# 查看作业环境片段
ssh root@192.168.31.18 "cat /etc/profile.d/eda_scratch.sh"
#    预期:LOCAL_SCRATCH_ROOT / LOCAL_SCRATCH / TMPDIR 三行

# 修复/重装(幂等:已就绪则零变更、全跳过)
.venv/bin/python main.py --config config/slurm_deploy.yaml --local-scratch

# 卸载(卸挂载 + 移 fstab 条目 + 删 profile 与空目录 + 卸虚盘;盘文件保留)
.venv/bin/python main.py --config config/slurm_deploy.yaml --local-scratch --rollback

⚠️ 三条约束: ① 格式化不可逆——安装时对空盘执行 mkfs.xfs,目标设备由宿主 virsh XML 的 target dev 推导, 不依赖固定盘名;推导失败即拒绝执行。 ② 宿主需 sudo 免密——qemu-img / virsh 需在 /kvm 下操作。 ③ 宿主 ssd-pool 空间超卖——三块盘名义 150G > 实测可用 111–133G(qcow2 稀疏,按写入增长); 写满会 ENOSPC 并影响同盘其它虚机,需留意宿主 df -h /。

另注:profile.d 只对登录 shell 生效;sbatch 提交的脚本是非 login shell, 需在脚本首行 source /etc/profile.d/eda_scratch.sh,或后续由 TaskProlog 注入(尚未实施)。

4.10 EDA 共享存储(/projects、/tools、/pdk、Tier0 scratch)

三台计算节点各挂载三个 NFS 共享目录,构成 EDA 工具 / 项目 / 工艺库的统一视图; Tier0 的 Lustre 上已建标准 scratch 结构。

挂载点 来源 挂载参数 权限与用途
/projects 192.168.31.249:/data/nfs/projects rw,hard,timeo=600,retrans=2,noatime,actimeo=30,_netdev 按 LDAP 8 组,2775 root:<组>;项目工作区
/tools 192.168.31.249:/data/nfs/tools ro,hard,timeo=600,retrans=2,noatime,actimeo=30,_netdev 755 root:root(宿主侧设);工具安装,空壳待填
/pdk 192.168.31.249:/data/nfs/pdk 同 /tools 755 root:root(宿主侧设);工艺库,空壳待填
/mnt/lustre/scratch Lustre edafs defaults,noatime,nofail users/projects 默认、tmp 1777;跨节点临时数据
# 查看三台的挂载与读写性
for h in 18 19 20; do echo "[.$h]"; ssh root@192.168.31.$h \
  'for mp in /projects /tools /pdk; do printf "%-11s " $mp; findmnt -no OPTIONS -M $mp | cut -d, -f1; done
   touch /projects/.w 2>/dev/null && echo "可写" && rm -f /projects/.w || echo "不可写"'; done
#    预期:/projects rw 可写;/tools、/pdk ro

# 查看按组权限(应 8 个目录,drwxrwsr-x root <组>)
ssh root@192.168.31.18 "ls -l /projects"

# 查看 Tier0 scratch
ssh root@192.168.31.18 "ls -1 /mnt/lustre/scratch; findmnt -no OPTIONS -M /mnt/lustre | grep -o noatime"

# 修复/重装(幂等:已就绪则零变更、全跳过)
.venv/bin/python main.py --config config/slurm_deploy.yaml --storage-layout

# 卸载(卸挂载 + 移 fstab + 撤销宿主导出;不删数据)
.venv/bin/python main.py --config config/slurm_deploy.yaml --storage-layout --rollback

⚠️ 三条注意: ① /tools、/pdk 是只读挂载,其属主与权限只能在宿主机(/data/nfs/tools 等)设置, 在客户端执行 chown 会报 Read-only file system; ② 导出用 exportfs -o 单条追加——宿主 NFS 与 k8s 共用,禁止 exportfs -ra 全量重载(会瞬时打断 k8s PVC); ③ NFS 的 ro/rw 无法用 mount -o remount 修正,参数不符须卸载重挂。

工具体积大,就位时请装到 /tools/<厂商>/<工具>/<版本>,并同步改 modulefile 的 install_dir。

4.11 scratch 生命周期清理(/local_scratch 与 Lustre scratch)

机制(三层互补,2026-09-24 上线):

层 触发时机 行为
TaskProlog 作业步启动 注入 LOCAL_SCRATCH 与 TMPDIR=/local_scratch/users/<user>/<jobid>,并建该目录
Epilog 作业结束 成功(退出码 0)→ 删除本作业目录;失败 → 改名 <jobid>.failed.<ts> 保留现场
systemd timer 每日 03:30(随机延迟 30m) 清理本地 >7 天、Lustre >30 天的超期目录

速查:

# timer 状态与下次触发时间
ssh root@192.168.31.18 "systemctl is-enabled slurm-scratch-gc.timer; systemctl is-active slurm-scratch-gc.timer"
ssh root@192.168.31.18 "systemctl list-timers slurm-scratch-gc.timer --no-pager"   # 预期 NEXT 为次日 03:xx

# 清理日志
ssh root@192.168.31.18 "tail -20 /var/log/slurm/scratch_gc.log"   # 老化清理(timer)
ssh root@192.168.31.18 "tail -20 /var/log/slurm/epilog.log"       # 作业结束时(Epilog)

# 看谁在占本地盘
ssh root@192.168.31.18 "du -sh /local_scratch/users/* 2>/dev/null | sort -h | tail -10"

# 手工触发老化清理:先干跑审阅,再实跑
ssh root@192.168.31.18 "/usr/local/slurm/slurm-scratch-gc.sh --dry-run"   # 只列出待清目录,不删
ssh root@192.168.31.18 "/usr/local/slurm/slurm-scratch-gc.sh"             # 实际清理

作业脚本范例(推荐写法,自清更即时):

#!/bin/bash
#SBATCH -J sim
trap 'rm -rf -- "${TMPDIR:-}"' EXIT      # TMPDIR 由 TaskProlog 自动注入
echo "TMPDIR=$TMPDIR"
# 注意:EDA 编译产物默认落在 cwd,不在 $TMPDIR —— 需 cd 到 $TMPDIR,或用 -Mdir 显式指定

保留期与执行时刻:配置在 config/slurm_deploy.yaml 的 scratch_gc 段 (local_retention_days / lustre_retention_days / on_calendar)。改后执行 .venv/bin/python main.py --config config/slurm_deploy.yaml --scratch-gc 生效,无需停服。

保护非作业目录(清理排除):老化规则按 depth 匹配目录,会把「非 jobid 命名」的长期目录 一并当作超期作业目录整棵删除。要让某目录豁免,登记到 scratch_gc.exclude_patterns.<层> —— 相对各层根路径的 glob,别以 / 开头,只允许字母数字与 _ . / * -(validate() 会拦非法值)。 例:保护 EDA 仿真在 /mnt/lustre/scratch/users/<用户>/ 下自建的长期目录

exclude_patterns:
  local: []
  lustre:
    - "users/*/virtuoso"        # 相对 /mnt/lustre/scratch

改后同样跑一次 --scratch-gc 下发,再干跑核对 —— 被排除目录不应出现在清单里, 日志会打印本次生效的排除规则条数(OK <层>: 无超期目录(>=N天)于 <root>(排除 M 条规则)):

ssh root@192.168.31.18 "grep -n 'not -path' /usr/local/slurm/slurm-scratch-gc.sh"   # 确认规则已渲染
ssh root@192.168.31.18 "/usr/local/slurm/slurm-scratch-gc.sh --dry-run"             # 清单里不应出现被排除目录

手工删除某用户 scratch(⚠️ 高危:删除不可恢复。先看清单,再明确到具体目录删除):

ssh root@192.168.31.18 "ls -la /local_scratch/users/<user>/"                       # 先看
ssh root@192.168.31.18 "rm -rf -- /local_scratch/users/<user>/<jobid>"             # 再删(禁止通配扩大范围)

故障:作业结束后目录未清理、或节点变 drain → 见第八章「场景 I」。

4.12 作业提交节点(hpc-submit)

是什么:hpc-submit(192.168.31.28)是集群的专用作业提交入口,2026-09-25 由 --submit-node 纳管。它只装客户端能力,不跑任何 Slurm daemon、不承载作业。

装了 不装
Slurm 客户端命令(sinfo/squeue/sbatch/srun,来自控制节点分发的产物) slurmd / slurmctld / slurmdbd 服务
munged + 与集群一致的 munge key Lustre(/mnt/lustre)
LDAP 认证(sssd + authselect),su - <用户> 可用 本地 scratch(/local_scratch)、作业钩子的执行环境(无 slurmd,/etc/slurm/task_prolog_lmod.sh 随 Lmod 站点文件一并写入但不会被调用)
共享盘:/home、/opt/modulefiles、/projects、/tools、/pdk 健康检查程序(HealthCheck 只在计算节点跑)

速查:

# 就绪检查:munge 运行 + 5 处共享盘挂载
ssh root@192.168.31.28 "systemctl is-active munge; findmnt -rno TARGET,SOURCE -t nfs,nfs4 | sort"
#    预期:active;5 行(/home /opt/modulefiles /projects /tools /pdk),源均为 192.168.31.249:/data/nfs/*

# 从提交节点查集群(LDAP 用户视角,走 bash 登录 shell 以加载 PATH 与配置源)
ssh root@192.168.31.28 'su - cy01 -s /bin/bash -c "sinfo -h -o \"%P %N %T\"; squeue -h -o \"%i %u\" | head"'

# 提交节点的配置来源(configless)
ssh root@192.168.31.28 "cat /etc/profile.d/slurm_configless.sh"
#    预期:export SLURM_CONF_SERVER=slurm-master-01:6817,slurm-master-02:6817

# 修复 / 重装(幂等:已就绪则零变更、全跳过;不重启集群任何服务)
.venv/bin/python main.py --config config/slurm_deploy.yaml --submit-node

# 预演(只看清单不改动)
.venv/bin/python main.py --config config/slurm_deploy.yaml --submit-node --dry-run

# 卸载该提交节点(卸挂载 + 移除认证与 PATH 配置 + 摘 symlink + 重建 /etc/hosts 块;不删数据)
.venv/bin/python main.py --config config/slurm_deploy.yaml --submit-node --rollback

# 日志
tail -50 logs/slurm_submit_node.log          # 执行日志(工程根目录下)

要点与坑:

  • configless 取配置:该节点无 slurmd,靠环境变量 SLURM_CONF_SERVER 让客户端命令向控制节点取配置。 登录 shell 自动带上(/etc/profile.d/slurm_configless.sh);脚本或非登录 shell 里需显式设置, 否则报找不到配置。
  • LDAP 用户 loginShell 是 /bin/csh:csh 不读 /etc/profile.d/*.sh,因此 su - <用户> 之后 sinfo 不在 PATH —— 这与计算节点行为完全一致(slurm-work-01 实测同样如此),不是本节点缺陷。 需要命令时用 su - <用户> -s /bin/bash -c "...",或用绝对路径 /usr/local/slurm/bin/sinfo。
  • 其它子命令也会覆盖这个节点:--node-env、--module-env 的目标集合天然包含 submit 组; --storage-layout 通过 storage_layout.node_groups 包含它(本轮未实跑这两条路径,按代码路径推定)。 区别在于 --module-env 会重启计算节点的 slurmd(执行前 squeue 必须为空),而 --submit-node 不碰任何 daemon。
  • 节点清单变化:新增/删除提交节点 = 改 config/slurm_deploy.yaml 的 nodes.submit,再跑一次 --submit-node(新增)或 --submit-node --rollback + 从 yaml 删除(下线)。
  • 主机名必须先改对:pre_check 会比对目标机 hostnamectl --static 与 yaml 的 hostname, 不一致直接中止(避免把配置写到错的机器上)。
  • 镜像源:该节点的 Rocky/EPEL 源已改指 mirrors.aliyun.com(原配置备份在 /root/yum.repos.d.bak.20260925-014652);官方 mirrorlist 在本网络实测仅 ~1 KB/s,会导致装包超时。
  • 回滚不删数据:共享盘内容与 /usr/local/slurm-26.05 产物目录保留,需人工确认后清理; 备份台账见 submit_node_onboarding/backup/README.md。

五、配置管理

配置项位置

文件 位置 说明
部署配置(唯一事实源) config/slurm_deploy.yaml 节点、开关、DB、QoS 定义都在这里
特殊配置模板 slurm_conf_old/ slurm.conf / slurmdbd.conf / cgroup.conf / topology.conf 模板与 pro_epilog/*.sh
集群实际配置 {安装目录}/etc/*.conf(symlink 为 /usr/local/slurm/etc/) 由部署器生成,禁止手工编辑:下次部署会按模板重写

修改流程

# 1. 改部署配置或模板(不要直接改集群上的 /usr/local/slurm/etc/slurm.conf)
vi config/slurm_deploy.yaml

# 2. 先预演确认变更清单
cd /home/rain/Documents/slurm_ins
.venv/bin/python main.py \
  --config config/slurm_deploy.yaml --dry-run

# 3. 执行(实现体先备份、再变更)
.venv/bin/python main.py \
  --config config/slurm_deploy.yaml

生效方式

改动类型 生效方式
slurm.conf 参数(多数) 部署器会重启服务;也可手工 scontrol reconfigure(不重启进程)
HealthCheckProgram 等 slurmd 侧参数 需重启 slurmd
systemd 单元 systemctl daemon-reload + 重启对应服务
分区 / QoS / 账户 scontrol reconfigure 或 sacctmgr 直接修改

换用另一套模板(迁移到新集群时)

slurm_conf_old/ 是从某个旧集群导出的配置模板。换用其它集群导出的模板时,旧主机名/IP/安装路径 不需要手工改写——部署器会从模板自身提取(ControlMachine/SlurmctldHost、NodeName、PluginDir、 Prolog 路径、全文 IP),并按 yaml 的节点清单重算分区归属。

# 1. 把新模板放到工程内(例如 slurm_conf_prod/)
cp -r <新模板目录> slurm_conf_prod

# 2. 指向新模板(legacy 段全部留空,即自动提取)
vi config/slurm_deploy.yaml
#   slurm.custom_config.source_dir: "slurm_conf_prod"
#   slurm.custom_config.legacy:  全部留空

# 3. 预演,重点看日志里打印的“旧环境标识”是否符合预期
.venv/bin/python main.py \
  --config config/slurm_deploy.yaml --dry-run
#    预期日志:特殊配置模板的旧环境标识: 控制节点=[...] 计算节点=[...] 安装目录=... 前缀=...

若自动提取结果不符合预期(例如模板里有同名相似前缀的其它设备名),在 custom_config.legacy 中显式列出即可覆盖:

    legacy:
      control_hosts: ["prod-ctl-01", "prod-ctl-02"]
      compute_hosts: ["prod-cmp-01", "prod-cmp-02"]
      ips: ["192.168.0.2"]
      install_dir: "/opt/slurm-24.11"
      prefix: "/opt/slurm"

分区归属规则:模板里某分区的 Nodes= 若覆盖了模板定义的全部计算节点,则视为"该分区全量", 替换为当前 yaml 的全部计算节点;若只覆盖一部分,则保持子集语义。yaml 的 partitions[] 中同名分区 若显式写了 nodes,优先级最高。

环境校验开关

配置 作用 默认
os_check pre_check 校验目标机发行版(/etc/os-release 的 ID/ID_LIKE)、主版本、架构;不匹配直接报错退出,不进装包阶段 启用,接受 RHEL 系 9.x + x86_64
auto_detect 计算节点 cpus/memory_mb 留空时按真机探测;memory_ratio 控制 RealMemory 占物理内存比例 启用,比例 0.95
# 探测结果会打印在 pre_check 阶段
.venv/bin/python main.py \
  --config config/slurm_deploy.yaml --dry-run 2>&1 | grep -A3 "探测"
# 预期:slurm-work-0x: CPUs=8 RealMemory=14944MB (物理 15730MB × 0.95)

特殊场景(如目标为 Rocky 8、aarch64)需改 os_check 后再执行;关掉它则这些检查全部跳过。

易错点

  1. 不要手工改 /usr/local/slurm/etc/ 下的文件——它是 symlink 指向版本化目录,下次部署会被覆盖;改动请落到模板或 yaml。
  2. QoS 必须先于 PartitionName 存在,否则 slurmctld 启动即 fatal。新增分区引用新 QoS 时,先在 sacctmgr 建 QoS。
  3. AccountingStorageEnforce=associations 意味着未注册的用户/账户无法提交作业;新用户需先 sacctmgr add user。
  4. 机器名改动:/etc/hosts 的集群段由部署器维护(# BEGIN slurm-deploy 标记),不要手工编辑该段。
  5. cgroup v2:slurmd.service 必须保持 Type=notify 与 --systemd -s,改动会导致作业无法启动。

六、备份与恢复

备份策略

内容 位置 产生方式
DB 全量 dump /var/backups/slurm/db_slurm_acct_db_<ts>.sql.gz 每次执行部署时自动
旧安装目录 /var/backups/slurm/slurm-<ver>_bak_<ts>.tar.gz 检测到版本变更时自动
配置文件 /var/backups/slurm/<文件名>.bak.<ts> 每次写配置前自动
宿主机 /etc/exports docs/backup/etc/exports.bak.* 本次变更前手工备份
节点 NSS/PAM/挂载配置 /var/backups/slurm/node_env_<ts>/(内含 _etc_nsswitch.conf、_etc_pam.d、_etc_fstab、_etc_sssd_sssd.conf) 安装节点基础环境前自动 cp -a

完整台账(用途与何时可删)见 docs/backup/README.md。

手工备份

# 备份数据库
ssh root@192.168.31.16 "mysqldump --defaults-extra-file=<临时cnf> \
  --single-transaction --quick slurm_acct_db | gzip \
  > /var/backups/slurm/db_slurm_acct_db_$(date +%Y%m%d_%H%M%S).sql.gz"

# 备份配置与 state
ssh root@192.168.31.16 "tar czf /var/backups/slurm/manual_$(date +%Y%m%d_%H%M%S).tar.gz \
  /usr/local/slurm-26.05/etc /etc/systemd/system/slurmctld.service"

恢复步骤

# 1. 数据库恢复
systemctl stop slurmdbd                                             # 高危:停服
gunzip < /var/backups/slurm/db_slurm_acct_db_<ts>.sql.gz | \
  mysql -h 192.168.31.10 -u slurm -p slurm_acct_db
systemctl start slurmdbd

# 2. 配置恢复
cp /var/backups/slurm/slurm.conf.bak.<ts> /usr/local/slurm-26.05/etc/slurm.conf
systemctl restart slurmctld && scontrol reconfigure

# 3. 验证
/usr/local/slurm/bin/scontrol ping                    # 预期主备均 UP
/usr/local/slurm/bin/sacct -S today | head            # 预期能看到历史作业

演练记录

日期 内容 结果
2026-09-18 部署过程实际触发过目录 tar 备份与配置 .bak,--rollback 路径未做真实演练 建议补一次演练

七、监控与告警

关键指标与查看入口

指标 命令 正常范围
节点状态 sinfo -N -o '%N %T' 全部 idle 或 alloc,无 drain/down
主备存活 scontrol ping 两行均 is UP
队列积压 squeue -h \| wc -l 与业务预期比对,突增需排查
共享存储写入延迟 见下方 dd 命令 ≤ 50ms(基线 9–12ms)
控制器内存 systemctl status slurmctld \| grep Memory 无明显持续增长
健康巡检 systemctl is-active slurm-cluster-health.timer active

需要重点盯的日志与告警

关键词 含义 处置
Saving to StateSaveLocation took 共享存储写入变慢 见 场景 F
Nodes ... not responding 计算节点失联 见 场景 A
error: socket ... refused / Auth failure munge 认证异常 见 场景 D
DRAIN / Node unexpectedly rebooted 节点被排空 见 场景 A
cannot create cgroup context cgroup v2 配置异常 见 场景 C
# 共享存储写入延迟自查(在 .16 执行)
cd /mnt/slurm-shared && for i in 1 2 3; do
  s=$(date +%s%N); dd if=/dev/zero of=./iotest bs=4k count=20 conv=fsync status=none
  e=$(date +%s%N); echo "第$i 次: $(( (e-s)/1000000 )) ms"; done; rm -f ./iotest
# 预期 9–12 ms;若 > 200ms 需按场景 F 排查

已配置的自动自愈

slurm-cluster-health.timer 每 15 分钟执行一次巡检(cluster_health_check.py --fix),它会:

  • 检查 slurmctld/slurmd 是否在运行,不在则尝试拉起
  • 扫描 sinfo 中非 idle/alloc 的节点并尝试 Drain → RESUME 恢复
  • 跳过有作业的节点(避免误伤业务)
  • 异常节点 ≤3 个时先等待 5 秒复检(防抖)

手工触发一次(排查用):

/usr/bin/python3 /usr/local/bin/cluster_health_check.py --status    # 只报告不改动
/usr/bin/python3 /usr/local/bin/cluster_health_check.py --fix       # 检查并尝试恢复

八、故障处置

场景 A:计算节点变为 drain 或 down

症状:sinfo -N -o '%N %T' 中出现 drain、down 或 draining;用户报"作业一直排队但不执行"。

诊断

# 1. 看节点具体原因
/usr/local/slurm/bin/sinfo -R -o '%N %T %E'          # 预期 %E 列给出 DRAIN 原因
# 2. 看该节点 slurmd 是否在跑(在故障节点上执行)
sudo ssh root@192.168.31.19 "systemctl is-active slurmd"     # 预期 active
# 3. 看 slurmd 日志
sudo ssh root@192.168.31.19 "journalctl -u slurmd -n 50 --no-pager | grep -iE 'error|fatal'"
# 4. 看是否被 HealthCheck 判定不健康
sudo ssh root@192.168.31.19 "bash /usr/local/bin/slurm_health_check.sh; echo exit=\$?"
#    预期 exit=0;非 0 时脚本会打印具体失败项(磁盘/内存/munge/目录可写)

处置

# a) 若原因为磁盘满:清理或扩容后恢复
ssh root@192.168.31.19 "df -h /"                     # 找到写满的分区
#    处理完成后:
/usr/local/slurm/bin/scontrol update NodeName=slurm-work-02 State=RESUME

# b) 若 slurmd 未运行
ssh root@192.168.31.19 "systemctl restart slurmd && systemctl is-active slurmd"

# c) 若节点失联(降级为 down),确认节点恢复后再
/usr/local/slurm/bin/scontrol update NodeName=slurm-work-02 State=RESUME

验证

/usr/local/slurm/bin/sinfo -N -o '%N %T' | grep slurm-work-02       # 预期 idle
/usr/local/slurm/bin/scontrol show node slurm-work-02 | grep -E 'State|Reason'   # 预期无 Reason

若同一节点反复被 DRAIN,先解决根因再恢复(巡检脚本会在 15 分钟内自动尝试一次)。

场景 B:主控切换 / 主控不可用

症状:scontrol ping 只有 backup 响应或报错;用户报"提交作业报 Unable to contact slurm controller"。

诊断

# 1. 看主备状态
/usr/local/slurm/bin/scontrol ping
#    预期(正常):Slurmctld(primary) at slurm-master-01 is UP / (backup) at slurm-master-02 is UP
# 2. 看主控服务(在 .16)
ssh root@192.168.31.16 "systemctl is-active slurmctld; journalctl -u slurmctld -n 30 --no-pager | grep -iE 'error|fatal'"
# 3. 看共享存储是否掉线(主控依赖它读写 state)
ssh root@192.168.31.16 "findmnt /mnt/slurm-shared"   # 预期 nfs4 挂载存在
# 4. 确认备控是否已接管
ssh root@192.168.31.17 "systemctl is-active slurmctld"

处置

# a) 共享存储掉线(最常见):先恢复 NFS,再重启主控
ssh root@192.168.31.16 "systemctl stop slurmctld; mount /mnt/slurm-shared; systemctl start slurmctld"
#    /etc/fstab 已有条目且带 _netdev,可直接 mount

# b) 主控服务异常退出
ssh root@192.168.31.16 "systemctl restart slurmctld"

# c) 主控整机不可用:备控会在一分钟内自动接管,此时无需干预;
#    待 .16 恢复后再确认它作为 backup 回归(Slurm 的 primary 身份由配置文件顺序决定)

验证

/usr/local/slurm/bin/scontrol ping                    # 两行均 UP(或备控已在提供服务)
/usr/local/slurm/bin/sinfo | head                     # 能正常输出分区
/usr/local/slurm/bin/squeue                           # 队列内容与切换前一致

切换后作业不会丢失(state 在共享存储上);但 slurmdbd 只在 .16 运行,若 .16 整机故障则记账暂不可用,调度仍可继续。

场景 C:作业无法启动

症状:作业一直 PENDING 或启动后立即失败;srun 报 Job step creation failed;日志出现 cannot create cgroup context。

诊断

# 1. 看作业状态与原因
/usr/local/slurm/bin/squeue -o '%i %T %r'             # PENDING 时 %r 给出原因
/usr/local/slurm/bin/scontrol show job <jobid> | grep -E 'JobState|Reason|ExitCode'
# 2. 看失败作业的详情
/usr/local/slurm/bin/sacct -j <jobid> --format=JobID,State,ExitCode,Reason
# 3. 看计算节点 slurmd 日志(cgroup 相关最常见)
ssh root@192.168.31.18 "journalctl -u slurmd --since '10 min ago' --no-pager | grep -iE 'cgroup|error|fatal'"
# 4. 检查关键前提
ssh root@192.168.31.18 "ldd /usr/local/slurm-26.05/lib/slurm/cgroup_v2.so | grep 'not found'"
#    预期无输出(依赖齐全)
ssh root@192.168.31.18 "systemctl show slurmd -p Type -p Delegate | head -3"
#    预期 Type=notify、Delegate=yes

处置

# a) 缺运行库(出现 not found)
#    直接跑一次部署,实现体会自动探测缺失库并安装:
cd /home/rain/Documents/slurm_ins
.venv/bin/python main.py --config config/slurm_deploy.yaml

# b) cgroup 相关:确认单元参数未被改动,必要时重跑部署恢复
ssh root@192.168.31.18 "grep -E 'ExecStart|Type|Delegate' /etc/systemd/system/slurmd.service"
#    预期 ExecStart 含 --systemd -s,Type=notify,Delegate=yes

# c) 因记账校验被拒(QOS/账户不存在)
/usr/local/slurm/bin/sacctmgr -n show assoc user=<用户名>    # 无输出说明用户未注册
/usr/local/slurm/bin/sacctmgr -i add user <用户名> Account=<账户> Cluster=cluster

验证

cd /tmp && printf '#!/bin/bash\nhostname\n' > t.sh
/usr/local/slurm/bin/sbatch -N1 -o /tmp/t_%j.out t.sh
sleep 15 && cat /tmp/t_*.out                          # 预期输出计算节点主机名
/usr/local/slurm/bin/sacct -n -P -o JobID,State,ExitCode --starttime today | tail -1
#    预期 COMPLETED 0:0

场景 D:munge 认证失败

症状:slurmctld/slurmd/slurmdbd 起不来,日志报 Auth failure 或 munged 相关错误; scontrol ping 报认证失败。

诊断

# 1. 看 munged 是否在跑(每个节点都要看)
for ip in 16 17 18 19 20; do echo -n "192.168.31.$ip: "; \
  ssh root@192.168.31.$ip "systemctl is-active munge"; done
#    预期全部 active
# 2. 看 key 是否全节点一致
for ip in 16 17 18 19 20; do echo -n "192.168.31.$ip: "; \
  ssh root@192.168.31.$ip "sha256sum /etc/munge/munge.key | cut -c1-16"; done
#    预期 5 行哈希完全相同
# 3. 看 key 权限(必须是 400,group/world 可读会被 munged 拒绝)
ssh root@192.168.31.16 "ls -l /etc/munge/munge.key"
#    预期:-r-------- 1 munge munge
# 4. 看启动失败原因
ssh root@192.168.31.16 "journalctl -u munge -n 20 --no-pager | tail -5"

处置

# a) 权限不对(报 Keyfile is insecure)
ssh root@192.168.31.16 "chown munge:munge /etc/munge/munge.key && \
  chmod 400 /etc/munge/munge.key && systemctl restart munge"       # 每个异常节点都执行

# b) key 不一致:以主控为源统一分发
#    建议直接重跑部署(实现体会比对哈希并统一下发,同时校正权限)
cd /home/rain/Documents/slurm_ins
.venv/bin/python main.py --config config/slurm_deploy.yaml

验证

ssh root@192.168.31.16 "munge -n | unmunge | grep STATUS"    # 预期 STATUS: Success (0)
/usr/local/slurm/bin/scontrol ping                            # 预期主备均 UP

场景 E:记账数据库不可用

症状:sacct 报错或无数据;新作业提交被拒(Invalid account / Unable to contact slurmdbd); .16 上 slurmdbd 反复重启。

诊断

# 1. 数据库端口是否可达
timeout 4 bash -c 'cat < /dev/null > /dev/tcp/192.168.31.10/3306' && echo OPEN || echo CLOSED
# 2. 看 slurmdbd 服务与日志
ssh root@192.168.31.16 "systemctl is-active slurmdbd"
ssh root@192.168.31.16 "journalctl -u slurmdbd -n 30 --no-pager | grep -iE 'error|fatal|connect'"
# 3. 用应用账号连库验证(密码从 yaml 取,勿明文粘贴)
ssh root@192.168.31.16 "mysql --defaults-extra-file=/tmp/.my.cnf -e 'SELECT 1'"

处置

# a) 数据库 Pod 异常(k8s 侧):先恢复 MariaDB
kubectl -n server get pod mariadb-0                # 预期 1/1 Running
kubectl -n server logs mariadb-0 --tail=50         # 看是否有异常

# b) 数据库恢复后重启 slurmdbd
ssh root@192.168.31.16 "systemctl restart slurmdbd && systemctl is-active slurmdbd"

验证

/usr/local/slurm/bin/sacctmgr -n -i show cluster        # 预期输出 cluster 记录
/usr/local/slurm/bin/sacct -S today | head              # 预期能查到作业记录

场景 F:共享存储写入变慢或不可用

症状:slurmctld 日志高频出现 Saving to StateSaveLocation took <n> ms; 严重时 slurmctld 停止响应、调度中断。

诊断

# 1. 是否已挂载、挂载源是否正确
ssh root@192.168.31.16 "findmnt -o TARGET,SOURCE,FSTYPE /mnt/slurm-shared"
#    预期:/mnt/slurm-shared  192.168.31.249:/data/nfs/slurm-state  nfs4
# 2. 写入延迟
ssh root@192.168.31.16 "cd /mnt/slurm-shared && dd if=/dev/zero of=./iotest bs=4k count=20 conv=fsync status=none && rm -f ./iotest"
#    预期 < 50ms;数百 ms 说明后端变慢
# 3. 宿主机导出是否正常、是否被改回 sync
ssh rain@192.168.31.249 "sudo exportfs -v | grep slurm-state"
#    预期含 (async,...);若为 sync 说明导出被改动
# 4. 主控侧告警频率
ssh root@192.168.31.16 "journalctl -u slurmctld --since '10 min ago' --no-pager | grep -c 'Saving to StateSaveLocation'"

处置

# a) 未挂载:先停主控再挂载(避免状态写入失败)
ssh root@192.168.31.16 "systemctl stop slurmctld && mount /mnt/slurm-shared && systemctl start slurmctld"
ssh root@192.168.31.17 "systemctl restart slurmctld"      # 备控同步恢复

# b) 导出被改回 sync 或丢失:在宿主机补回(高危:改 /etc/exports 前先备份)
ssh rain@192.168.31.249 "sudo cp -a /etc/exports /etc/exports.bak.$(date +%Y%m%d_%H%M%S)"
ssh rain@192.168.31.249 "sudo grep -q slurm-state /etc/exports || \
  sudo sh -c 'printf \"/data/nfs/slurm-state 192.168.31.0/24(rw,async,no_subtree_check,no_root_squash)\\n\" >> /etc/exports'"
ssh rain@192.168.31.249 "sudo exportfs -ra"

验证

ssh root@192.168.31.16 "journalctl -u slurmctld --since '5 min ago' --no-pager | grep -c 'Saving to StateSaveLocation'"
#    预期 0
/usr/local/slurm/bin/scontrol ping                    # 预期主备均 UP

场景 G:LDAP 用户无法登录或家目录异常

症状:su - <用户> 报 user does not exist;或能切换但家目录读不了;或 ssh <用户>@<节点> 认证失败。

诊断(在故障节点上执行)

# 1. NSS 能否解析出用户
ssh root@192.168.31.19 "getent passwd cy01"
#    预期 cy01:*:4001:4000:cy01:/home/cy01:/bin/csh;无输出说明问题在 NSS/sssd
# 2. sssd 与 oddjobd 是否在跑(oddjobd 负责建家目录)
ssh root@192.168.31.19 "systemctl is-active sssd oddjobd"
# 3. authselect 配置是否在位
ssh root@192.168.31.19 "authselect current | head -4"          # 预期 sssd + with-mkhomedir
# 4. sssd 日志
ssh root@192.168.31.19 "journalctl -u sssd --since '10 min ago' --no-pager | grep -iE 'error|fail|denied'"
# 5. 家目录与挂载
ssh root@192.168.31.19 "findmnt -n -o SOURCE /home; ls -ld /home/cy01 2>&1"
# 6. SELinux 与布尔(Enforcing 下必须为 on)
ssh root@192.168.31.19 "getenforce; getsebool use_nfs_home_dirs"

处置

# a) sssd 未运行或配置缺失:重跑部署器补齐(幂等,不重启 Slurm 服务)
cd /home/rain/Documents/slurm_ins
.venv/bin/python main.py \
  --config config/slurm_deploy.yaml --node-env

# b) LDAP 侧刚改过用户(改组/改 shell):清缓存并重启 sssd
ssh root@192.168.31.19 "sss_cache -E && systemctl restart sssd"

# c) 家目录不存在:交给 with-mkhomedir 在下次登录时创建,或按 LDAP 的 uid/gid 手工建
ssh root@192.168.31.19 "mkdir -p /home/cy01 && chown 4001:4000 /home/cy01 && chmod 700 /home/cy01"

# d) 家目录在但读不了:多为 SELinux 布尔或 /home 掉挂载
ssh root@192.168.31.19 "getsebool use_nfs_home_dirs | grep -q 'on' || setsebool -P use_nfs_home_dirs on"
ssh root@192.168.31.19 "findmnt /home >/dev/null || mount /home"

# e) 宿主机导出丢失:补回(高危:改 /etc/exports 前先备份)
ssh rain@192.168.31.249 "sudo cp -a /etc/exports /etc/exports.bak.\$(date +%Y%m%d-%H%M%S)"
ssh rain@192.168.31.249 "sudo grep -q '/data/nfs/home' /etc/exports || \
  sudo sh -c 'printf \"/data/nfs/home 192.168.31.0/24(rw,async,no_subtree_check,no_root_squash)\\n\" >> /etc/exports'"
ssh rain@192.168.31.249 "sudo exportfs -ra"

验证

ssh root@192.168.31.19 "su - cy01 -c 'id -u'"          # 预期 4001
ssh root@192.168.31.19 "findmnt -n -o SOURCE /home"    # 预期 192.168.31.249:/data/nfs/home

场景 H:module 命令或模块加载异常

症状:module: command not found;作业里 module load 报 command not found; module avail 看不到预期模块;module load 报"工具尚未安装或路径待配置"。

诊断

# 1. Lmod 装了吗、module 函数可用吗
ssh root@192.168.31.19 "rpm -q Lmod; bash -lc 'command -v module; module --version 2>&1 | grep -i version'"
# 2. 共享 modulefiles 是否挂载
ssh root@192.168.31.19 "findmnt -o SOURCE,OPTIONS /opt/modulefiles"
# 3. MODULEPATH 是否含系统 Core 路径
ssh root@192.168.31.19 "bash -lc 'echo \$MODULEPATH'"
#    预期以 /opt/modulefiles/Core 开头
# 4. 站点文件是否在位
ssh root@192.168.31.19 "ls -l /etc/profile.d/zzz_site_lmod.sh /etc/lmod/lmod_config.lua /etc/slurm/task_prolog_lmod.sh"
# 5. TaskProlog 是否已接管(控制节点)
ssh root@192.168.31.16 "grep '^TaskProlog=' /usr/local/slurm/etc/slurm.conf"
#    预期 TaskProlog=/etc/slurm/task_prolog_lmod.sh

处置

# a) Lmod 未装或配置缺失:重跑部署器补齐(幂等,不重启 Slurm 服务)
cd /home/rain/Documents/slurm_ins
.venv/bin/python main.py \
  --config config/slurm_deploy.yaml --module-env

# b) module avail 看不到刚加的模块:清 Lmod 的目录扫描缓存
module --ignore_cache avail            # 临时生效
rm -rf ~/.cache/lmod                   # 或彻底清(只影响当前用户)

# c) 作业里找不到 module 命令:确认脚本首行已 source(标准写法见 4.8)
grep -n 'zzz_site_lmod' <作业脚本路径>

# d) 报"工具尚未安装或路径待配置:/opt/eda/...":该工具的 install_dir 仍是占位值
grep -n 'install_dir' config/slurm_deploy.yaml    # 改成真实路径后重跑 --module-env

# e) /opt/modulefiles 未挂载(NFS 侧问题)
ssh root@192.168.31.19 "mount /opt/modulefiles"                 # fstab 已有条目,可直接挂
ssh rain@192.168.31.249 "sudo exportfs -v | grep modulefiles"   # 确认宿主侧导出仍在

验证

ssh root@192.168.31.19 "bash -lc 'module --version 2>&1 | grep -i version; module load slurm && command -v sinfo'"
# 预期:Modules based on Lua: Version 8.7.65 ... 与 /usr/local/slurm/bin/sinfo

场景 I:scratch 未清理,或 Epilog 失败导致节点 drain

症状:作业结束后 /local_scratch/users/<user>/<jobid> 仍存在;或 sinfo 显示节点 drain, journalctl -u slurmd 出现 error: epilog failed: rc:<非 0>。

诊断 1. 看 Epilog 日志尾部。预期每个作业三行:start → purged/kept → done bash ssh root@192.168.31.18 "tail -20 /var/log/slurm/epilog.log" 只有 start 没有 done,说明脚本中途失败(脚本报错或返回非 0)。 2. 看 slurmd 是否报 Epilog 失败 bash ssh root@192.168.31.18 "journalctl -u slurmd --since '-30 min' --no-pager | tail -20" 预期无输出;出现 epilog failed: rc:1 即命中本场景。 3. 用最小环境复现(模拟 slurmd,去掉登录 shell 的变量) bash ssh root@192.168.31.18 "env -i PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin SLURM_JOB_ID=0 SLURM_JOB_USER=root SLURM_JOB_EXIT_CODE=0 bash /usr/local/slurm/epilog_eda.sh; echo EXIT=\$?" 预期 EXIT=0。非 0 说明脚本自身有问题,需按工程模板修复后重新分发。

处置 - 临时止血:在控制节点把 slurm.conf 的 Epilog= 行注释掉,scontrol reconfigure 后新作业 不再触发 Epilog(节点可恢复正常调度);根因修复走工程模板重发,不要手改 /usr/local/slurm/。 - 个别历史残留目录:用 4.11 的手工删除命令处理,或等 timer 老化(本地 7 天 / Lustre 30 天)。 - 节点已 drain:确认 Epilog 修复后执行 scontrol update NodeName=<节点> State=RESUME。

验证

ssh root@192.168.31.16 "/usr/local/slurm/bin/sinfo -N -o '%N %T'"        # 预期全部 idle
ssh root@192.168.31.16 "/usr/local/slurm/bin/sbatch --wrap='echo TMPDIR=\$TMPDIR'"
ssh root@192.168.31.18 "ls -la /local_scratch/users/root/"               # 预期该 jobid 目录已消失

⚠️ 红线:改 epilog_eda.sh 时禁止加 set -u——变量未定义会让 Epilog 返回非 0,直接 导致节点 drain(2026-09-24 实测踩中)。验证钩子脚本必须用 env -i 复现 slurmd 环境, 在登录 shell 下测通不算。

场景 J:作业卡在 X 显示 :80 被占(Cadence ADE-XL 派发链)

症状:上层 ADE-XL 经 Slurm 派发时,ICRP child 反复报 :80 被占 / 建不起会话而卡死; 节点上看似没有 X 进程,而 /tmp/.X11-unix/X80(或 /tmp/.X80-lock、/tmp/clsbd.*)仍在。

诊断 1. 看残留(进节点:/tmp 是节点本地盘、不共享) bash ssh root@192.168.31.18 'ls -la /tmp/.X11-unix/ /tmp/.X80-lock 2>/dev/null; ls /tmp/clsbd.* 2>/dev/null' 2. 判定是否为孤儿(无对应 X 进程才算) bash ssh root@192.168.31.18 'fuser -s /tmp/.X11-unix/X80; echo "fuser_rc=$? (1=无进程占用)"; \ ps -eo pid,user,args | grep -E "X(org|vnc)|cdsVncserver" | grep -v grep' 预期:fuser_rc=1 且无 X 进程 → 判为孤儿;若 fuser_rc=0 或见到 X 进程 → 保留,另查。 3. 看 Epilog 是否已清理(2026-10-05 起脚本第 3 段覆盖此项) bash ssh root@192.168.31.18 'grep -E "stale (X|clsbd)" /var/log/slurm/epilog.log | tail'

处置 - 常规:确认钩子为 844715fc…fea8af 后触发一次清理(幂等,无残留时零动作) bash ssh root@192.168.31.18 'sha256sum /usr/local/slurm/epilog_eda.sh; bash /usr/local/slurm/epilog_eda.sh; echo rc=$?' - 应急手工止血(仅确认无进程占用时) bash ssh root@192.168.31.18 'fuser -s /tmp/.X11-unix/X80 || rm -f -- /tmp/.X11-unix/X80 /tmp/.X80-lock' - 钩子越界或失效:不要手改 /usr/local/slurm/,改源模板 slurm_conf_old/pro_epilog/epilog_eda.sh 后走 .venv/bin/python main.py --config config/slurm_deploy.yaml --scratch-gc 重新下发。

验证

ssh root@192.168.31.18 'ls /tmp/.X11-unix/X[0-9]* 2>/dev/null | wc -l; ls /tmp/clsbd.* 2>/dev/null | wc -l'   # 预期 0 0

⚠️ 红线:删除前必须确认无对应 X 进程;不得在未判定时对 /tmp/.X11-unix/* 做通配删除。 机制说明与根因见 docs/BASELINE.md 第 3 节;本次变更档案见 epilog_xdisplay_cleanup_20261005/SOP.md。

九、安全与权限

账号与权限模型

层 机制
集群内互信 munge key(/etc/munge/munge.key,400 munge:munge,全节点一致)
守护进程身份 slurmctld 以 slurm(uid 64030)运行;slurmd/slurmdbd 以 root 运行
作业隔离 cgroup v2:ConstrainCores=yes、ConstrainRAMSpace=yes
记账准入 AccountingStorageEnforce=associations,qos,limits:未注册用户无法提交
SSH root 免密(部署机 → 5 台)

密钥与证书轮换

# munge key 轮换(高危:会导致集群内认证短暂中断,须停服操作)
systemctl stop slurmd slurmctld slurmdbd                  # 全部节点
rm -f /etc/munge/munge.key && /usr/sbin/mungekey --create  # 主控生成新 key
# 分发到其余 4 台并统一权限,然后按依赖顺序启动
chown munge:munge /etc/munge/munge.key && chmod 400 /etc/munge/munge.key
systemctl start munge && systemctl start slurmdbd slurmctld slurmd

实际轮换建议直接改 slurm_deploy.yaml 后重跑部署(实现体会比对哈希并统一下发)。

访问控制

  • slurm.conf 中的分区与 QoS 限制作业的资源与时长上限
  • QoS 定义:interactive(4h,高优先级)、regression(8h)、normal(24h)、long(72h,可被抢占)
  • 账户层级:以 LDAP 为唯一来源,四个部门账户 frontend / analog / it / backend, 其下为小组账户(design/dv/custom/layout/cad/sre/pnr/signoff); 另保留管理账户 root 供 root 提交作业。原按"工种"划分的 EDA 账户已于 2026-09-20 移除, 详见 4.4

十、容量与性能

当前水位基线

项 数值
计算节点 3 台 × 8 核 = 24 核可分配
内存 3 台 × 15000MB = 45GB 可分配
共享存储写入延迟 9–12ms(fsync 4K×20)
数据库 slurm_acct_db,MariaDB 12.3.3(k8s Pod)
控制器 4C/3G,StateSaveLocation 在 NFS

扩容触发条件与操作

触发条件 操作
队列长期积压(squeue -h \| wc -l 持续增长) 按 4.3 增加计算节点
分区内作业因 MaxWall 被拒 调整 QoS 的 MaxWall(sacctmgr -i modify qos <name> set MaxWall=...)
共享存储写入延迟 > 200ms 见 场景 F
slurmctld 内存持续增长 检查 state 规模与作业数量,必要时重启主控(不影响运行中作业)

已知瓶颈

  1. slurmdbd 单点(仅 .16):.16 整机故障时记账不可用。如需消除,需扩展 DBD 双活。
  2. 共享存储为单台宿主机(192.168.31.249):宿主机故障会导致主控无法读写 state,调度中断。
  3. 控制器规格偏小(主控 4C/3G、备控 2C/1G):大规模作业(数千并发)时可能成为瓶颈。

十一、附录

术语表

术语 含义
SlurmctldHost 控制器主机,配置文件中第一条为 primary,其余为 backup
StateSaveLocation 控制器状态目录,主备共享,本环境为 NFS 上的 /mnt/slurm-shared/slurmctld-state
configless 计算节点不存配置,启动时从 slurmctld 拉取(--conf-server)
DRAIN 节点被排空:不再接受新作业,已运行的作业继续
Prolog / Epilog 作业或步骤执行前后的钩子脚本
QoS 服务质量等级,约束作业优先级、时限与并发
TRES 可记账资源类型(cpu/mem/license 等)
cgroup v2 内核统一控制组,Slurm 用它做作业的 CPU/内存隔离

相关文档与交付物

文件 用途
docs/SOP.md 本次变更的实施、验证与回滚
docs/INCIDENT-20260918-slurm-26.05部署排障.md 本次排障台账与复盘
docs/backup/README.md 备份台账
docs/troubleshoot.md 历史排障记录
slurm_health_ensure/SLURM_HEALTHCHECK_STANDARD_SOP.md 健康保障原始设计文档

修订记录

日期 修改人 变更内容
2026-09-18 部署执行人 首版:服务概览、日常操作、六类故障场景、容量基线
2026-09-18 部署执行人 补充「换用另一套模板」流程与分区归属规则
2026-09-20 部署执行人 补充 os_check 与 auto_detect 开关说明;扩缩容支持留空规格
2026-09-20 部署执行人 新增「用户与账户同步(LDAP)」章节:账户层级、手工触发、入离职处理
2026-09-21 部署执行人 新增「节点基础环境」:命令 PATH(可直接用 sinfo)、LDAP 用户(su - <用户> / ssh)、共享家目录(/home 走 NFS);补充场景 G 与相关速查项
2026-09-21 部署执行人 /home 改为 soft 挂载(宿主机故障时报 I/O 错误而非卡死登录);修正第九章账户层级与 4.7 的挂载说明
2026-09-22 部署执行人 新增「环境模块(Lmod)使用」章节与场景 H;速查表补 module 相关条目;服务概览与外部依赖补 Lmod 与共享 modulefiles
2026-09-24 部署执行人 新增 4.11「scratch 生命周期清理」章节与场景 I(Epilog 失败致节点 drain);补充红线:Epilog 脚本禁用 set -u
2026-10-05 部署执行人 新增场景 J(作业卡在 X 显示 :80 被占:孤儿 X socket / clsbd 残留的判定、清理与红线);对应 Epilog 第 3 段清理能力

来源:/home/rain/Documents/slurm/slurm_ins/docs/RUNBOOK.md | 最后更新:2026-10-07 03:37(由 build/sync.py 同步,请勿在站点侧修改)