A CronJob's runs overlap and pile up — fix it with concurrencyPolicy and history limits.
This CronJob's runs sometimes take longer than its interval, so a new run starts while the last is still going, and finished Jobs accumulate.
Constraints: prevent overlapping runs and bound how many completed/failed Jobs are retained. Change only CronJob spec fields — do not touch the schedule or the container.
apiVersion: batch/v1
kind: CronJob
metadata:
name: report
spec:
schedule: "*/5 * * * *"
# runs can take 8 min and overlap the next tick;
# completed/failed Jobs pile up in the namespace
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: report
image: report:1.4
Add the fields that stop overlap and cap retained Job history.
Set concurrencyPolicy: Forbid so a new run is skipped while the previous Job still runs (or Replace to cancel the old). Cap retained history with successfulJobsHistoryLimit and failedJobsHistoryLimit (e.g. 3 and 1); startingDeadlineSeconds skips long-missed ticks. Forbid stops the pile-up; the limits stop old Jobs cluttering the namespace.
- ✗Thinking
concurrencyPolicy: Allowprevents overlap (it permits it) - ✗Confusing history limits with retry or parallelism settings
- ✗Using
suspend(which stops all runs) to fix overlap
- →How do
ForbidandReplacediffer when a run is still in flight? - →What does
startingDeadlineSecondsdo when the controller misses a schedule?
Solution
apiVersion: batch/v1
kind: CronJob
metadata:
name: report
spec:
schedule: "*/5 * * * *"
concurrencyPolicy: Forbid # skip a new run while the last is still going
startingDeadlineSeconds: 120 # do not fire long-missed ticks
successfulJobsHistoryLimit: 3 # keep 3 successful Jobs
failedJobsHistoryLimit: 1 # keep 1 failed Job
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: report
image: report:1.4
Job has not finished (Replace would instead cancel the old one and start the new; Allow, the default, is what permits overlap in the first place).
this clears the namespace clutter, and is unrelated to retry count.
very old ticks are not "caught up".
concurrencyPolicy: Forbid— the controller skips a tick if the previoussuccessful/failedJobsHistoryLimitbound how many finished Jobs are retained —startingDeadlineSeconds— if the controller missed a window (e.g. it was down),