关于Slurm任务处于RUNNING状态但资源充足却停滞无进展的技术问询
结合你提供的任务详情(JobId=981862)和slurm.conf配置,我来拆解这个异常问题:
核心异常点
你观察到的矛盾状态是关键:任务标记为RUNNING,但同时存在SuspendTime=2021-09-09T08:36:17,且任务停滞6小时无进展。这说明Slurm的任务状态同步出现了问题——任务实际处于暂停状态,但控制节点未正确更新状态,导致无法触发自动恢复逻辑。
根因分析
根据配置和任务信息,可能的诱因有以下几个:
节点健康检查(NHC)触发暂停但状态同步失败
你的配置中启用了HealthCheckProgram=/usr/sbin/nhc,检查间隔为10秒,且ReturnToService=0(节点故障后不会自动重回集群)。如果任务启动时,节点tf-125.biz出现临时健康问题(比如磁盘IO波动、内存瞬时不足),NHC会触发任务暂停,但之后节点恢复正常时,由于ReturnToService=0,Slurm不会自动重新调度恢复该任务,同时状态未同步为SUSPENDED,仍显示RUNNING。抢占机制的自动恢复失效
配置中PreemptType=preempt/partition_prio、PreemptMode=SUSPEND,GANG,高优先级(high_priority分区,PriorityTier=10)任务会抢占低优先级任务的资源并暂停它们。如果当时有高优先级任务抢占了该任务,之后高优先级任务释放资源,但Slurm未自动恢复被暂停的任务——可能是因为缺少ResumeProgram配置,或者Slurm版本存在抢占恢复的bug。Slurm版本的状态同步bug
部分旧版本的Slurm在处理任务暂停、节点状态变更时,存在控制节点与计算节点状态不同步的问题,导致任务实际暂停但状态显示为RUNNING,无法触发自动恢复逻辑。
排查步骤
先确认具体根因,建议做以下检查:
- 查看计算节点tf-125.biz的
/var/log/slurm/slurmd.log,在2021-09-09T08:36:17左右,是否有任务暂停的日志记录,以及节点健康检查的结果。 - 查看控制节点的
/var/log/slurm/slurmctld.log,同一时间段是否有抢占事件、状态更新失败的报错。 - 确认你的Slurm版本,对比官方文档查看是否存在已知的状态同步或暂停恢复bug。
自动化解决方案
1. 修复配置层面的问题
- 调整节点自动恢复配置:修改
slurm.conf中的ReturnToService=1,这样节点健康检查恢复后会自动重新加入集群,Slurm会尝试恢复暂停的任务。修改后重启slurmctld和所有slurmd服务:systemctl restart slurmctld systemctl restart slurmd - 优化抢占恢复逻辑:如果不需要GANG调度,将
PreemptMode改为SUSPEND,避免混合模式可能带来的冲突。同时确保ResumeTimeout(默认300秒)设置合理,给Slurm足够时间恢复任务。
2. 升级Slurm版本
如果排查后确认是版本bug,升级到最新稳定版(比如23.x系列),官方修复了很多旧版本的状态同步问题。
3. 自动化监控与恢复脚本
编写一个脚本定期检查并恢复这类异常任务,示例如下:
#!/bin/bash # 监控并恢复RUNNING但停滞且有SuspendTime的Slurm任务 # 定义停滞阈值:运行超过1小时,且输出文件30分钟未更新 RUNTIME_THRESHOLD="01:00:00" OUTPUT_IDLE_THRESHOLD=1800 # 秒 # 获取所有RUNNING状态的任务,提取JobId、SuspendTime、RunTime squeue -o "%.18i %.20S %.10M" | grep RUNNING | while read job_id suspend_time runtime; do # 跳过无SuspendTime的正常任务 [[ -z "$suspend_time" || "$suspend_time" == "N/A" ]] && continue # 检查运行时间是否超过阈值 if [[ "$runtime" > "$RUNTIME_THRESHOLD" ]]; then # 获取任务的输出文件路径 output_file=$(scontrol show job "$job_id" | grep -oP 'StdOut=\K.*') if [[ -f "$output_file" ]]; then # 计算输出文件最后修改时间与当前时间的差值 last_mod=$(stat -c %Y "$output_file") current_time=$(date +%s) idle_time=$((current_time - last_mod)) if [[ $idle_time -gt $OUTPUT_IDLE_THRESHOLD ]]; then echo "$(date): Requeuing stuck job $job_id (runtime: $runtime, idle: $idle_time sec)" scontrol requeue "$job_id" fi else # 如果输出文件不存在,直接尝试恢复 echo "$(date): Requeuing stuck job $job_id (missing output file)" scontrol requeue "$job_id" fi fi done
将脚本保存为slurm_stuck_job_recover.sh,加入crontab定期执行(比如每15分钟):
*/15 * * * * /path/to/slurm_stuck_job_recover.sh >> /var/log/slurm/stuck_job_recover.log 2>&1
内容的提问来源于stack exchange,提问作者Oleh Linnyk

