[故障排查] Slurm 计算节点 NFS 挂载严重卡顿:一场由百个“流氓”容器引发的拥堵

问题背景

作为 Slurm 集群管理员,发现某一个特定计算节点(CN04)在挂载 NFS 共享存储(/public)时出现严重卡顿。
具体表现:

  • 执行 ls, cd 等简单命令响应极慢(卡死)。
  • NFS 挂载参数为:mount -t nfs -o nolock -o tcp -o nfsvers=3 ...
  • 其他节点正常,仅该节点异常。

排查阶段一:网络层诊断(Network Diagnostics)

NFS 对网络质量极度敏感。首先排查是否由物理网络丢包或 MTU 配置错误导致。

1. 基础连通性检查

使用 ping 检查丢包率和延迟:

ping -c 50 -s 8192 183.169.15.16
  • 测试结果: 0% 丢包,但延迟(RTT)约为 19ms
  • 分析:
    • 没有丢包说明物理线路大概率没问题。
    • 19ms 的延迟对于局域网 HPC 存储来说过高(通常应 < 1ms)。NFSv3 协议交互繁琐,高延迟会导致元数据操作(如 ls)呈指数级变慢。

2. MTU 配置检查

检查是否存在巨型帧(Jumbo Frame)配置不一致导致的包分片问题:

ip link show | grep mtu
  • 测试结果: 物理网卡 eno3 MTU 为 1500,正常。
  • 异常发现: 输出中发现了大量的 veth 虚拟网卡接口和 br-xxxxx 网桥,暗示该节点运行了复杂的容器网络。

排查阶段二:系统资源与 IO 分析(System & IO Analysis)

排除网络断连后,检查是否因系统负载过高导致 NFS 客户端进程(kernel threads)被阻塞。

1. 检查系统负载与 IO 等待

# 查看负载 (Load Average) 和 IO 等待 (wa)
top
vmstat 1 5
  • 结果: Load Average 约为 8.x,IO Wait (wa) 约为 2.7%。
  • 分析: 负载不算极高,但对于空闲节点来说也不正常。

2. 检查 IO 吞吐与进程

查看是否有进程在疯狂读写磁盘:

# 查看进程级 IO
iotop -oPa
  • 结果: 吞吐量仅几 MB/s。
  • 分析: 带宽没被跑满,但IOPS(每秒操作数)竞争可能依然存在。

3. 查看内核日志

检查是否有 NFS 协议层的报错:

dmesg | tail
tail -f /var/log/messages
  • 目的: 寻找 nfs: server not responding 报错。如有,通常意味着网络拥塞或超时。

排查阶段三:定位元凶——“流氓”容器(The Culprit)

ip link 中发现大量 veth 接口是关键线索。我们深入排查了容器环境。

1. 检查 Docker 容器状态

# 查看所有正在运行的容器
docker ps
  • 震撼的发现:
    • 节点上运行了 100+ 个容器
    • 包含大量的 metabolism-worker(计算进程)、elasticsearchredis
    • 状态为 Up 29 hours
  • 来源确认: 这些是 StarDrop 软件留下的计算环境。由于作业脚本未配置自动清理,导致这些容器在作业结束后依然在后台运行。

2. 为什么这会导致 NFS 卡顿?

  • 网络风暴: 100 多个容器同时存活,即便不进行大数据传输,也会产生大量的 ARP 广播和网络中断上下文切换。
  • 并发争抢:19ms 高延迟 的网络环境下,100 个进程同时尝试通过单一 NFS TCP 连接与服务器交互,导致请求队列瞬间塞满,造成客户端“假死”。

解决方案(Resolution)

步骤 1:清理“流氓”容器

既然确认这些是已完成作业的残留,我们需要释放资源。

  • 策略: 优先使用 stop 而非 rm,防止误删数据,且能立刻释放 CPU/网络资源。
# 停止所有正在运行的容器(立刻见效)
docker stop $(docker ps -q)

# [可选] 确认无误后彻底删除清理
# docker rm $(docker ps -a -q)
# docker network prune -f

效果: 执行后,ls /public 响应速度瞬间恢复正常。

步骤 2:优化 NFS 挂载参数(针对高延迟环境)

针对该节点 19ms 的网络延迟,默认的 NFS 参数效率太低。我们调整了挂载命令,开启激进的本地缓存

优化后的挂载命令:

mount -t nfs -o nolock,tcp,nfsvers=3,rsize=1048576,wsize=1048576,hard,intr,noatime,nodiratime,actimeo=60,nocto 183.169.15.16:/public /public

关键参数解析:

  • actimeo=60 (关键): 强制客户端在 60 秒内缓存文件属性,不要频繁询问服务器“文件变没变”。这能极大缓解高延迟下列出目录(ls)时的卡顿。
  • rsize/wsize=1M: 增大读写块大小,减少网络往返次数。
  • nocto: 关闭 “Close-to-Open” 一致性检查,进一步减少协议开销。

经验总结与管理员建议

  1. 警惕“看不见”的负载:topiotop 数据看似正常时,检查网络接口(ip link)和容器运行时(docker ps)。大量的空闲容器也是网络杀手。
  2. 作业清理机制(Epilog): 建议在 Slurm 的 slurm.conf 中配置 Epilog 脚本,在作业结束后强制执行 docker stopdocker-compose down,防止计算环境残留。
  3. 延迟 vs 带宽: 对于 NFS 体验,延迟(Latency) 往往比带宽更重要。如果是跨网段或高延迟挂载,必须使用 actimeonocto 等缓存参数进行补偿。
Logo

中国智能体开发者社区,聚焦智能体与大模型开发,提供前沿资讯、实用工具链、开源项目及行业案例。通过技术沙龙、开发者大赛等活动,促进经验交流与协作,助力开发者快速构建创新智能应用。

更多推荐