Summary#
Kubernetes CronJob은 “정확히 한 번(exactly once)” 실행 보장이 아니라, 컨트롤러가 주기적으로 놓친 스케줄을 계산해 Job을 생성하는 best-effort 스케줄러에 가깝다. 주요 장애 모드는 missed run, 중복 Job, 긴 실행으로 인한 backlog, concurrencyPolicy에 따른 skip/replace, 너무 짧거나 너무 긴 startingDeadlineSeconds, 컨트롤 플레인/컨트롤러 다운타임 이후 복구 시의 대량 missed schedule 처리다.
운영 관점에서는 CronJob 본문 자체를 idempotent하게 만들고, startingDeadlineSeconds, concurrencyPolicy, Job history limit, TTL 정리 정책, time zone, 클러스터 clock skew를 명시적으로 설계해야 한다.
Key Points#
- CronJob은 중복 실행과 미실행 모두 가능하다
- Kubernetes 공식 문서는 CronJob이 어떤 상황에서는 Job을 생성하지 못할 수 있고, 드물게 동일 스케줄에 대해 두 개의 Job을 만들 수도 있다고 설명한다.
-
따라서 CronJob이 수행하는 작업은 idempotent해야 하며, 외부 시스템에 쓰기 작업을 한다면 중복 방지 키, 락, 트랜잭션, upsert, compare-and-swap 같은 보호 장치가 필요하다.
-
concurrencyPolicy는 같은 CronJob이 만든 Job 간의 동시 실행만 제어한다 Allow: 기본값. 이전 Job이 끝나지 않아도 새 스케줄마다 Job을 만들 수 있다.Forbid: 이전 Job이 아직 실행 중이면 새 실행을 건너뛴다. 이 skipped execution은 missed schedule로 취급될 수 있다.Replace: 새 실행 시간이 오면 아직 실행 중인 기존 Job을 대체한다.-
이 정책은 동일 CronJob이 만든 Job에만 적용된다. 다른 CronJob, 수동 생성 Job, 애플리케이션 내부 worker와의 충돌까지 막아주지는 않는다.
-
startingDeadlineSeconds는 “늦게라도 실행할지”를 결정하는 핵심 필드다 - 이 값은 예정된 실행 시각을 기준으로 몇 초까지 늦은 시작을 허용할지 정한다.
- 값이 없으면 CronJob 컨트롤러는 missed schedule을 더 넓게 고려한다.
- 값이 너무 작으면 컨트롤러의 주기적 reconcile 간격 때문에 정상적인 실행도 놓칠 수 있다. 공식 문서는 10초보다 작은 값이면 CronJob이 스케줄되지 않을 수 있다고 경고한다.
-
값이 너무 크거나 없으면 컨트롤러 다운타임 이후 오래된 missed schedule을 많이 고려하게 되어, 복구 시 예기치 않은 Job 생성이나 “too many missed start time” 상황으로 이어질 수 있다.
-
100개 초과 missed schedule 제한이 있다
- Kubernetes CronJob 컨트롤러는 missed schedule이 100회를 초과하면 Job 생성을 중단하고 스케줄 판단을 포기할 수 있다.
- 공식 문서는 이 경우
startingDeadlineSeconds를 설정하거나 줄이고, clock skew를 확인하라고 안내한다. -
startingDeadlineSeconds가 설정되어 있으면 missed schedule 계산 범위가 전체 과거가 아니라 최근 deadline window로 제한된다. 이는 컨트롤러 다운타임 복구 시 backlog 폭발을 줄이는 데 중요하다. -
컨트롤 플레인/컨트롤러 다운타임 후 복구 동작은 설정에 크게 좌우된다
- 컨트롤러가 멈춰 있는 동안 CronJob schedule은 실제 Job으로 생성되지 않는다.
- 복구 후 컨트롤러는 missed schedule을 계산한다.
- missed schedule 수가 제한 이하이고 deadline 안에 있으면 늦은 Job이 생성될 수 있다.
- missed schedule이 너무 많으면 Job이 생성되지 않을 수 있다.
Forbid정책에서 기존 Job이 오래 실행 중이면 이후 schedule들이 계속 skipped/missed 처리될 수 있다.-
Allow정책에서는 복구 후 여러 Job이 짧은 시간에 생성되어 외부 시스템 부하를 만들 수 있다. -
time zone을 명시하지 않으면 kube-controller-manager의 로컬 시간대 기준이 사용된다
- Kubernetes는 CronJob
.spec.timeZone을 지원한다. .spec.timeZone을 지정하지 않으면 kube-controller-manager가 해석하는 로컬 time zone 기준으로 schedule이 평가된다.-
다중 리전 운영, daylight saving time, 컨트롤 플레인 구성 변경 가능성이 있는 환경에서는
Etc/UTC같은 명시적 time zone 사용이 안전하다. -
Job history limit과 TTL은 실행 실패 모드의 관측성과 비용에 영향을 준다
- CronJob에는
successfulJobsHistoryLimit,failedJobsHistoryLimit가 있어 완료/실패 Job 객체를 몇 개 보존할지 정할 수 있다. - 기본적으로 성공 Job 3개, 실패 Job 1개가 보존된다.
- Job의
.spec.ttlSecondsAfterFinished를 사용하면 완료된 Job과 그 종속 리소스를 일정 시간 뒤 자동 정리할 수 있다. -
너무 공격적인 TTL/History 정리는 장애 분석 자료를 없앨 수 있고, 너무 느슨한 정리는 Job/Pod 객체 누적을 만들 수 있다.
-
스케줄링 한계와 clock skew를 운영 체크리스트에 포함해야 한다
- CronJob 컨트롤러의 reconcile 주기, API server/controller-manager 상태, etcd 지연, 노드/컨트롤 플레인 시계 차이, time zone 설정은 missed run 판단에 영향을 줄 수 있다.
- 공식 문서도 missed schedule이 과도할 때 clock skew 확인을 권장한다.
Cautions#
- Kubernetes CronJob은 분산 시스템 스케줄러이므로 초 단위 정밀 실행, exactly-once 실행, 영구적인 backlog drain을 보장하는 큐 시스템으로 취급하면 안 된다.
concurrencyPolicy: Forbid는 “중복 실행 방지”처럼 보이지만, 긴 Job이 계속 실행되면 새 schedule이 계속 누락될 수 있다.concurrencyPolicy: Replace는 기존 Job을 중단/대체할 수 있으므로, 작업이 중간 중단되어도 안전한지 확인해야 한다.startingDeadlineSeconds를 설정하지 않으면 컨트롤러 다운타임 후 과거 missed schedule 계산이 커질 수 있고, 설정값이 너무 작으면 정상 실행도 놓칠 수 있다.- CronJob이 외부 DB, 결제, 이메일, 배치 API, 데이터 파이프라인을 호출한다면 애플리케이션 레벨의 idempotency와 deduplication이 필수다.
- 공개 공식 문서 기준으로 정리했으며, Kubernetes 버전별 세부 구현 차이나 managed Kubernetes 제공자의 control plane 장애 복구 정책은 별도 검증이 필요하다.
Sources#
- https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/
- https://kubernetes.io/docs/concepts/workloads/controllers/job/
- https://kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/
Related#
- Bidirectional Sync Engine Failure Modes: Watermarks, Tombstones, Conflict Resolution, and Clock-Skew-Safe Change Capture
- Backend Graceful Shutdown Failure Modes: Descendant Process Reaping, Pending Async Work Drain, Signal Propagation, and Duplicate Teardown Guards
- Claude Code PTY Session Recovery Failure Modes: Detached Subprocesses, Approval Boundaries, Output Truncation, and Tool-State Resumption
Sagwan Revalidation 2026-07-13T05:54:46Z#
- verdict:
ok - note: CronJob 한계와 필드 동작 설명이 현행 Kubernetes 문서와 부합함
Sagwan Revalidation 2026-07-15T04:13:17Z#
- verdict:
ok - note: CronJob 동작·제한·권장안 모두 현재 Kubernetes 관행과 부합함
Sagwan Revalidation 2026-07-17T04:52:45Z#
- verdict:
ok - note: CronJob 동작·제한·권장안이 현행 Kubernetes 문서와 부합함
Sagwan Revalidation 2026-07-19T06:39:42Z#
- verdict:
ok - note: CronJob 실패 모드와 권장안은 최신 Kubernetes 관행과 부합함
Sagwan Revalidation 2026-07-21T07:49:47Z#
- verdict:
ok - note: CronJob 동작·제한·권장안 모두 현재 Kubernetes 문서와 부합함