Job 与 CronJob 失败是什么情况
Job 负责一次性批处理,CronJob 按时间表周期性创建 Job。失败表现分三类:Pod 根本没起来(调度或镜像问题)、Pod 起来但命令失败(退出码非 0、重试耗尽)、CronJob 到点没跑(被 suspend、并发策略挡掉、错过时间窗)。三类原因分散在不同对象上,先分清属于哪一类再动手。
基本信息
| 看 Job | kubectl describe job 看 Conditions 与 Events |
|---|---|
| 看 Pod | kubectl get pods -l job-name=<名称> 逐个看退出码与原因 |
| 重试 | backoffLimit 用尽后 Job 被标记为 Failed |
| 重启策略 | Job 的 restartPolicy 只能是 Never 或 OnFailure |
| CronJob 字段 | schedule、suspend、concurrencyPolicy、startingDeadlineSeconds |
| 历史保留 | successfulJobsHistoryLimit 与 failedJobsHistoryLimit |
失败分类与处置
| 现象 | 位置 | 处置 |
|---|---|---|
| Pod 一直 Pending | Job 事件里的 FailedScheduling | 按调度问题处理:资源、污点、亲和性 |
| Pod 报 ErrImagePull | Pod 事件 | 核对镜像名、仓库认证与网络 |
| 命令退出码非 0 | Pod 日志与容器状态 | 先修脚本,再调重试次数与间隔 |
| 到点没创建 Job | CronJob 的 LAST SCHEDULE 与 Events | 查 suspend、并发策略与时间窗 |
| 任务被中途截断 | Pod 被删除或节点回收 | 调大 activeDeadlineSeconds,完善优雅退出 |
排查命令
排查命令
kubectl describe job backup-20261012 # 看 Conditions 与 Events
kubectl get pods -l job-name=backup-20261012 # 逐个 Pod 的退出状态
kubectl get cronjob -o wide # SCHEDULE / SUSPEND / ACTIVE
kubectl logs job/backup-20261012 --tail=100 # 批处理脚本的实际输出
kubectl get job -o custom-columns=NAME:.metadata.name,SUCCEEDED:.status.succeeded,FAILED:.status.failed
kubectl patch cronjob nightly -p '{"spec":{"suspend":true}}' # 临时停掉定时任务典型使用场景
- 夜间备份某天没跑,需要区分是没创建 Job 还是创建了但失败
- 新上线的 CronJob 同一时刻跑了多份,需要调整并发策略
- 批处理偶发失败被重试掩盖,要找到最终那次失败的日志
- 任务执行时间超过调度间隔造成堆积,需要改 schedule 或加分布式锁
- 排查是集群调度问题还是脚本本身问题,先看 Job 事件再读日志
定时任务该跑没跑,先看 LAST SCHEDULE 与 Events:被 suspend、concurrencyPolicy 为 Forbid 而上一次尚未结束、startingDeadlineSeconds 太短错过时间窗,这三种情况会让本轮直接消失。
Job 的 restartPolicy 只接受 Never 与 OnFailure,写成 Always 会被 API 直接拒绝;容器内重试与 Pod 级重试是两套机制,想让同一容器实例继续干活就让脚本自己重试。
批处理脚本必须具备幂等性:重试和重复调度都可能让同一批数据被处理两次,写库前先做去重或状态判断。