训练任务失败后,平台自动重试并保留现场日志的核心做法是:在任务编排层配置失败识别与退避重试,同时用独立日志通道和快照机制把崩溃现场固定下来,避免容器一删,证据全没。
训练任务失败自动重试机制怎么设计
训练任务挂了,平台的第一反应不应该是无脑拉起,而是先看一眼退出码,再决定要不要重试,如果代码本身有语法错误,拉起来十次还是失败,还白白烧GPU卡时。
先给失败分类,再决定重试策略
多数训练平台的失败可以分成两类:
- 可重试失败:节点资源不足、网络抖动、GPU驱动临时异常、数据加载超时、节点漂移。
- 不可重试失败:训练代码报错、配置文件写错、数据路径不存在、精度不收敛。
区分这两类失败,通常靠容器退出码,例如Kubernetes环境下,退出码137多半是OOM或被信号杀掉,退出码1一般是程序自身抛异常,平台会根据退出码判断是否需要自动重试。
Kubernetes Job的重试参数怎么配
在Kubernetes里,一个训练任务通常用Job或自定义资源承载,自动重试依赖两个字段:
restartPolicy:Pod级别策略,可以设为OnFailure或Never。
backoffLimit:Job级别重试次数上限。
一个最小配置长这样:
apiVersion: batch/v1
kind: Job
metadata:
name: train-retry-demo
spec:
backoffLimit: 3
template:
spec:
restartPolicy: OnFailure
containers:
- name: trainer
image: pytorch/pytorch:2.0.0-cuda11.7-cudnn8-runtime
command: ["python", "train.py"]
volumeMounts:
- name: logs
mountPath: /workspace/logs
volumes:
- name: logs
persistentVolumeClaim:
claimName: train-logs-pvc
backoffLimit: 3表示整个Job最多额外重试3次。restartPolicy: OnFailure表示Pod内容器失败后原地重启,这里有一个容易踩的坑:Pod内重启不消耗backoffLimit次数,它只针对Pod级失败,比如节点被驱逐、Pod被删。
退避间隔不要照搬Web服务
Web服务常用的指数退避,对GPU训练任务未必合适,训练任务通常需要先找回checkpoint,再重新申请资源,如果退避太短,任务会在资源未释放时反复撞墙;如果退避太长,又会放大排队等待成本。
业内专家指出,重试策略必须与断点续训配合,否则只是重复烧钱,多数情况下,训练重试采用固定短间隔加人工熔断,比长尾指数退避更稳。
训练平台故障现场日志保留方法
很多团队以为stdout就是日志,容器退出后还能用

kubectl logs看到,容器一旦被驱逐,或者Pod被控制器清理,标准输出会跟着容器生命周期一起消失,真正能用于事后排查的,是写到持久卷或对象存储的那份落盘日志。
日志不要只写容器标准输出
训练脚本里建议同时输出到两个地方:
stdout:方便实时查看和平台采集。/workspace/logs/train.log:落到PVC或对象存储,容器重建后依然存在。
Python训练脚本里可以这样写:
import logging
logging.basicConfig(
level=logging.INFO,
handlers=[
logging.StreamHandler(),
logging.FileHandler("/workspace/logs/train.log")
]
)
容器编排侧再用一个日志采集sidecar,比如Vector、Fluentd或Filebeat,去tail这个目录,把日志推到对象存储,sidecar和训练容器共享同一个日志卷,训练容器写,sidecar实时上传,训练容器崩了也不影响上传进程。
现场快照比日志更“现场”
日志只能说明程序走到哪一步,看不出当时的环境状态,现场快照才是完整证据。
训练平台保留现场日志时,至少要做三件事:
- 保留训练容器退出前的最后一段日志,可以用
kubectl logs train-xxx -c trainer --previous取到上一次崩溃记录。 - 保留
/workspace/checkpoints下的最新checkpoint文件,这是重试能从断点继续的前提。 - 保留环境变量和GPU拓扑信息,例如
nvidia-smi输出、env输出、/proc/driver/nvidia/version
对于偶发性CUDA错误,现场快照尤其重要,可以配合容器提交命令把崩溃现场保存成镜像:
docker commit train-container train-crash-snapshot:20260101
这样即使原始节点被回收,也能在本地重新拉起容器做复现。
core dump不能丢
如果训练进程崩在底层CUDA或NCCL,文本日志往往只有一行Segmentation fault,真正有用的是core dump。
在容器里提前放开core dump,并指定输出到共享卷:
ulimit -c unlimited echo "/workspace/coredumps/core.%e.%p" > /proc/sys/kernel/core_pattern
需要注意,改core_pattern需要容器具备较高权限,生产环境通常由平台统一配置,保留core dump后,后续可以用gdb或cuda-gdb还原崩溃栈。
深度学习训练中断自动重试怎么设置
不同平台的配置入口不一样,但思路一致:把失败识别、重试次数、checkpoint恢复串起来。
Kubeflow PyTorchJob的自动重试
Kubeflow上跑分布式训练,PyTorchJob的自定义资源里直接配置

restartPolicy。
apiVersion: kubeflow.org/v1
kind: PyTorchJob
metadata:
name: training-retry
spec:
pytorchReplicaSpecs:
Master:
replicas: 1
restartPolicy: OnFailure
template:
spec:
containers:
- name: pytorch
image: pytorch/pytorch:2.0.0-cuda11.7-cudnn8-runtime
这里Master和Worker最好使用不同策略,Master失败一般要重试,因为它负责聚合梯度;Worker失败如果框架支持弹性训练,可以降级继续,也可以按OnFailure策略重建,多数情况下,Master和Worker都设成OnFailure,但要在代码里接住NCCL超时,避免一个Worker卡住拖垮整个Job。
SLURM集群的中断重试
SLURM上跑训练任务,如果节点故障,任务会直接终止,可以在提交脚本里加--requeue参数:
srun --requeue --job-name=train-gpu --gres=gpu:8 python train.py
--requeue的作用是任务被节点故障打断后,自动回到队列等待可用资源,如果训练框架支持checkpoint,作业重新调度后会自动从最近一次保存点继续。
需要注意,--requeue对用户主动取消的任务不生效,只对系统原因导致的失败负责,这个机制适合长时间训练的GPU任务。
PyTorch Lightning的代码级重试
不想依赖平台,也可以在训练框架里做重试,PyTorch Lightning的Trainer直接支持:
from pytorch_lightning import Trainer
trainer = Trainer(
max_retries=3,
retry_strategy="exponential_backoff",
default_root_dir="/workspace/checkpoints"
)
它会在训练异常退出后自动从最新checkpoint恢复,这个方案的好处是平台无关,坏处是重试过程仍然受当前进程和节点限制,节点整个挂掉时,代码级重试也无能为力。
GPU训练任务失败自动重试方案对比
不是所有重试方案都适合GPU训练,下面把常见方案按重试粒度、日志保留能力和适用场景做个对比。
| 方案 | 重试粒度 | 现场日志保留 | 适用场景 | 配置复杂度 |
|---|---|---|---|---|
| Kubernetes Job | Pod级 | 依赖PVC或外部采集 | 单机单卡训练 | 低 |
| Kubeflow PyTorchJob | 角色级 | 依赖持久卷和sidecar | 分布式多卡训练 | 中 |
| SLURM requeue | 作业级 | 依赖集群共享存储 | 超算中心、高校集群 | 低 |
| PyTorch Lightning | 进程级 | 依赖本地目录,节点丢失会丢 |
中小规模、快速实验 |
低 |
| 云平台托管训练 | 任务级 | 一般自带日志服务 | 企业生产环境 | 低 |
从保留现场日志的角度看,云平台托管训练通常最省心,因为它把日志、指标、checkpoint都接到对象存储,但从可控性和成本看,Kubernetes自建方案更灵活,也更容易按北京地区GPU训练平台的需求做定制。
训练任务失败日志排查:从现场日志到根因
现场日志保留下来,不是为了“有日志”,而是为了能快速定位,训练任务失败后的日志排查,一般沿着这条路径走:
kubectl get events --sort-by=.lastTimestamp | grep train-xxx kubectl logs train-xxx -c trainer --previous --tail=200 kubectl describe pod train-xxx | grep -A10 "Events"
三条命令分别看调度事件、上一次崩溃日志、Pod状态变化,多数训练失败都能在这一轮里找到方向。
常见失败模式和检索关键词:
- CUDA out of memory:日志里直接出现,属于显存不足。
- NCCL timeout:分布式通信超时,检查网络和GPU拓扑。
- DataLoader worker exit:数据加载进程异常,减少
num_workers或检查存储IO。 - Checkpoint corrupted:checkpoint文件损坏,需要回到更早的保存点。
日志路径最好固定成约定,例如/workspace/logs/train-{job_id}.log,这样平台侧可以用同一套采集和清理策略管理,不会出现每个任务日志散落各处的情况。
训练任务失败后平台如何自动重试并保留现场日志:Q&A
训练任务失败后平台如何自动重试并保留现场日志?
平台通过任务控制器监听失败事件,先判断退出码是否属于可重试类型,再按照配置的重试次数和退避策略拉起新容器,日志保留依靠两个通道:训练容器把文本日志写入持久卷,sidecar实时上传对象存储;同时平台保留最新checkpoint和可选core dump作为现场快照。
GPU训练任务失败自动重试方案里,重试次数设多少合适?
行业共识认为,日志保留周期至少要覆盖一个完整训练周期加两次重试窗口,重试次数多数建议控制在3次以内,GPU任务的成本按卡时计费,超过3次仍失败,基本可以判断为代码或数据问题,需要人工介入。
北京地区训练平台日志保留多久?
主流云平台在北京地区与其它地域的默认日志服务保留周期多数为7天,部分服务支持延长到30天,自建平台一般将PVC回收策略设为Retain,日志对象存储生命周期按项目要求配置,训练任务日志通常不建议短于7天。
