cgroup限制slurm申请资源
在集群上,有极少部分用户作业管理系统提交作业申请的核数和输入文件的核数不一致,特别是输入文件写的核数大于作业申请的核数,这样容易使节点CPU过载。这种情况需要在Slurm作业系统启用cgroup插件控制核数资源。
Cgroup模式¶
slurm支持cgroup的2种模式,一种是传统模式(cgroup v1),一种是统一模式(cgroup v2)。在RHEL/Rocky 8系统中,默认启用v1,在RHEL/Rocky 9中默认启用v2。
# 判断系统中Cgroup的模式
mount |grep cgroup
# 如果输出cgroup2,代表使用统一模式
# 如果输出tmpfs,代表使用传统模式
在RHEL/Rocky 8系统中启用Slurm的cgroup插件¶
slurm.conf和cgroup.conf配置文件设置¶
[root@quantum ~]# grep -i cgroup /etc/slurm/slurm.conf
TaskPlugin=task/cgroup,task/affinity
ProctrackType=proctrack/cgroup
JobAcctGatherType=jobacct_gather/cgroup
[root@quantum ~]# cat /etc/slurm/cgroup.conf
CgroupAutomount=yes # 在24.05版本后,这个参数废弃了
ConstrainCores=yes
ConstrainSwapSpace=yes
AllowedSwapSpace=0
ConstrainRAMSpace=yes
AllowedRAMSpace=95
启用pam_slurm_adopt插件¶
如果还要限制salloc+ssh这种运行作业的核数限制,以及防止用户在用sbatch提交后再ssh到分配的节点用命令提交其他任务,需要启用pam_slurm_adopt插件模块。
在slurm.conf中必须添加PrologFlags=contain
,这将设置一个"extern"步骤来追踪ssh发起的进程。
在计算节点/etc/pam.d/sshd的最后面添加1行:
account required pam_slurm_adopt.so
如果想对某些user放行,不管是在计算节点上有没有作业,都可以ssh到计算节点上。
account sufficient pam_listfile.so item=user sense=allow onerr=fail file=/path/to/allowed_users_file
account required pam_slurm_adopt.so
在RHEL/Rocky 9系统中启用Slurm的cgroup插件¶
slurm.conf和cgroup.conf配置文件设置¶
[root@quantum ~]# egrep -i 'cgroup|PrologFlags' /etc/slurm/slurm.conf
TaskPlugin=task/cgroup,task/affinity
ProctrackType=proctrack/cgroup
JobAcctGatherType=jobacct_gather/cgroup
PrologFlags=Alloc,Contain
[root@quantum ~]# cat /etc/slurm/cgroup.conf
CgroupAutomount=yes # 在24.05版本后,这个参数废弃了
CgroupMountpoint=/sys/fs/cgroup
CgroupPlugin=cgroup/v2
ConstrainCores=yes
ConstrainDevices=yes
ConstrainRAMSpace=yes
ConstrainSwapSpace=yes
启用pam_slurm_adopt插件¶
跟RHEL/Rocky 8系统中启用pam_slurm_adopt插件一样,但配置好了,怎么也限制不了ssh发起进程的核数。
在RHEL/Rocky 9系统,cgroup默认挂载是v2,/sys/fs/cgroup/system.slice/slurmstepd.scope为slurm的cgroup路径;而sshd的cgroup路径为/sys/fs/cgroup/system.slice/sshd.service,并没有包含到slurm的cgroup路径中,且sshd及bash的PID也没包含在slurm的cgroup路径下的cgroup.procs中。最终导致限制不了用户经ssh发起进程的核数。
如果只是想使用salloc占有和使用资源,可在slurm.conf配置文件中加上LaunchParameters=use_interactive_step
,这样使用salloc时将自动启用Interactive步骤发起srun进程,在分配的节点上启动终端。也就是这时跟使用srun --pty bash
差不多,直接进入分配的节点。只不过srun是用的extern步骤,而salloc是用的interactive步骤。
PAM执行脚本绑定用户进程PID¶
脚本思路分析¶
在Cgroup v2模式下,通过上面的方法,只要不用ssh进入节点发起作业进程,都是能限制核数资源的。但只要从管理/登录节点ssh到作业分配的节点,这种ssh进程如果再使用命令就限制不了核数资源。
为了解决用户经ssh发起进程的CPU核数资源限制问题,我们需要把ssh进入到节点的shell进程绑定到slurm的cgroup中。
思路:只要在slurm.conf配置文件中加入PrologFlags=contain
,就会有extern步骤,那我们就需要把ssh进入到节点的当前shell进程及父进程PID绑定到extern步骤的cgroup.procs里面。但cgroup.procs的权限是root,不可能管理员每次都用root账号手动把PID写进去。所以这里,我们就借用PAM的pam_exec.so来执行脚本,且可以用root权限执行。
绑定用户ssh进程PID的脚本¶
#!/bin/bash
# 清理环境变量
unset PATH LD_LIBRARY_PATH
export PATH=/bin:/usr/bin
# 获取当前登录用户(通过PAM_USER环境变量)
USER_NAME=${PAM_USER:-$(id -un)}
USER_ID=$(id -u "$USER_NAME")
# 如果是 root 或系统用户 (UID < 1000),直接退出
if [ "$USER_ID" -lt 1000 ]; then
exit 0
fi
# 获取当前节点的主机名
NODE_NAME=$(hostname)
# 获取用户在当前节点上的所有作业信息,并按 CPU 核数降序排序
# squeue 输出格式:JOBID PARTITION NAME USER ST TIME NODES NODELIST(REASON)
JOB_INFO=$(squeue -u $USER_NAME -h -o "%i %N %C" |grep "$NODE_NAME" |sort -k3,3nr)
# 检查是否有匹配的作业
#if [ -z "$JOB_INFO" ]; then
# echo "No active jobs found for user $USER_NAME on node $NODE_NAME"
# exit 1
#fi
# 获取CPU核数最多的作业 ID
TARGET_JOB_ID=$(echo "$JOB_INFO" |head -n1 |awk '{print $1}')
MAX_CPUS=$(echo "$JOB_INFO" |head -n1 |awk '{print $3}')
# 构建cgroup路径
CGROUP_PATH="/sys/fs/cgroup/system.slice/slurmstepd.scope/job_$TARGET_JOB_ID/step_extern/user/task_0"
# 检查路径是否存在
if [ ! -d "$CGROUP_PATH" ]; then
echo "Cgroup path $CGROUP_PATH does not exist!"
exit 1
fi
# 将当前shell的PID及父进程PID绑定到cgroup
echo $(awk '/PPid/ {print $2}' /proc/$$/status) >> "$CGROUP_PATH/cgroup.procs"
echo $$ >> "$CGROUP_PATH/cgroup.procs"
# 记录日志
LOG_FILE="/var/log/slurm-cgroup-bind.log"
echo "$(date): Bound user $USER_NAME (UID=$USER_ID) to cgroup $CGROUP_PATH for job $TARGET_JOB_ID with $MAX_CPUS CPUs" >> $LOG_FILE
id -un
来获得,因为是root权限执行,那得到的USE_NAME就是root,要获得普通用户的USE_NAME,需要用$PAM_USER变量才行。把脚本放在/usr/local/bin下,并赋予可执行权限
chmod 711 /usr/local/bin/bind_sshd_to_slurm_cgroup.sh
PAM配置¶
#--保留文件原来的内容--
account required pam_slurm_adopt.so
session optional pam_exec.so /usr/local/bin/bind_sshd_to_slurm_cgroup.sh
如果不用pam_slurm_adopt.so,用户ssh到没有作业的节点,会提示:
/usr/local/bin/bind_sshd_to_slurm_cgroup.sh failed: exit code 1
Access denied by pam_slurm_adopt: you have no active jobs on this node
验证¶
阻止用户ssh到没有他/她作业的节点,并提示消息
[userA@quantum ~]$ qa
JOBID NAME USER ST TIME TIME_LIMIT NODES CPUS PARTITION NODELIST(REASON)
[userA@quantum ~]$ ssh cu01
Access denied by pam_slurm_adopt: you have no active jobs on this node
Connection closed by 10.1.255.1 port 22
[userA@quantum ~]$ salloc -N1 -n1
salloc: Granted job allocation 28
salloc: Nodes cu01 are ready for job
[userA@quantum ~]$ qa
JOBID NAME USER ST TIME TIME_LIMIT NODES CPUS PARTITION NODELIST(REASON)
28 interactive userA R 0:07 UNLIMITED 1 1 public cu01
[userA@quantum ~]$ ssh cu01
Last login: Mon Feb 24 22:48:50 2025 from 10.1.255.1
[userA@cu01 ~]$ stress-ng --cpu 2 --timeout 120 --metrics-brief
[root@cu01 ~]# top -n 1
top - 14:29:40 up 3 days, 41 min, 2 users, load average: 0.92, 0.34, 0.12
Tasks: 182 total, 3 running, 179 sleeping, 0 stopped, 0 zombie
%Cpu(s): 50.0 us, 3.1 sy, 0.0 ni, 46.9 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 3625.4 total, 2249.9 free, 675.1 used, 1007.7 buff/cache
MiB Swap: 4096.0 total, 4096.0 free, 0.0 used. 2950.3 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
25417 userA 20 0 46524 6248 4096 R 50.0 0.2 0:03.01 stress-ng-cpu
25418 userA 20 0 46524 6248 4096 R 50.0 0.2 0:03.01 stress-ng-cpu
# 从top命令可看出,用户提交了2核CPU作业,但是由于salloc申请的1核CPU,受cgroup限制,所以每个stress-ng线程只能使用50%,总和为1核。
[root@cu01 ~]# pstree -p |egrep '^systemd|slurm|sshd'
systemd(1)─┬─ModemManager(870)───{ModemManager}(927)
├─slurmd(25153)
├─slurmstepd(5404)
├─slurmstepd(25164)─┬─sleep(25168)
│ ├─{slurmstepd}(25165)
│ ├─{slurmstepd}(25166)
│ ├─{slurmstepd}(25167)
│ ├─{slurmstepd}(25336)
│ └─{slurmstepd}(25341)
└─sshd(14330)─┬─sshd(25238)───sshd(25256)───bash(25257)───pstree(25421)
└──sshd(25337)───sshd(25359)───bash(25360)───stress-ng(25416)─┬─stress-ng-cpu(25417)
└─stress-ng-cpu(25418)
# 从上面的PID树,可看出,sshd发起的进程PID并没有包含到slurmstepd步骤里
[root@cu01 ~]# cat /sys/fs/cgroup/system.slice/slurmstepd.scope/job_28/step_extern/user/task_0/cgroup.procs
25168
25337
25359
25360
25416
25417
25418
# 通过PAM执行脚本,把sshd(25337), sshd(25359), bash(25360)以及其子进程PID都写入extern步骤user作业的cgroup.procs里
[root@cu01 ~]# systemctl status slurmstepd.scope
● slurmstepd.scope
Loaded: loaded (/run/systemd/transient/slurmstepd.scope; transient)
Transient: yes
Active: active (running) since Sat 2025-02-22 13:52:41 CST; 3 days ago
Tasks: 14
Memory: 347.4M
CPU: 2h 18min 50.281s
CGroup: /system.slice/slurmstepd.scope
├─job_28
│ └─step_extern
│ ├─slurm
│ │ └─25164 "slurmstepd: [28.extern]"
│ └─user
│ └─task_0
│ ├─25168 sleep 100000000
│ ├─25337 "sshd: userA [priv]"
│ ├─25359 "sshd: userA@pts/0"
│ ├─25360 -bash
│ ├─25416 stress-ng --cpu 2 --timeout 120 --metrics-brief
│ ├─25417 stress-ng --cpu 2 --timeout 120 --metrics-brief
│ └─25418 stress-ng --cpu 2 --timeout 120 --metrics-brief
└─system
└─5404 /usr/sbin/slurmstepd infinity
# slurmstepd.scope也包含了用户sshd,bash以及命令行进程,说明核数资源是受限制的
# 所有核数资源受slurmstepd.scope/job_$jobid/cpuset.cpus控制
[root@cu01 ~]# cat /sys/fs/cgroup/system.slice/slurmstepd.scope/job_28/cpuset.cpus
0
# 如果是提交2核,cpuset.cpus内容就是0-1。
参考¶
本文阅读量 次本站总访问量 次