4. SLURM 基本配置:slurm.conf 关键参数与实战
聊到 SLURM,最绕不开的就是 slurm.conf。我个人习惯,接手一个新集群,第一件事就是翻这个文件。它决定了集群的“骨架”和“规则”。
说白了,SLURM 的所有行为都靠这个文件驱动。写对了,集群就稳了一半。写错了,排查起来够你喝一壶的。今天咱们就挑几个最关键的参数来拆解一下。
4.1 核心配置文件 slurm.conf 的位置与骨架
这个文件通常放在 /etc/slurm/ 或 /etc/slurm-llnl/ 下。你安装好 SLURM 后,第一步就是配置它。
它的骨架大概长这样:
#
# slurm.conf (Sample)
#
ClusterName=mycluster
ControlMachine=master01
ControlAddr=192.168.1.10
# 其他全局参数...
# 节点定义
NodeName=node01 NodeAddr=192.168.1.11 CPUs=16 RealMemory=64000
NodeName=node02 NodeAddr=192.168.1.12 CPUs=16 RealMemory=64000
# 其他节点...
# 分区定义
PartitionName=normal Nodes=node[01-08] Default=YES MaxTime=INFINITE State=UP
PartitionName=debug Nodes=node[01-02] Default=NO MaxTime=1:00:00 State=UP
嗯,这里要注意,参数的顺序其实无所谓,但逻辑一定要清晰。我见过有人把 ControlMachine 写成了计算节点的名字,结果整个集群都找不到老大。
4.2 关键参数详解
咱们逐个拆解,重点讲讲我踩过坑的几个。
4.2.1 ControlMachine 与 ControlAddr
这是 SLURM 的“大脑”。ControlMachine 指定运行 slurmctld 服务的主机名。ControlAddr 则是它的 IP 地址。
ControlMachine:必填。所有计算节点和服务进程都知道该找谁汇报。ControlAddr:可选,但强烈建议填写。如果你有 DNS 解析或 hosts 文件,可以省略。但为了稳定,我会直接写 IP。
ControlAddr 写死成 IP,避免这种“低级”灾难。
4.2.2 NodeName 与节点定义
每个计算节点都必须在这里注册。你想想看,SLURM 怎么知道你有哪些机器可以用呢?
参数格式:
NodeName=主机名 NodeAddr=IP地址 CPUs=核心数 RealMemory=内存MB State=状态
这里有几点要注意:
NodeName:主机名,必须与hostname一致,或者能被hosts文件解析。NodeAddr:计算节点的管理网 IP。CPUs:节点的 CPU 核心数。SLURM 靠它分配任务。RealMemory:节点的物理内存(MB)。SLURM 用它判断内存是否足够。State:初始状态,通常是UNKNOWN,SLURM 启动后会根据实际通信结果更新。
举个例子:
NodeName=compute01 NodeAddr=10.0.0.1 CPUs=32 RealMemory=128000 State=UNKNOWN
NodeName=compute02 NodeAddr=10.0.0.2 CPUs=64 RealMemory=256000 State=UNKNOWN
注意,如果你的节点数量很多,比如 100 台,可以用简写模式:
NodeName=compute[01-100] NodeAddr=10.0.0.[1-100] CPUs=32 RealMemory=128000
这个正则写法能省很多事。不过,要确保 IP 地址和主机名能够一一对应。
4.2.3 PartitionName 与分区定义
分区,就是“队列”。你把节点划分成不同的逻辑组,用户提交作业时,指定分区名即可。
PartitionName=队列名 Nodes=节点列表 Default=是否默认 MaxTime=最大运行时间 State=状态
PartitionName:队列名称,比如normal、gpu。Nodes:属于该队列的节点。可以是node[01-10]或者node01,node02。Default:YES或NO。如果你不指定--partition,作业就会被投到默认分区。MaxTime:最大运行时间。格式为DAYS-HOURS:MINUTES:SECONDS。比如3-00:00:00表示 3 天。
debug 分区 MaxTime=1:00:00,快速测试用;long 分区可以设置 MaxTime=14-00:00:00,跑长任务。这样可以防止长作业把测试节点占满。
实际例子:
PartitionName=normal Nodes=compute[01-08] Default=YES MaxTime=INFINITE State=UP
PartitionName=highmem Nodes=compute[09-10] Default=NO MaxTime=7-00:00:00 State=UP
4.2.4 DefMemPerCPU 与 DefMemPerNode
这是个很重要的资源限制参数。它定义了用户不指定内存时,默认每个 CPU 核心或每个节点能分配到多少内存。
DefMemPerCPU:每个 CPU 分配的默认内存(MB)。DefMemPerNode:每个节点分配的默认内存(MB)。
为什么要专门配置这个参数?
我遇到过这种情况:用户提交作业时不指定 --mem,结果 SLURM 默认认为作业只需要很少的内存,于是把很多作业塞到同一个节点。最后内存 OOM,机器 hang 了。
所以,我建议设置一个合理的默认值。比如:
DefMemPerCPU=2048
# 或者
DefMemPerNode=32000
这样一来,哪怕用户忘写内存申请,作业也有基本保障。不过要注意,这两个参数不能同时使用。SLURM 会检查冲突。我通常选择 DefMemPerCPU,因为更灵活。
4.2.5 MaxMemPerLimit 与 MaxMemPerNode
有默认值,就有上限。可以防止用户内存申请过大,把整台机器的资源都抢走。
MaxMemPerLimit=64000 # 每个作业最多申请 64GB 内存
MaxMemPerNode=128000 # 每个节点最多 128GB
你想想看,如果和 RealMemory 配合使用,就能精确控制每个作业的资源范围了。
4.3 实战检查步骤
配置文件写好后,不是直接重启就完事了。我建议按以下步骤验证:
- 语法检查:
slurmctld -t。它会告诉你slurm.conf有没有语法错误。 - 模拟加载:
slurmctld -C。它会模拟加载配置,并输出集群信息,检查节点和分区是否定义正确。 - 重启核心服务:
systemctl restart slurmctld。在主控节点执行。 - 同步给所有节点:记得把
slurm.conf复制到所有计算节点的/etc/slurm/目录下,然后重启slurmd。 - 检查状态:
sinfo看节点状态,scontrol show node看详细配置。
来看看具体的命令输出示例:
# 检查配置文件
$ slurmctld -t
slurmctld: slurm.conf syntax OK
# 能看到节点只有 16 个 CPU?那是因为我定义的就是 16
$ scontrol show node node01
NodeName=node01 Arch=x86_64 CoresPerSocket=8
CPUAlloc=0 CPUTot=16 CPULoad=0.01
RealMemory=64000 AllocMem=0 FreeMem=52345
State=IDLE
嗯,看到 State=IDLE,说明配置生效了。如果出现 DOWN 或 DRAIN,就要检查网络或 slurmd 服务了。
4.4 一张图看懂核心配置
为了让你更直观地理解这些配置之间的关系,我画了一张概念图。
从这张图可以看出来,slurm.conf 就像是一个指挥中心。它先定义好“大脑”(ControlMachine),然后是“手脚”(Nodes),接着把“手脚”分组到不同“生产部门”(Partitions),最后给每个人设定“饭量”(资源限制)。
4.5 避坑与经验
- 节点名称冲突:我踩过坑。节点
NodeName和NodeAddr写了不同的机器,但主机名解析时指向同一台。SLURM 会识别失败,报错Node not responding。 - RealMemory vs 实际内存:
RealMemory要填写物理内存总量。SLURM 用它来计算剩余资源。填少了任务可能被拒,填多了容易 OOM。 - 分区状态:分区
State=UP表示可用。如果设置成DOWN,这个分区就暂时不接活了,适合维护的时候用。 - 配置文件同步:修改
slurm.conf后,必须同步到所有节点。我见过有人只改了主控,忘了计算节点,导致作业跑在“旧配置”上,内存限制没生效。