Kubernetes Job 的 backoffLimit 和 restartPolicy 组合,踩过才知道的四个坑
批处理任务用 Job 跑,最容易被 backoffLimit 和 restartPolicy 这两个字段的组合绕进去。下面四个场景都是实际踩过的。
一、restartPolicy 只能是 OnFailure 或 Never
Job 的 pod 模板里写 Always 会直接被 API Server 拒绝。想让任务失败后重试,就得用 OnFailure,让容器在同一个 Pod 里重启。
区别在于:
- OnFailure:Pod 不重建,容器原地重启,节点资源占用不变,日志留在同一个 Pod 里,排查方便。
- - Never:Pod 失败后新建一个 Pod,旧 Pod 留成 Completed/Error 状态,能看到每次失败的现场,但节点上会堆很多 Pod。
大量短任务重试时,Never 更容易把节点上的 Pod 数量顶到上限,kubelet 报 too many pods。
二、backoffLimit 数的是「失败次数」,不是「总尝试次数」
默认 backoffLimit 是 6。含义是失败 6 次之后 Job 被判 Failed,所以总尝试次数是 7 次(首次 + 6 次重试)。
重试间隔是指数退避:10s、20s、40s……最长到 6 分钟封顶。所以一个必然失败的任务,跑完 7 次大约要 10 分钟以上,不是立刻失败。
如果想让任务快速失败,把 backoffLimit 设小,比如 1 或 2。
三、Parallelism 和 completions 一起改才会真正并行
只设 parallelism 不设 completions,Job 的完成条件是「至少一个 Pod 成功」,此时其他并行的 Pod 会被终止。
想让 N 个分片全跑完,必须 completions=N,同时 parallelism 控制并发度。配合索引可以用 completionMode: Indexed,每个 Pod 拿到 JOB_COMPLETION_INDEX,直接当分片号用。
四、Pod 卡在 Pending 不算失败,backoffLimit 不会触发
backoffLimit 只统计「Pod 进入 Failed 阶段」的次数。如果 Pod 一直 Pending(资源不足、亲和性不满足、PVC 挂不上),Job 会一直等下去,既不失败也不成功。
这种情况要么配 activeDeadlineSeconds 兜底,要么在调度层把资源配额调够。activeDeadlineSeconds 到达后 Job 直接被标记失败,正在跑的 Pod 也会被删掉。
排查顺序
- kubectl describe job 看 Events 里的「BackoffLimitExceeded」还是「DeadlineExceeded」
- 2. kubectl get pods -l job-name=xxx 看是 Completed、Error 还是 Pending
- 3. Pending 就 describe pod 看调度原因
- 4. Error 就 kubectl logs --previous 看上一次容器退出码
把这四个字段的关系理清,Job 的失败原因基本一眼能定位。
- 点赞
- 收藏
- 关注作者
评论(0)