如何解决Slurm集群用户无Docker权限致作业执行失败问题?
问题背景
我们团队搭建了一个使用Lua认证插件的Slurm集群,所有作业都在runc容器中运行,通过oci.conf配置容器运行逻辑。当前oci.conf内容如下:
CreateEnvFile=true RunTimeQuery="sudo runc --rootless=true --root=/tmp/ state %n.%u.%j.%s.%t" RunTimeKill="sudo runc --rootless=true --root=/tmp/ kill -a %n.%u.%j.%s.%t" RunTimeDelete="sudo runc --rootless=true --root=/tmp/ delete --force %n.%u.%j.%s.%t" RunTimeRun="CONTAINER_NAME=%n.%u.%j.%s.%t ORIG_BUNDLE_DIR=%b PREPARED_BUNDLE_DIR=/var/runc/config/%n.%u.%j.%s.%t && \ /etc/slurm/prepare_bundle.py --orig-bundle-dir $ORIG_BUNDLE_DIR --prepared-bundle-dir $PREPARED_BUNDLE_DIR --container-name $CONTAINER_NAME --env-file %e && \ sudo runc --rootless=true --root=/tmp/ run $CONTAINER_NAME -b $PREPARED_BUNDLE_DIR"
其中prepare_bundle.py依赖docker pull和docker export生成容器rootfs,但作业提交用户来自LDAP/AD,无Docker执行权限,导致脚本运行失败。之前尝试的两个方案均未生效:
- 方案1(临时添加Docker组):在prolog脚本执行
usermod -aG docker <user>,但作业会话中用户组信息未实时更新,id命令显示用户未加入docker组。 - 方案2(切换提交UID):在SP插件的
slurm_spank_task_init_privileged函数修改JOB_SUBMIT_UID,但prepare_bundle.py仍以原用户身份运行。
可行解决方案
1. 配置sudoers允许免密执行指定Docker命令
直接给作业用户授权免密运行docker pull和docker export命令,无需修改用户组:
- 创建sudoers规则文件
/etc/sudoers.d/slurm-docker:
ALL ALL=(root) NOPASSWD: /usr/bin/docker pull *, /usr/bin/docker export *
- 修改
prepare_bundle.py中的Docker命令,添加sudo前缀,比如:
subprocess.run(["sudo", "docker", "pull", image_name], check=True) subprocess.run(["sudo", "docker", "export", container_id, "-o", rootfs_tar], check=True)
2. 以特权用户身份执行prepare_bundle.py
修改oci.conf中的RunTimeRun配置,让prepare_bundle.py以拥有Docker权限的专用用户(比如slurm-docker)运行:
RunTimeRun="CONTAINER_NAME=%n.%u.%j.%s.%t ORIG_BUNDLE_DIR=%b PREPARED_BUNDLE_DIR=/var/runc/config/%n.%u.%j.%s.%t && \ sudo -u slurm-docker /etc/slurm/prepare_bundle.py --orig-bundle-dir $ORIG_BUNDLE_DIR --prepared-bundle-dir $PREPARED_BUNDLE_DIR --container-name $CONTAINER_NAME --env-file %e && \ sudo runc --rootless=true --root=/tmp/ run $CONTAINER_NAME -b $PREPARED_BUNDLE_DIR"
同时需要在sudoers中添加规则,允许作业用户免密切换到slurm-docker执行该脚本:
ALL ALL=(slurm-docker) NOPASSWD: /etc/slurm/prepare_bundle.py *
3. 配置Rootless Docker
让每个LDAP用户可以独立运行Rootless Docker,无需依赖root权限:
- 在集群节点上为LDAP用户配置Rootless Docker环境(完成基础安装配置)。
- 修改
prepare_bundle.py中的Docker命令,直接使用用户自身的Rootless Docker实例(无需sudo)。
4. 调整SPANK插件逻辑
之前修改JOB_SUBMIT_UID无效,是因为该字段仅控制作业提交记录的UID,不影响任务执行时的用户身份。正确的做法是在slurm_spank_task_init阶段切换到特权用户执行prepare_bundle.py,示例代码片段:
#include <slurm/spank.h> #include <unistd.h> SPANK_PLUGIN(slurm_docker_switch, 1); int slurm_spank_task_init(spank_t sp, int ac, char **av) { // 切换到拥有Docker权限的用户(比如UID为1000的slurm-docker用户) if (setuid(1000) != 0) { slurm_error("Failed to switch to slurm-docker user"); return -1; } // 执行prepare_bundle.py,需替换为实际参数 system("/etc/slurm/prepare_bundle.py ..."); // 切回原用户继续执行作业 setuid(spank_get_item(sp, S_JOB_UID)); return 0; }
调试思路
- 验证用户组更新问题:在
prepare_bundle.py中执行id -nG并输出到日志,确认当前会话的组列表;用户组修改后需重新登录才会生效,Slurm作业会话不会自动加载新组,因此usermod方案本质不可行。 - 检查Slurm日志:查看节点上的
slurmd.log(通常在/var/log/slurm/),确认prolog脚本、SPANK插件是否正确执行,有无权限报错。 - 测试sudo规则:以作业用户身份登录节点,手动执行
sudo docker pull <镜像名>,确认是否无需密码即可运行。 - 排查脚本权限:检查
prepare_bundle.py的执行权限(需chmod +x),以及脚本中Docker命令的绝对路径是否正确(避免环境变量差异导致找不到命令)。
内容的提问来源于stack exchange,提问作者GustavoS
相关产品推荐
相关产品推荐

