在高性能计算(HPC)领域,Slurm 几乎是绕不开的一个名字。无论你是在给实验室搭一套几十个节点的 GPU 集群,还是帮学校/单位建设正式的 HPC 平台,Slurm(Simple Linux Utility for Resource Management)都是当前最主流的开源作业调度系统。很多朋友第一次接触 Slurm,看到一堆节点概念——控制节点、计算节点、登录节点、存储节点——容易一头雾水,资料东拼西凑,搭到一半就卡住。
这篇内容我想聊的,就是一套完整的 Slurm 集群构建实战方案。我会把四个核心角色(控制 / 计算 / 登录 / 存储节点)逐一拆开讲,覆盖从硬件规划、基础环境、共享存储、MUNGE 认证、slurmctld/slurmd 配置,到计算节点加入和作业提交测试的完整流程。文章适合两类人:一是从来没搭过集群、想从零上手 HPC 调度的运维新手;二是已经在用别的调度器、想平滑迁移到 Slurm 的工程师。我会把常见问题和排障思路也一起放进来,尽量让你照着操作就能跑通。
1. 整体架构设计与节点规划
1.1 为什么 Slurm 集群要拆成四类节点
先理解一个朴素的问题:为什么不把控制、计算、登录、存储全部塞进同一台机器里?对于跑hostname都嫌多的玩具环境,这样做确实可以,但一旦作业规模上来,问题立刻暴露。
计算节点需要把 CPU、内存和 GPU 绝大部分资源都让给作业使用,如果同时跑着调度服务、文件服务、用户登录进程,资源被抢占是小事,更麻烦的是互相干扰:某个用户跑了个top卡住,或者文件服务把磁盘 IO 打满,都会直接拖垮正在运行的作业,甚至让调度器无响应。
所以四类节点的职责边界很清晰:
- 控制节点(slurmctld):运行 Slurm 主控服务,负责记录节点状态、管理作业队列、做出调度决策。
- 计算节点(slurmd):运行 Slurm 计算代理服务,接收控制节点下发的作业,真正执行计算任务。
- 登录节点(login):用户接入集群的入口,在这里提交作业、查看结果,不承担计算任务。
- 存储节点(storage):统一提供共享文件系统,保证用户在任意计算节点上都能读到自己的数据和软件。
1.2 硬件规划参考与网络设计
我做过的项目中,一个入门级的小型集群通常长这样(以 5 个计算节点为例):
| 节点角色 | 主机名示例 | 建议硬件配置 | 关键软件 |
|---|---|---|---|
| 控制节点 | slurmctl | 4C8G,SSD 100GB | slurmctld, slurmdbd, MariaDB, munge |
| 登录节点 | slurm-login | 8C16G,SSD 200GB | Slurm 客户端工具, pam_slurm |
| 计算节点 | slurm-node[01-05] | 按实际算力需求,16C64G 起 | slurmd, munge |
| 存储节点 | slurm-storage | 机械盘按容量,SSD 做读写缓存 | NFS / BeeGFS / Lustre |
网络方面,小规模集群至少需要一张管理网络(通常千兆即可,负责节点通信、NFS 挂载、SSH 登录);如果涉及并行计算(MPI 跨节点通信),建议再加一张高速计算网络,常见方案是 InfiniBand(100Gbps 起步)或 RoCE 高速以太网,这类网络只承载作业数据,避免与管理流量抢带宽。
提示:如果你只是学习实验,把控制节点和登录节点放在同一台机器上完全可以接受。但生产环境请务必分开,否则控制节点上用户的交互式进程一多,会影响整个集群的调度稳定性。
2. 基础环境准备与依赖安装
2.1 操作系统与主机名规划
我习惯用 Rocky Linux 9(或 AlmaLinux 9)作为集群操作系统,原因是它在 RHEL 生态下稳定性好、EPEL 源里可以直接拿到 Slurm 和 MUNGE 的软件包,省去源码编译的折腾。Ubuntu 也有对应包,但服务管理方式稍有差别,下面以 Rocky Linux 9 为例。
先把所有节点的主机名设置好,并写入/etc/hosts。这一步看似简单,却是后面很多诡异问题的根源:
# 在每台节点上执行 hostnamectl set-hostname slurmctl # 按角色分别设置# /etc/hosts 示例(所有节点保持一致) 192.168.10.10 slurmctl 192.168.10.11 slurm-login 192.168.10.21 slurm-node01 192.168.10.22 slurm-node02 192.168.10.23 slurm-node03 192.168.10.24 slurm-node04 192.168.10.25 slurm-node05 192.168.10.30 slurm-storage排查过太多失败案例后我可以说,Slurm 节点之间对主机名的解析非常敏感,不要依赖 DNS 出问题后再去查,直接写死 hosts 是最省心的做法。
2.2 时间同步:集群调度不漂移的前提
调度系统最怕的就是节点间时间不一致。作业的开始/结束时间、票据的过期时间都依赖节点时钟,如果某个计算节点时间慢了 30 秒,slurmctld 和 slurmd 之间会出现令牌校验失败或者作业状态错乱。
用 chrony 统一时间,选择控制节点作为时间源:
# 所有节点安装 chrony sudo dnf install -y chrony sudo systemctl enable --now chronyd控制节点/etc/chrony.conf建议增加对外时间源的同步,同时允许内网其他节点跟随:
# 默认的 pool 行保留,同时增加 allow 192.168.10.0/24 local stratum 10其余计算、登录、存储节点把/etc/chrony.conf里的pool全部注释掉,改为:
server slurmctl iburst然后重启 chronyd,用chronyc sources确认时间源状态。这里有经验的工程师往往还会顺手在所有节点上加上timedatectl set-timezone Asia/Shanghai(按需),避免时区不一致导致日志分析出现偏差。
3. 存储节点与共享文件系统
3.1 选型:小规模 NFS,大规模并行文件系统
HPC 集群必须解决一个问题:用户在登录节点提交作业,作业被调度到某一台计算节点上执行,计算节点得能读到用户的代码、输入数据和软件环境。这就需要一个所有节点都能访问的共享文件系统。
小规模实验集群用NFS最简单直接,部署快、概念清晰,足够支撑几十个计算节点的负载。但如果要做严肃的并行计算(大规模 MPI 作业、海量小文件读写),NFS 会成为瓶颈,这时就要上BeeGFS / Lustre / GPFS这类并行文件系统。本文先讲 NFS,逻辑通了之后再去接触并行文件系统会容易很多。
未完待续…(为了直接给出完整文章,下文继续延续实战细节)存储节点在/home、/project、/opt/soft三个目录上分别提供共享,并在/etc/exports中配置:
# 存储节点 /etc/exports /home 192.168.10.0/24(rw,sync,no_root_squash,no_subtree_check) /project 192.168.10.0/24(rw,sync,no_root_squash,no_subtree_check) /opt/soft 192.168.10.0/24(ro,sync,no_root_squash,no_subtree_check)no_root_squash这个参数在 HPC 环境非常关键。默认情况下 NFS 会把root用户映射为nobody,导致计算节点上的管理员无法对共享目录做管理操作(比如安装软件到/opt/soft)。但要注意,no_root_squash也意味着拥有 root 权限的客户端能直接改存储端文件,所以仅限在内网可信环境使用。
客户端挂载在/etc/fstab中写入:
192.168.10.30:/home /home nfs4 defaults,_netdev 0 0 192.168.10.30:/project /project nfs4 defaults,_netdev 0 0 192.168.10.30:/opt/soft /opt/soft nfs4 defaults,_netdev 0 0挂载后统一所有节点的用户 UID/GID 是必须做的一步。我见过太多集群因为用户在控制节点和计算节点 UID 不一致,导致作业写出的文件所有权错乱。简单粗暴的做法是在所有节点上保持/etc/passwd中与 HPC 用户相关的条目一致;更推荐的方式是引入 LDAP 或直接维护一份统一的用户数据库。总之,用户管理务必集中化。
4. Slurm 控制节点与计算节点的核心配置
4.1 MUNGE 认证:Slurm 集群的信任基石
Slurm 集群内部所有通信都要做认证,官方默认的认证机制就是 MUNGE。它相当于集群各节点共享的一把“万能钥匙”,只有持有同一个 key 的节点之间才能互相通信。
在所有节点(控制、计算、登录、存储)上安装并启动 MUNGE:
sudo dnf install -y epel-release sudo dnf install -y munge munge-libs munge-devel然后在控制节点上生成 key,并通过 scp 分发到其他节点(只分发一次,后续新节点也要同步这份 key):
sudo create-munge-key sudo scp /etc/munge/munge.key root@slurm-node01:/etc/munge/ sudo scp /etc/munge/munge.key root@slurm-login:/etc/munge/分发完成后,所有节点执行:
sudo chown -R munge:munge /etc/munge /var/log/munge /run/munge sudo chmod 0700 /etc/munge /var/log/munge /run/munge sudo systemctl enable --now munge用一个命令验证 MUNGE 是否正常:
munge -n | unmunge看到STATUS: Success就成了。这里有个经典坑:key 文件权限必须是 0400 且属主为 munge,如果权限不对,MUNGE 服务能起来,但节点间认证会反复失败,日志里只留下一个含糊的Invalid credential。
4.2 slurm.conf 详解:一份配置,全集群统一
Slurm 的配置核心是/etc/slurm/slurm.conf。这份文件必须保持所有节点完全一致,控制节点和计算节点用同一份,所以配置好之后统一分发。
下面是一份适合入门集群的配置:
ClusterName=hpc-cluster SlurmctldHost=slurmctl SlurmUser=slurm SlurmdUser=root AuthType=auth/munge CryptoType=crypto/munge ProctrackType=proctrack/cgroup TaskPlugin=task/cgroup SelectType=select/cons_tres SelectTypeParameters=CR_Core_Memory SchedulerType=sched/backfill PriorityType=priority/multifactor SlurmctldPort=6817 SlurmdPort=6818 StateSaveLocation=/var/spool/slurmctld SlurmdSpoolDir=/var/spool/slurmd SlurmctldPidFile=/run/slurmctld.pid SlurmdPidFile=/run/slurmd.pid AccountingStorageType=accounting_storage/slurmdbd AccountingStorageHost=slurmctl AccountingStoragePort=7030 AccountingStorageUser=slurm AccountingStoragePass=slurm_db_password ReturnToService=1 MpiDefault=none| 参数 | 作用解释 |
|---|---|
SelectType=cons_tres | 按可消耗资源(CPU、内存等)调度,支持--mem、--cpus-per-task等细粒度限制 |
SchedulerType=sched/backfill | 启用回填调度,让短作业利用大作业的空闲资源,提高集群利用率 |
ProctrackType/cgroup | 用 cgroup 限制并跟踪作业占用的资源,防止进程逃逸 |
ReturnToService=1 | 节点从故障恢复后自动回到可用状态 |
接下来定义节点和分区。假设每个计算节点有 16 核、64GB 内存(这里RealMemory单位是MB):
NodeName=slurm-node[01-05] CPUs=16 RealMemory=64000 Sockets=1 CoresPerSocket=16 ThreadsPerCore=1 State=UNKNOWN PartitionName=normal Nodes=slurm-node[01-05] Default=YES MaxTime=72:00:00 State=UPNodeName支持正则式的范围展开,这在大规模集群里能省掉很多行配置。State=UNKNOWN表示节点初始状态未知,等 slurmd 上线后会自动转入 idle。分区normal是默认分区,作业不指定-p就会投递到这里。
4.3 启动控制节点:让调度器先跑起来
控制节点准备好之后,额外装一下 slurmctld 相关的包并启动:
sudo dnf install -y slurm slurm-slurmctld slurm-slurmdbd sudo systemctl enable --now slurmctld同时建议配置存储记账(可选但强烈推荐)。Slurm 的账户系统slurmdbd依赖 MariaDB,先把数据库准备好:
sudo dnf install -y mariadb-server sudo systemctl enable --now mariadb mysql -e "create database slurm_acct_db;" mysql -e "grant all on slurm_acct_db.* to 'slurm'@'localhost' identified by 'slurm_db_password';"然后创建/etc/slurm/slurmdbd.conf(注意权限必须是 600,属主 slurm):
DbdHost=slurmctl DbdPort=7030 SlurmUser=slurm DatabaseType=mysql DbHost=localhost DbPort=3306 DbName=slurm_acct_db DbUser=slurm DbPass=slurm_db_password再启动 slurmdbd,并把集群加入账户系统:
sudo systemctl enable --now slurmdbd sacctmgr add cluster hpc-cluster不启用 slurmdbd 集群也能跑,但没有历史作业记录,用户提交作业后的sacct查询、计费、资源使用报表全部无法实现。生产环境几乎没有不做的理由。
5. 计算节点加入集群:从 slurmd 到节点上线
5.1 计算节点的统一配置
计算节点相对干净,只需要三样东西:munge.key、slurm.conf、cgroup.conf。前两样直接从控制节点复制过来:
# 在控制节点上执行,这里以 slurm-node01 为例 sudo scp /etc/slurm/slurm.conf root@slurm-node01:/etc/slurm/ sudo scp /etc/slurm/cgroup.conf root@slurm-node01:/etc/slurm/cgroup.conf的内容用于让 Slurm 真正约束作业的 CPU 和内存:
CgroupAutomount=yes ConstrainCores=yes ConstrainRAMSpace=yes ConstrainSwapSpace=yes然后安装并启动 slurmd:
sudo dnf install -y slurm slurm-slurmd sudo systemctl enable --now slurmd5.2 验证节点状态与常见加入失败原因
回到控制节点,通过sinfo和scontrol查看节点是否正常上线:
sinfo -N -l scontrol show node slurm-node01正常情况会看到State=IDLE。如果节点一直处于DOWN或UNKNOWN,先按顺序检查:
- MUNGE key 是否一致:在计算节点执行
munge -n | unmunge,确认返回 Success。 - 网络连通性:从计算节点
telnet slurmctl 6817,确认能连上控制节点的调度端口。 - slurmd 日志:查看
/var/log/slurmd/slurmd.log,里面有具体的认证失败或连接失败原因。 - 节点状态强制恢复正常:如果节点物理上没问题,只是被标记为异常,可以在控制节点执行:
scontrol update NodeName=slurm-node01 State=RESUME计算节点加入时我踩过最大的坑是:slurmctld 已启动,但 slurmd 未启动时,节点状态显示为DOWN,并且Reason字段写着一些含糊的调度器内部信息。这时候不要急着去乱改配置,先把 slurmd 拉起来,等几秒再看状态。
6. 登录节点与作业提交实践
6.1 登录节点的职责与防护配置
登录节点是用户看到的“集群大门”。用户在这里编辑代码、上传数据、提交作业和管理任务。但登录节点绝对不能用来跑计算作业,这是集群设计的基本原则。
生产环境的登录节点我通常会装slurm客户端、pam_slurm和slurm-pam_slurm,并做两个额外优化:
- 启用
pam_slurm_adopt,防止用户通过 SSH 直接登到计算节点上抢占资源。标准做法是在/etc/pam.d/sshd中添加:
account sufficient pam_slurm_adopt.so这样只有正在使用某个作业的用户,才被允许 SSH 到该作业所在的计算节点。
- 用 cgroup 限制登录节点上 SSH 会话的 CPU 和内存,防止哪个用户随手起几个进程就把登录节点挤爆。
从这层意义上说,登录节点配置的核心不是“能提交作业”,而是“如何规范用户行为、隔离异常负载”。
6.2 第一个作业:sbatch 与 srun 的使用
在登录节点把测试脚本写好,用sbatch提交批处理作业:
#!/bin/bash #SBATCH --job-name=hello_hpc #SBATCH -p normal #SBATCH -N 1 #SBATCH --ntasks-per-node=4 #SBATCH --mem=4G #SBATCH --time=00:05:00 srun hostname srun sleep 60提交并查看:
sbatch test.slurm squeue -u $USER scontrol show job 12345如果作业能正常进入RUNNING,计算节点上执行hostname并输出结果,说明整条链路(登录节点 -> 调度器 -> 计算节点 -> 共享存储)已经打通。这是任何一个 Slurm 集群从搭建到交付的一个重要里程碑。
关于交互式调试,srun更合适:
srun -p normal -N 1 --ntasks-per-node=4 --mem=4G --time=00:30:00 --pty /bin/bash进入计算节点交互 shell 后,可以直接测试并行程序,用完exit退出,资源和计费自动回收。
7. 常见问题与故障排查速查表
| 现象 | 最常见原因 | 排查与解决办法 |
|---|---|---|
| 节点状态始终 DOWN | slurmd 未启动或 MUNGE 认证失败 | 在计算节点启动 slurmd;检查 munge.key 是否一致、权限是否是 0400 |
| 作业一直 PENDING | 分区无资源、QOS 或账号限制、Backfill 未生效 | squeue -o "%.18i %.9P %.8j %.8u %.2t %.10M %.6D %R"查看 Reason |
srun报 unable to allocate resources | 请求的资源超过分区上限,或节点被 drain | sinfo -p normal -o "%n %t %C %m"看可用资源 |
| 节点被 DRAIN 后不恢复 | 节点健康检查失败或手动维护 | scontrol show node <node>看 Reason;scontrol update NodeName=<node> State=RESUME |
| NFS 挂载后 Permission denied | 客户端 UID/GID 与服务端不一致 | 统一用户 UID;检查 exports 的no_root_squash是否按需配置 |
| Slack 的 sacct 无记录 | slurmdbd 未启动或配置错误 | 查看/var/log/slurmdbd.log;确认 MariaDB 服务正常、密码正确 |
| 重启节点后作业丢失 | 计算节点 slurmd 的 spool 目录未持久化 | 确保/var/spool/slurmd在重启后能保留,不应放在 tmpfs |
提示:修改 slurm.conf 之后不需要重启整个集群。在控制节点执行
scontrol reconfigure即可热加载配置,这个操作比重启 slurmctld 安全得多。计算节点端 slurmd 一般也能通过scontrol update NodeName=...配合完成平滑生效。
再分享一个我个人的实操心得:新集群搭建阶段,先不要急着挂载生产数据。先在共享存储里建一个 test 目录,用一个小作业验证调度链路,确认节点状态、账户系统、共享存储都稳定了,再逐步放开用户数据和软件环境。这样即便出现问题,排查范围也会小很多,不会把“存储权限问题”和“调度认证问题”搅在一起。
最后一个小技巧:Slurm 集群日常维护时,养成定期看/var/log/slurmctld/slurmctld.log和/var/log/slurmd/slurmd.log的习惯。很多节点假死、调度延迟的前兆都会提前出现在日志里。真等用户跑来抱怨作业跑不动,再去看日志就已经晚了。这一套四节点架构搭完之后,后续要扩充算力就是买机器、装系统、同步 munge.key 和 slurm.conf、启动 slurmd 这么简单,这也是 Slurm 能在 HPC 领域长盛不衰的重要原因。