Please enable Javascript to view the contents

常用 GPU 运维及故障处理

 ·  ☕ 7 分钟

处理故障时,参考或者记录下的内容,持续更新中

1. XID 错误事件

XID 是 NVIDIA 的错误码,可以通过命令:

1
dmesg -T | grep -i "NVRM: Xid"

或者

1
journalctl --since `date -d "10 days ago" "+%Y-%m-%d"`|grep Xid

根据 XID 可以定位故障,下面是一些常见的 XID 事件

XID说明
13Graphics Engine Exception。通常是数组越界、指令错误,小概率是硬件问题。
31GPU memory page fault。通常是应用程序的非法地址访问,极小概率是驱动或者硬件问题。
43GPU stopped processing。通常是用户应用自身错误而非硬件问题。
45Preemptive cleanup, due to previous errors – Most likely to see when running multiple cuda applications and hitting a DBE。通常是用户手动退出或者其他故障(硬件、资源限制等)导致 GPU 应用退出,Xid 45 只是一个结果,通常需要分析日志。
68NVDEC0 Exception。通常是硬件或驱动问题。
32Invalid or corrupted push buffer stream。事件由 PCIE 总线上管理 NVIDIA 驱动和 GPU 之间通信的 DMA 控制器上报,通常是 PCI 质量问题导致,而非用户程序产生。
38Driver firmware error。通常是驱动固件错误而非硬件问题。
48Double Bit ECC Error(DBE)。当 GPU 发生不可纠正的错误时,会上报 Xid48 事件。该错误也会同时反馈给用户的应用程序。通常需要重置 GPU 或重启节点来清除这个错误。
61Internal micro-controller breakpoint/warning。GPU 内部引擎停止工作,客户业务已经受到影响。
62Internal micro-controller halt。与 Xid61 的触发场景类似。
63ECC page retirement or row remapping recording event。当应用程序遭遇到 GPU 显存硬件错误时,NVIDIA 自纠错机制会将错误的内存区域 retire 或者 remap,retirement 和 remapped 信息需要记录到 infoROM 中才能永久生效。Volt 架构:记录 ECC page retirement 事件到 infoROM 成功。Ampere 架构:记录 row remapping 事件到 infoROM 成功
64ECC page retirement or row remapper recording failure。与 Xid63 的触发场景类似,只是 Xid63 代表 retirement 和 remapped 信息成功记录到了 infoROM,Xid64 代表该记录操作失败。
74NVLINK Error。NVLink 硬件错误产生的 Xid,收到此事件说明 GPU 已经出现严重硬件故障,需要下线维修。
79GPU has fallen off the bus。GPU 硬件检测到掉卡,无法从总线上检测到,收到此事件说明 GPU 已经出现严重硬件故障,需要下线维修。
92High single-bit ECC error rate。硬件或驱动故障。
94Contained ECC error。当应用程序遭遇到 GPU 不可纠正的显存 ECC 错误时,NVIDIA 错误抑制机制会尝试将错误抑制在踩到硬件故障的应用程序,而不会让错误导致 GPU 上的所有应用程序受到影响。当抑制机制成功抑制错误时,会产生 Xid 94 事件,仅影响遭遇了不可纠正 ECC 错误的应用程序。
95Uncontained ECC error。与 Xid94 的触发场景类似。只是 Xid94 代表抑制成功,而 Xid95 代表抑制失败,此时表明运行在该 GPU 上的所有应用程序都已受到影响。

详情参考 https://docs.nvidia.com/deploy/xid-errors/index.html

2. GPU 过高

通常 GPU 温度应该在 85°C 以下,超过时会出现锁频性能下降的问题。执行以下命令,能直接看到 GPU 编号及温度。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
nvidia-smi --query-gpu=index,temperature.gpu --format=csv,noheader

0, 28
1, 40
2, 44
3, 30
4, 27
5, 27
6, 31
7, 32

解决方案:

除了一些物理的方法,从纯软件层考虑,可以直接将温度超过阈值的 GPU 上面的应用程序杀掉,使其更换到其他的 GPU 上。

3. 重启掉卡,nvswitch 报错

1
systemctl status nvidia-fabricmanager.service

或者

1
less /var/log/fabricmanager.log | grep error

看到有 NVlink、NVSwitch 报错。

或者 nvidia-smi 找不到 device handle,Unknown Error 错误。

或者重启之后少卡。

解决方案:

启用 nvidia-persistenced 持久模式,让驱动程序保持加载状态,可以很大幅度的缓解这个问题。

4. Pod 中 nvidia-smi 报错 Function not Found

在 Pod 中执行命令报错:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
nvidia-smi

+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.129.03             Driver Version: 535.129.03   CUDA Version: 12.2     |
|-----------------------------------------+----------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |         Memory-Usage | GPU-Util  Compute M. |
|                                         |                      |               MIG M. |
|=========================================+======================+======================|
|   0  NVIDIA TITAN X (Pascal)        On  | 00000000:03:00.0 Off |                  N/A |
| 23%   26C    P8               8W / 250W | Function Not Found   |      0%      Default |
|                                         |                      |                  N/A |
+-----------------------------------------+----------------------+----------------------+

因为 Pod 中的 cuda 版本过低,与节点上的 cuda 版本不匹配。

解决办法:

加上环境变量,重启应用。

1
LD_LIBRARY_PATH=/usr/local/cuda/lib64:/usr/lib/x86_64-linux-gnu:/usr/local/nvidia/lib

5. 显存无法释放

执行命令:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
nvidia-smi

+---------------------------------------------------------------------------------------+
| NVIDIA-SMI 535.104.05             Driver Version: 535.104.05   CUDA Version: 12.2     |
|-----------------------------------------+----------------------+----------------------+
| GPU  Name                 Persistence-M | Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp   Perf          Pwr:Usage/Cap |         Memory-Usage | GPU-Util  Compute M. |
|                                         |                      |               MIG M. |
|=========================================+======================+======================|
|   0  NVIDIA A800-SXM4-80GB          On  | 00000000:10:00.0 Off |                    0 |
| N/A   32C    P0              68W / 400W |  42058MiB / 81920MiB |      0%      Default |
|                                         |                      |             Disabled |
+---------------------------------------------------------------------------------------+
| Processes:                                                                            |
|  GPU   GI   CI        PID   Type   Process name                            GPU Memory |
|        ID   ID                                                             Usage      |
|=======================================================================================|
+---------------------------------------------------------------------------------------+

会看到没有进程使用显卡,但是显存依然被大量占用。

同时可以发现有一批杀不死的僵尸进程。

1
2
3
4
5
ps aux | grep -E '\<defunct\>'
root      966461  0.0  0.0   6432  2488 pts/0    S+   11:30   0:00 grep --color=auto -E \<defunct\>
root     2215172  0.0  0.0      0     0 ?        Zl   Apr04   1:10 [python] <defunct>
root     2215428  0.0  0.0      0     0 ?        Zl   Apr04   0:00 [python] <defunct>
root     2215442  0.0  0.0      0     0 ?        Zl   Apr04   0:00 [python] <defunct>

解决办法:

依次尝试重启 Kubelet、Docker、主机,即可释放显存资源

6. Docker Hang 住,节点 NotReady

在 Kubelet 中看到 PLEG is not healthy 相关错误日志。在 Docker 中没有异常日志。

可能是 runc hang 住了,因为 pipe 默认大小只有 64 MB,对于高性能计算场景不够用。

解决办法:

设置为 1GB,这里设置的是 262144 * 4K = 1GB

1
echo "fs.pipe-user-pages-soft=262144" >> /etc/sysctl.conf && sysctl -p

7. df\ls hang 住, 无法响应

查看 hang 住的进程

1
2
3
strace df -h

stat("/data/kubelet/pods/af4c411c-bafa-4322-9a21-e5c60ab1658e/volumes/kubernetes.io~nfs/workspace-pv",

找到相关的 mount point

1
2
3
mount | grep mmt-10289-v2-1-4

1.1.1.1:/cfs-fSfmHNQjNA/workspace on /data/kubelet/pods/af4c411c-bafa-4322-9a21-e5c60ab1658e/volumes/kubernetes.io~nfs/workspace-pv type nfs (ro,relatime,vers=3,rsize=131072,wsize=524288,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=10.8.254.230,mountvers=3,mountport=300,mountproto=tcp,local_lock=none,addr=10.8.254.230)

确认目录已经不可使用

1
ls /data/kubelet/pods/af4c411c-bafa-4322-9a21-e5c60ab1658e/volumes/kubernetes.io~nfs/workspace-pv

此时应该 hang 住无法响应。通常是远端服务 1.1.1.1 已经无法访问,但挂载的客户端未清理导致。

强行卸载目录

1
umount -f /data/kubelet/pods/af4c411c-bafa-4322-9a21-e5c60ab1658e/volumes/kubernetes.io~nfs/workspace-pv

8. 磁盘 df 与 du 数据严重不符

使用 df 查看发现 / 使用了 86%。

1
2
3
4
df -h

Filesystem               Size  Used Avail Use% Mounted on
/dev/sda3                435G  352G   62G  86% /

但使用 df 统计却只有很少使用量

1
2
3
du -h --max-depth=2 --exclude=/data --exclude=/data1 --exclude=/var/lib/juicefs/volume / | grep '[0-9.]\+G'

32G	/

原因是,删除大文件时,依然有程序占用文件,导致内核无法回收空间。

解决办法:

  1. 找出程序占用的文件
1
lsof -n | grep deleted
  1. 删除程序占用的文件
1
lsof -n | grep deleted | awk '{print $2}' | sort -u | xargs sudo kill -9

9. 使用 ipmitool 重启主机

使用 reboot 命令重启主机,只是系统层面,有些硬件故障不能恢复。

1
ipmitool chassis power cycle

相当于断电重启。

10. version mismatch

1
2
3
4
nvidia-smi

Failed to initialize NVML: Driver/library version mismatch
NVML library version: 535.129
1
2
3
4
5
modinfo nvidia | grep version

version:        535.183.01
srcversion:     E1D7E062E93D47A443165F6
vermagic:       5.4.0-1131-oracle SMP mod_unload modversions

解决办法:

卸载 nvidia driver 之后,重新安装

1
2
3
apt-get --purge remove "*cublas*" "cuda*"
apt-get --purge remove "*nvidia*"
apt autoremove

11. no free node

使用 https://github.com/tkestack/gpu-manager 对 GPU 进行管理,需要注意驱动的版本不能太高,比如 535.183 无法兼容。

我们测试的可兼容版本是 535.129。

使用高版本驱动时,显存分配之后,无法正常回收,导致第一次分配完成之后,新 Pod 创建时会报错 no free node

根本原因在于,gpu-manager 无法获取到实时的显存信息。

在兼容的版本下如果遇到这个问题,可以尝试重启 kubelet,更新显存信息。

12. 企业版 JuiceFS 速度剧烈波动

在预热之后,访问速度应该能够平稳、较快,但如果 P2P 缓存服务节点组中,有访问慢的节点,会导致访问速度局部下降,拉低整体的访问速度。

可以进入 fluid 的 worker pod。

1
2
3
ps aux | grep jfsmount

root         190 47.8  0.0 6160996 397776 ?      S<l  Sep13 673:59 /usr/local/juicefs/mount/jfsmount myjuicefs-storage /runtime-mnt/juicefs/mynamespace/myjuicefs-storage-fluid/juicefs-fuse -o cache-group=mynamespace-myjuicefs-storage-fluid,cache-size=5242880,free-space-ratio=0.1,cache-dir=/data1/jfs/cache:/data/jfs/cache,foreground,no-update

查看 P2P 缓存服务节点组之间的连接

1
lsof -p 190

排查是否有慢、不符合预期的节点,剔除相关节点即可恢复。

13. resolv.conf: no such file or directory

Pod 起不来,报错:

1
/run/systemd/resolve/resolv.conf: no such file or directory

解决办法:

1
vim /var/lib/kubelet/kubeadm-flags.env

KUBELET_KUBEADM_ARGS 中修改 --resolv-conf=/etc/resolv.conf

然后重启 kubelet:

1
2
systemctl daemon-reload
systemctl restart kubelet

14. 升级节点 CPU 之后 kubelet 起不来

报错信息

1
start cpu manager error: current set of available CPUs \"0-7\" doesn't match with CPUs in state \"0-3\"

解决办法:

1
2
3
rm -f /var/lib/kubelet/cpu_manager_state
systemctl daemon-reload
systemctl restart kubelet

15. gpu-manager 启动报错 can’t load container response data

报错信息

1
can't load container response data, &json.SyntaxError{msg:"unexpected end of JSON input", Offset:0}

有时也会提示找不到 kubelet_internal_checkpoint 类似错误。

解决办法:

尝试多重启几次 Kubelet,如果还是不行就从其他节点拷贝 /var/lib/kubelet/device-plugins/kubelet_internal_checkpoint 文件到当前节点。

故障的原因是 GPU Manager 有 Bug,导致有时会无法生成 kubelet_internal_checkpoint 文件。

1
wget https://ghp.ci/https://raw.githubusercontent.com/shaowenchen/hubimage/refs/heads/main/ai/kubelet_internal_checkpoint  -O /var/lib/kubelet/device-plugins/kubelet_internal_checkpoint

16. cannot allocate unhealthy devices tencent.com/vcuda-core 无法创建 Pod

gpu manager 报错

1
E1114 03:01:12.308213   33781 server.go:133] Unable to set Type=notify in systemd service file?

解决办法:

1
systemctl restart kubelet

17. DCGM 报错 Failed to watch metrics

报错信息

1
Failed to watch metrics: Error watching fields: Host engine is running as non-root

解决办法:

编辑 dcgm-exporter 的 DaemonSet,确认 Pod 的以下配置无误。

1
2
3
4
5
6
securityContext:
  capabilities:
    add:
      - SYS_ADMIN
  runAsNonRoot: false
  runAsUser: 0

特别是这里的 capabilities 配置,确保有 SYS_ADMIN 权限,仅仅 runAsUser: 0 还不够。

18. PCI 识别不到 GPU

执行命令:

1
echo 1 > /sys/bus/pci/rescan

尝重新识别 PCI 设备,不一定能解决问题,因为有可能是硬件问题。

19. 分配不足一整张卡时报错 rpc client exit with 255

报错提示

1
/tmp/cuda-control/src/register.c:87 rpc client exit with 255

解决办法:

添加环境变量

1
LD_LIBRARY_PATH=/usr/local/cuda/lib64:/usr/lib/x86_64-linux-gnu:/usr/local/nvidia/lib

原因是 CUDA 默认是不支持分配不足一整张卡的,需要 GPU 分片的组件支持。如果使用的是 GPU Manager,可以通过设置上面的环境变量劫持分配请求。

20. drain 禁用指定的故障卡

  • 查看卡的 PCI 位置
1
2
3
4
nvidia-smi --query-gpu=index,pci.bus_id --format=csv
index, pci.bus_id

0, 00000000:18:00.0

第一列是卡的编号,第二列是卡的 PCI 位置。

  • 禁用指定的 GPU 卡
1
nvidia-smi drain -p 0000:18:00.0 -m 1

-m 1 表示驱逐状态,-m 0 表示关闭驱逐状态。执行完成之后,卡在 nvidia-smi 不可见,但在 lspci 中可见。

  • 查看卡的驱逐状态
1
nvidia-smi drain -p 0000:18:00.0 -q

21 NCCL Cannot allocate memory

报错提示,无法分配显存

misc/ibvwrap.cc:262 NCCL WARN Call to ibv_reg_mr failed with error Cannot allocate memory

解决办法:

给 Pod 添加上 IPC_LOCK 权限

1
2
3
4
securityContext:
  capabilities:
    add:
      - IPC_LOCK

微信公众号
作者
微信公众号