上一篇 下一篇 分享链接 返回 返回顶部

GPU服务器与GPU云服务器任务异常时,如何关联系统、容器与GPU监控日志定位故障?

发布人:Minchunlin 发布时间:2026-09-30 20:29 阅读量:2
GPU服务器与GPU云服务器任务异常时,如何关联系统、容器与GPU监控日志定位故障?

GPU任务出现报错、卡死、退出或反复重启时,最容易误判的是只看应用最后一行异常。真正的故障可能发生在更早的时间点:宿主机触发内存回收、容器被终止、GPU驱动报告设备错误,应用只是最后感知到“设备不可用”或“任务失败”。因此,定位时不能只围绕一份日志,而要把任务日志、容器状态、系统日志和GPU监控数据放到同一条时间线上。

现场排查建议遵循“先固定范围和时间,再看任务与容器,随后核对系统和GPU,最后做修复验证”的顺序。这样既能避免过早重启导致证据丢失,也能区分是应用配置问题、容器资源限制、宿主机资源不足,还是GPU驱动或设备链路异常。

先把任务异常拆成四层

层级主要查看内容重点字段能回答的问题
任务或应用训练、推理、渲染、计算任务日志时间戳、任务ID、进程PID、进程组或rank、异常类型、退出码、GPU编号哪个任务、哪个进程、哪个计算阶段先失败
容器或编排Docker日志、容器状态、Kubernetes Pod事件容器ID、Pod名称、节点、重启次数、退出码、OOMKilled、启动和结束时间任务是否被容器运行时或编排系统终止
宿主机系统systemd、内核、资源和服务日志内核时间、OOM、cgroup、磁盘、驱动错误、服务重启宿主机是否在任务失败前出现资源或驱动异常
GPU监控GPU历史指标和驱动查询结果GPU UUID、利用率、显存、温度、功耗、进程、ECC、Xid或同类错误GPU是否已经异常、显存是否耗尽、故障影响哪块卡

同一个“任务退出”可以对应完全不同的原因。例如,应用报显存不足,不等于宿主机内存不足;容器退出码为137,也不等于一定是GPU故障;nvidia-smi当前显示正常,也不能证明故障发生时没有短暂的驱动异常。

第一步:固定时间、对象和现场证据

先确定故障窗口

至少记录以下信息:

  • 任务ID、提交时间、开始时间和最后一次成功时间;
  • 任务所在的主机名、云实例标识、容器ID或Pod名称;
  • 使用的GPU UUID、GPU索引,以及启用GPU分片时的实例标识;
  • 第一个异常出现的时间,而不是任务最终退出的时间;
  • 时间采用的时区,最好统一转换为带时区的绝对时间;
  • 任务是否自动重试、容器是否发生过重启或迁移。

Linux系统上可以先执行只读命令确认当前时间和基础环境。以下命令适用于常见的systemd Linux主机;没有systemd的环境,应使用系统自身的日志查询方式。

date -Is
timedatectl
hostname
cat /etc/os-release
free -h
df -h
df -i

如果使用的是NVIDIA GPU,可以记录当前设备和驱动可见性:

nvidia-smi -L
nvidia-smi

这些结果只能反映采集时刻的状态,不能替代历史监控。执行前应确认具备主机或容器内的读取权限,并注意日志可能包含任务参数、路径、用户名或环境变量等敏感信息,导出给其他人员前应进行脱敏。

不要先做会改变现场的操作

在没有保存证据前,不建议直接重启主机、重载GPU驱动、删除容器、清理Docker资源或清空系统日志。这些操作可能使原始时间线断裂,也可能让短暂的GPU错误无法再次确认。

如果业务必须立即恢复,应先保存:

  • 任务和容器的原始日志;
  • 容器状态、退出码和重启次数;
  • 内核日志中故障时间窗口的内容;
  • GPU查询结果和监控平台历史截图或导出数据;
  • 当前镜像版本、驱动版本和任务配置摘要。

第二步:按优先级查看各类日志

1. 先看任务日志,找出第一个失败的进程

应用日志应重点查找以下字段:

  • 精确时间戳,最好带毫秒或更细粒度;
  • 任务ID、作业名称、节点名;
  • 进程PID、进程组、分布式任务的rank;
  • GPU逻辑编号与GPU UUID;
  • CUDA或框架异常类型;
  • 显存分配失败、设备不可用、通信失败、进程收到信号等信息;
  • 最后一个成功步骤、检查点或批次编号。

多卡任务尤其要区分“第一个失败的rank”和随后被连带终止的rank。一个进程先失去GPU设备,其他进程可能只显示通信超时或同步失败。后续日志看起来更严重,但不一定是根因。

如果应用日志只显示类似“任务被终止”或“设备断开”,不要马上修改模型或任务参数,应继续核对容器和系统日志。应用往往只能报告它观察到的结果,无法说明是谁发出了终止信号。

2. 再看容器状态和运行时日志

Docker环境

先查看容器的最终状态、退出码和是否被判定为内存终止:

docker inspect --format 'id={{.Id}} status={{.State.Status}} exit={{.State.ExitCode}} oom={{.State.OOMKilled}} started={{.State.StartedAt}} finished={{.State.FinishedAt}}' 

再按故障时间读取带时间戳的标准输出和错误输出:

docker logs --timestamps --since "" --until "" 

如果任务由Docker直接启动,还应查看容器事件:

docker events --since "" --until ""

重点关注:

  • ExitCode是否为非零;
  • OOMKilled是否为true;
  • StartedAt和FinishedAt是否与应用日志吻合;
  • 是否出现停止、重启、删除或健康检查失败事件;
  • 容器日志时间是否与宿主机日志存在时区或延迟差异。

退出码137通常表示进程收到SIGKILL,常见原因包括内存不足或外部强制终止,但它本身不能证明一定是内存问题。只有当OOMKilled、内核OOM记录或容器资源事件同时吻合时,才能把容器内存不足作为主要方向。退出码143通常对应SIGTERM,还要结合编排事件判断是人工停止、滚动更新、节点维护还是其他控制动作。

如果docker logs没有内容,可能是应用把日志写到了容器内文件、使用了其他日志驱动,或者容器已经被删除。此时应查看容器挂载目录、日志驱动配置和宿主机运行时日志,而不是直接认定任务没有输出。

Kubernetes环境

如果任务运行在Pod中,应同时查看Pod描述、当前日志、上一次容器实例日志和事件:

kubectl get pod  -n  -o wide
kubectl describe pod  -n 
kubectl logs  -n  --timestamps
kubectl logs  -n  --previous --timestamps
kubectl get events -n  --field-selector involvedObject.name= --sort-by=.lastTimestamp

重点字段包括:

  • Pod所在节点;
  • 容器的Restart Count;
  • Last State、Reason、Exit Code;
  • OOMKilled;
  • 调度失败、节点不可用、驱逐、探针失败和容器启动失败事件;
  • GPU资源申请数量与实际可见设备;
  • Pod重启前后的容器ID。

--previous只能读取上一次已经结束的容器实例。如果Pod经历多次重启,较早的实例日志可能已经被轮转或清理,需要依靠集中式日志系统或节点上的容器日志文件补充。

容器运行时和节点代理的服务名可能因环境不同而变化,不要直接假定服务名称。可以先列出实际服务:

systemctl list-units --type=service | grep -Ei 'docker|containerd|kubelet'

确认名称后,再读取对应时间窗口:

sudo journalctl -u  --since "" --until "" -o short-precise
sudo journalctl -u  --since "" --until "" -o short-precise

3. 查看宿主机系统和内核日志

systemd主机可以先查看故障时间窗口内的告警和错误:

sudo journalctl --since "" --until "" -p warning..alert -o short-precise
sudo journalctl -k --since "" --until "" -o short-precise

针对GPU任务,可筛选常见关键词:

sudo journalctl -k --since "" --until "" -o short-precise \
  | grep -Ei 'oom|out of memory|killed process|cgroup|NVRM|Xid|gpu|pcie|aer'

需要重点观察:

  • Out of memory、oom-killer或cgroup内存限制;
  • 磁盘空间和inode耗尽;
  • GPU驱动加载、卸载或恢复失败;
  • 内核报告的GPU设备错误;
  • PCIe或设备访问相关错误;
  • Docker、containerd、kubelet等服务是否在同一时间重启;
  • 主机是否发生过异常重启或时间跳变。

如果内核日志中出现NVIDIA的Xid或其他厂商对应的GPU错误码,应把它当作重要线索,但不要仅凭错误码直接下硬件或驱动结论。错误码的具体含义与驱动版本、设备状态和厂商文档有关,应结合前后日志、GPU监控和复现结果判断。

还要区分主机内存、容器内存和GPU显存:

  • 主机内存不足通常会在内核或容器状态中留下OOM记录;
  • 容器内存上限触发时,应用可能被cgroup终止;
  • GPU显存不足通常表现为框架分配失败或GPU运行时错误,不一定触发Linux的OOM日志;
  • GPU利用率低也不代表任务没有问题,数据加载、CPU处理、同步等待或设备错误都可能让利用率下降。

4. 查看GPU监控和驱动状态

GPU监控平台提供的是带时间序列的指标,虽然不一定以“日志”形式保存,但在定位短暂故障时通常比当前查询更有价值。应查看故障前后至少一个完整任务阶段,重点核对:

  • 采样时间和时区;
  • 主机名、实例标识、GPU UUID;
  • GPU索引、分片或实例标识;
  • GPU利用率;
  • 显存已用量和总量;
  • 温度、功耗、时钟或性能状态;
  • 计算进程PID和进程名;
  • ECC计数或同类设备错误计数;
  • 驱动错误、设备不可见、监控采集失败事件;
  • 监控采样间隔和数据是否存在缺口。

在NVIDIA环境中,以下命令适合做当前状态核验:

nvidia-smi -L
nvidia-smi
nvidia-smi --query-gpu=index,uuid,utilization.gpu,memory.used,memory.total,temperature.gpu,pstate,power.draw --format=csv
nvidia-smi --query-compute-apps=pid,process_name,used_memory --format=csv

不同驱动版本支持的查询字段可能不同。如果某个字段返回不支持,应先查看本机帮助信息,不要据此判定GPU故障:

nvidia-smi --help-query-gpu
nvidia-smi --help-query-compute-apps

当前查询能够回答“现在是否可见、现在有哪些进程”,不能回答“十分钟前是否曾经掉卡”。历史问题必须回到监控系统或已保存的采集日志。

第三步:把日志关联成一条时间线

日志关联不应只按“相同错误关键词”进行,而要同时满足时间、对象和因果顺序三个条件。

统一时间格式

首先确认主机、容器日志、监控平台是否使用相同的时区。建议把所有时间转换为带时区的绝对时间,并保留原始时间。对于跨主机或跨节点任务,还要考虑时钟偏差。

应用日志可能使用本地时间,内核日志可能使用主机时间,监控系统可能统一保存为UTC。如果不先统一时间,容易把恢复动作误判为故障起点。

优先使用稳定标识,而不是GPU索引

GPU索引可能因设备枚举顺序、容器可见设备映射或任务重启而变化。关联时优先使用:

  1. 主机名或云实例标识;
  2. 容器ID或Pod名称;
  3. 宿主机PID;
  4. GPU UUID;
  5. 任务ID和rank。

容器内PID与宿主机PID可能不同,尤其在启用PID命名空间时,不能直接拿容器日志中的PID与主机GPU进程列表机械匹配。应结合容器ID、进程启动时间和GPU UUID共同确认。

按“最早异常”排列事件

可以建立如下时间线:

时间点证据来源关键事件判断方向
T0任务日志最后一次成功计算或检查点确定任务正常边界
T1GPU监控显存快速上涨、利用率异常或设备指标中断判断GPU侧是否先出现变化
T2内核日志OOM、驱动错误或设备访问异常判断宿主机是否先感知故障
T3容器日志收到信号、容器退出或重启判断是否由运行时终止
T4任务日志框架抛出最终异常确定应用层表现
T5编排事件重调度、驱逐或重新拉起判断后续恢复动作

如果T2早于T4,且T2的事件与任务所在GPU或节点一致,系统或GPU侧故障的优先级更高。如果只有T4,没有T1和T2,而异常明确指向显存分配或业务参数,则应先检查任务本身的资源使用。若T3早于T4且容器被标记为OOMKilled,则应优先核对容器内存限制和主机内存压力。

常见结果及其含义

观察结果更可能的方向下一步核验
应用报显存不足,监控显示显存接近上限,系统无OOMGPU显存分配或任务峰值问题核对失败批次、显存历史曲线、同一GPU上的其他进程
容器退出码137,OOMKilled=true,内核同时有OOM记录容器或主机内存不足核对容器内存限制、任务峰值和节点剩余内存
应用报设备不可用,内核先出现GPU驱动错误驱动或GPU设备路径异常保存驱动版本、GPU UUID和完整内核日志,避免先清除现场
GPU监控在异常时段断点,容器随后退出GPU采集或设备可见性中断对比宿主机和容器内的GPU查询结果,查看运行时事件
Pod重启,事件显示探针失败或节点驱逐编排层终止任务查看节点事件、重启前日志和探针配置
只有一个分布式rank先失败,其余rank随后超时首个rank或其GPU先异常以最早失败rank为主线,关联其PID、GPU UUID和节点
应用日志没有结束记录,容器突然消失外部终止、日志未落盘或容器被删除查看运行时事件、节点日志和集中式日志保留情况
nvidia-smi当前正常,但任务之前曾失败短暂故障已经恢复或当前状态与历史不同依靠GPU历史监控和内核日志,不以当前状态否定历史异常

GPU服务器和GPU云服务器有什么区别?关键在日志边界

排查方法本身基本一致,区别主要在于能够看到哪一层日志。

在自有或托管的GPU服务器上,通常可以直接查看操作系统、容器运行时、内核和GPU驱动日志,管理员能够把主机、容器和设备信息放到同一条时间线上。但能否查看更底层的设备管理信息,仍取决于实际权限和运维方式。

在GPU云服务器上,用户通常能够查看实例操作系统、容器和任务日志,但云平台宿主机、虚拟化层或物理设备侧的日志未必对实例开放。此时,实例内没有对应内核记录,并不等于云平台侧没有事件。向平台技术支持提交问题时,应提供:

  • 实例标识和主机名;
  • 故障发生的绝对时间和时区;
  • GPU UUID或云平台分配的设备标识;
  • 任务ID、容器ID或Pod名称;
  • 应用异常原文、退出码和重启记录;
  • 相关内核日志和GPU监控数据;
  • 驱动版本以及任务运行时版本。

不要只提交“GPU任务失败”的描述,也不要在没有证据时直接要求更换设备。时间窗口、设备标识和原始错误信息越完整,越容易判断问题发生在应用、实例系统、容器运行时还是云平台不可见的底层范围。

修复后的验证不能只看任务重新运行

故障处理完成后,至少分三层验证。

验证宿主机和GPU可见性

确认主机时间正常,GPU设备数量和UUID与任务预期一致,驱动查询可以正常返回。随后查看新的测试窗口内是否出现新的内核GPU错误、OOM或运行时重启。

对于已经发生过驱动或设备不可见问题的环境,不应只执行一次查询就结束。应在短时测试任务和正式任务阶段分别观察GPU监控,确认指标没有再次中断。

验证容器和编排状态

检查:

  • 容器或Pod没有重复重启;
  • GPU设备在容器内可见;
  • 容器内进程与预期GPU UUID对应;
  • OOMKilled保持为false;
  • 任务退出码正常;
  • 运行时和节点事件没有新的停止、驱逐或探针失败;
  • 日志能够持续写入并带有可关联的时间戳。

如果修复涉及镜像、资源限制或GPU运行时配置,应把修改前后的配置版本记录下来,避免多个变量同时改变后无法判断真正原因。

验证任务级行为

先执行能够覆盖同一GPU路径的短时测试,再运行具有代表性的任务阶段。多卡任务要确认所有rank都能完成初始化、计算和退出,不能只观察主进程。正式任务结束后,还应核对检查点、输出文件和最终退出码,避免“进程退出但结果不完整”。

最容易遗漏的是复核日志保留和时间同步。很多故障并不是没有发生,而是日志已经轮转、容器重启后旧实例日志被覆盖,或者应用、主机和监控平台使用了不同时间基准。只要保留原始时间戳、容器ID、GPU UUID和第一次异常位置,系统、容器与GPU监控日志通常就能从“各自孤立的报错”还原为一条可验证的故障链。

目录结构
全文