CronJob 看似简单,但上一次还没跑完怎么办、暂停之后会不会补跑、错过了怎么处理,每一条都有坑。这篇让五个 CronJob 在同一分钟起跑,真跑五分钟,把 concurrencyPolicy 三种取值、错过的调度、startingDeadlineSeconds 和历史清理都量出来。
cj-allow(concurrencyPolicy: Allow):在 287 秒的观察期里一共创建了 5 个 Job:
Job …29860670 创建于 + 4.0s;最后一次被看到是 +261.1s(之后消失了:被删除或被替换)
Job …29860671 创建于 + 64.0s;最后一次被看到是 +287.2s
Job …29860672 创建于 +124.0s;最后一次被看到是 +287.2s
Job …29860673 创建于 +184.0s;最后一次被看到是 +287.2s
Job …29860674 创建于 +244.0s;最后一次被看到是 +287.2s
cj-forbid(concurrencyPolicy: Forbid):在 287 秒的观察期里一共创建了 4 个 Job:
Job …29860670 创建于 + 4.0s;最后一次被看到是 +287.2s
Job …29860671 创建于 + 81.0s;最后一次被看到是 +287.2s
Job …29860672 创建于 +160.0s;最后一次被看到是 +287.2s
Job …29860673 创建于 +238.0s;最后一次被看到是 +287.2s
cj-replace(concurrencyPolicy: Replace):在 287 秒的观察期里一共创建了 5 个 Job:
Job …29860670 创建于 + 4.0s;最后一次被看到是 + 62.4s(之后消失了:被删除或被替换)
Job …29860671 创建于 + 64.0s;最后一次被看到是 +120.9s(之后消失了:被删除或被替换)
Job …29860672 创建于 +124.0s;最后一次被看到是 +182.6s(之后消失了:被删除或被替换)
Job …29860673 创建于 +184.0s;最后一次被看到是 +241.5s(之后消失了:被删除或被替换)
Job …29860674 创建于 +244.0s;最后一次被看到是 +287.2s
CronJob 控制器的事件:
cj-allow SuccessfulCreate x1 Created job cj-allow-29860670
cj-forbid SuccessfulCreate x1 Created job cj-forbid-29860670
cj-replace SuccessfulCreate x1 Created job cj-replace-29860670
cj-allow SuccessfulCreate x1 Created job cj-allow-29860671
cj-replace SuccessfulDelete x1 Deleted job cj-replace-29860670
cj-replace SuccessfulCreate x1 Created job cj-replace-29860671
cj-allow SawCompletedJob x1 Saw completed job: cj-allow-29860670, condition: Complete
cj-forbid SawCompletedJob x1 Saw completed job: cj-forbid-29860670, condition: Complete
cj-forbid SuccessfulCreate x1 Created job cj-forbid-29860671
cj-allow SuccessfulCreate x1 Created job cj-allow-29860672
cj-deadline SuccessfulCreate x1 Created job cj-deadline-29860672
cj-replace SuccessfulDelete x1 Deleted job cj-replace-29860671
cj-replace SuccessfulCreate x1 Created job cj-replace-29860672
cj-deadline SawCompletedJob x1 Saw completed job: cj-deadline-29860672, condition: Complete
cj-allow SawCompletedJob x1 Saw completed job: cj-allow-29860671, condition: Complete
cj-miss SuccessfulCreate x1 Created job cj-miss-29860672
cj-miss SawCompletedJob x1 Saw completed job: cj-miss-29860672, condition: Complete
cj-forbid SawCompletedJob x1 Saw completed job: cj-forbid-29860671, condition: Complete
cj-forbid SuccessfulCreate x1 Created job cj-forbid-29860672
cj-allow SuccessfulCreate x1 Created job cj-allow-29860673
cj-deadline SuccessfulCreate x1 Created job cj-deadline-29860673
cj-miss SuccessfulCreate x1 Created job cj-miss-29860673
cj-replace SuccessfulDelete x1 Deleted job cj-replace-29860672
cj-replace SuccessfulCreate x1 Created job cj-replace-29860673
cj-deadline SawCompletedJob x1 Saw completed job: cj-deadline-29860673, condition: Complete
cj-miss SawCompletedJob x1 Saw completed job: cj-miss-29860673, condition: Complete
cj-allow SawCompletedJob x1 Saw completed job: cj-allow-29860672, condition: Complete
cj-forbid SawCompletedJob x2 Saw completed job: cj-forbid-29860672, condition: Complete
cj-forbid SuccessfulCreate x1 Created job cj-forbid-29860673
cj-allow SuccessfulCreate x1 Created job cj-allow-29860674
cj-deadline SuccessfulCreate x1 Created job cj-deadline-29860674
cj-forbid JobAlreadyActive x10 Not starting job because prior execution is running and concurrency policy is Forbid
cj-miss SuccessfulCreate x1 Created job cj-miss-29860674
cj-replace SuccessfulDelete x1 Deleted job cj-replace-29860673
cj-replace SuccessfulCreate x1 Created job cj-replace-29860674
cj-deadline SawCompletedJob x1 Saw completed job: cj-deadline-29860674, condition: Complete
cj-miss SawCompletedJob x1 Saw completed job: cj-miss-29860674, condition: Complete
cj-allow SuccessfulDelete x1 Deleted job cj-allow-29860670
cj-allow SawCompletedJob x2 Saw completed job: cj-allow-29860673, condition: Complete每个 Job 睡 75 秒、每分钟一次,所以相邻两个必然重叠。Allow(默认)每个整分都创建新 Job,同时有两个在跑。Forbid:21:51:00 那次因为上一个还在运行而不创建,事件 JobAlreadyActive: Not starting job because prior execution is running and concurrency policy is Forbid(累计 10 次);等上一个完成后,控制器发现 21:51 的调度还没执行,于是在 +81.0 秒补建它,之后 +160.0、+238.0 秒——被跳过的调度只是推迟,并且越拖越晚。Replace:每个整分先 SuccessfulDelete 删掉仍在运行的上一个 Job 再创建新的,每个 Job 活 58~62 秒,从不跑完。
cj-miss 暂停了约 150 秒(期间错过 2 次整分调度),恢复后 137 秒内创建的 Job:[('29860672', -0.1), ('29860673', 33.9), ('29860674', 93.9)](时间是相对恢复那一刻的秒数)suspend: true 暂停约 150 秒(错过了 3 个整分)后恢复:只立刻创建了一个 Job——最近那次整分的(cj-miss-29860672,后缀是调度时刻的分钟数),没有把 3 次都补上;之后回到每个整分一个(+33.9 秒、+93.9 秒)。
cj-deadline(startingDeadlineSeconds=10)在某个整分之后约 31 秒恢复(那个整分的调度已经错过了 31 秒 > 10 秒):恢复后创建的 Job:[('29860672', 29.0), ('29860673', 89.0), ('29860674', 149.0)]
事件:[('SuccessfulCreate', 'Created job cj-deadline-29860672'), ('SawCompletedJob', 'Saw completed job: cj-deadline-29860672, condition: Complete'), ('SuccessfulCreate', 'Created job cj-deadline-29860673'), ('SawCompletedJob', 'Saw completed job: cj-deadline-29860673, condition: Complete'), ('SuccessfulCreate', 'Created job cj-deadline-29860674'), ('SawCompletedJob', 'Saw completed job: cj-deadline-29860674, condition: Complete')]设 startingDeadlineSeconds: 10 的 CronJob 在整分之后约 31 秒才恢复:那次调度已经晚了 31 秒,超过截止时间,不补;第一个 Job 要等到下一个整分(恢复后 +29.0 秒)才创建。不设这个字段时,错过的调度总是可以补,所以上面 Forbid 的 Job 才会越拖越晚。对“过时就没意义”的任务一定要设。
cj-miss 的 status:lastScheduleTime=2026-10-10T13:54:00Z lastSuccessfulTime=2026-10-10T13:54:08Z active=0;默认保留成功 Job 3 个、失败 1 个 命名空间里现存的 Job 总数 15(每个 CronJob 只留着最近成功的 3 个以及还在运行的)
status.lastScheduleTime 是最后一次创建 Job 的调度时刻,lastSuccessfulTime 是最后一次成功完成的时间。successfulJobsHistoryLimit 默认 3、failedJobsHistoryLimit 默认 1,多出来的旧 Job 会被自动删除(事件 SuccessfulDelete:cj-allow 删掉了最老的一个)。五个 CronJob 一共还剩 15 个 Job。