CronJob은 스케줄에 따라 Job을 자동으로 생성하는 Kubernetes 리소스입니다.
리눅스의 crontab과 동일한 스케줄 문법을 사용하며, 주기적으로 실행해야 하는 배치 작업에 적합합니다.
CronJob (스케줄 정의)
↓ 스케줄마다 생성
Job (실행 단위, 재시도 관리)
↓
Pod (실제 컨테이너 실행)
CronJob이 직접 Pod를 만드는 것이 아니라, Job을 생성하고 Job이 Pod를 생성합니다.
apiVersion: batch/v1
kind: CronJob
metadata:
name: simple-job
namespace: default
spec:
schedule: "*/1 * * * *"
concurrencyPolicy: Forbid
startingDeadlineSeconds: 100
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 1
jobTemplate:
spec:
backoffLimit: 6
completions: 1
parallelism: 1
template:
spec:
containers:
- name: simple-job
image: ap-chuncheon-1.ocir.io/axgu3qzufd5m/simple_job:latest
imagePullPolicy: Always
restartPolicy: OnFailure
Cron 표현식으로 실행 주기를 정의합니다.
┌───────────── 분 (0 - 59)
│ ┌───────────── 시 (0 - 23)
│ │ ┌───────────── 일 (1 - 31)
│ │ │ ┌───────────── 월 (1 - 12)
│ │ │ │ ┌───────────── 요일 (0 - 6, 일요일 = 0)
│ │ │ │ │
* * * * *
| 예시 | 의미 |
|---|---|
*/1 * * * * | 매 1분마다 |
0 * * * * | 매 시간 정각 |
0 0 * * * | 매일 자정 |
0 9 * * 1 | 매주 월요일 오전 9시 |
Job 실패 시 재시도 횟수입니다.
kubectl get job <job-name> -o jsonpath='{.spec.backoffLimit}'
Pod 실패 시 재시작 정책입니다.
| 값 | 동작 |
|---|---|
OnFailure | 실패 시 컨테이너 재시작 |
Never | 재시작하지 않음 (새 Pod 생성) |
Job에서는
Always사용 불가
컨테이너 이미지 pull 정책입니다.
| 값 | 동작 |
|---|---|
Always | 매번 레지스트리에서 pull |
IfNotPresent | 로컬에 없을 때만 pull |
Never | pull하지 않음 |
Always로 설정하면 이미지 업데이트 시 다음 Job부터 새 이미지 적용됩니다.
완료된 Job을 몇 개까지 보존할지 설정합니다.
| 설정 | 기본값 | 의미 |
|---|---|---|
successfulJobsHistoryLimit | 3 | 성공한 Job 보존 개수 |
failedJobsHistoryLimit | 1 | 실패한 Job 보존 개수 |
kubectl get jobs로 확인 시 이 개수만큼만 보입니다.
이전 Job이 아직 실행 중일 때 새 Job을 어떻게 처리할지 정의합니다.
| 값 | 동작 |
|---|---|
Allow | 동시 실행 허용 (기본값) |
Forbid | 새 Job 생성 안 함 (이전 Job 완료 대기) |
Replace | 이전 Job 종료 후 새 Job 생성 |
중복 실행이 문제가 되는 작업은
Forbid권장
스케줄된 시간에 Job을 시작하지 못했을 때, 얼마나 기다릴지 설정합니다.
spec:
startingDeadlineSeconds: 100
completions는 Job이 성공으로 간주되려면 몇 개의 Pod가 성공해야 하는지 설정합니다.
parallelism은 동시에 실행할 Pod 수입니다.
| completions | parallelism | 동작 |
|---|---|---|
| 1 | 1 | Pod 1개 실행, 성공하면 완료 (기본값) |
| 3 | 1 | Pod를 순차적으로 3번 실행 |
| 3 | 3 | Pod 3개 동시 실행, 모두 성공하면 완료 |
| 6 | 2 | Pod 2개씩 동시 실행, 총 6개 성공하면 완료 |
실제 흐름 (completions=6, parallelism=2)
시간 →
Pod1 ████ (성공)
Pod2 ████ (성공)
Pod3 ████ (성공)
Pod4 ████ (실패) → 재시도
Pod4 ████ (성공)
Pod5 ████ (성공)
Pod6 ████ (성공)
→ Job 완료
CronJob은 스케줄마다 Job을 생성합니다.
kubectl get job <job-name> -o yaml
apiVersion: batch/v1
kind: Job
metadata:
name: simple-job-29458577 # CronJob 이름 + 타임스탬프
ownerReferences:
- kind: CronJob
name: simple-job # 이 Job을 만든 CronJob
spec:
backoffLimit: 6
completions: 1
parallelism: 1
template:
spec:
containers:
- name: simple-job
image: ap-chuncheon-1.ocir.io/axgu3qzufd5m/simple_job:latest
imagePullPolicy: Always
restartPolicy: OnFailure
status:
succeeded: 1
completionTime: "2026-01-04T08:17:03Z"
| 항목 | 설명 |
|---|---|
metadata.name | CronJob 이름 + 타임스탬프 |
metadata.ownerReferences | 부모 CronJob 정보 |
status | 실행 결과 (succeeded, completionTime 등) |
jobTemplate에 명시하지 않은 값은 기본값이 자동 주입됩니다.
현재 시간을 출력하는 Rust 프로그램을 CronJob으로 실행합니다.
use chrono::Local;
fn main() {
let now = Local::now();
println!("Current time: {}", now.format("%Y-%m-%d %H:%M:%S"));
}
kubectl apply -f simple-job.yaml
kubectl get cronjob simple-job
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
simple-job */1 * * * * False 0 35s 10m
kubectl get jobs
NAME COMPLETIONS DURATION AGE
simple-job-29458568 1/1 2s 3m
simple-job-29458569 1/1 2s 2m
simple-job-29458570 1/1 2s 1m
kubectl logs -l job-name=simple-job-29458570
Current time: 2026-01-04 17:10:02