Job & CronJob #

Deployment, StatefulSet, dan DaemonSet semuanya dirancang untuk workload yang berjalan terus-menerus. Tapi tidak semua pekerjaan perlu berjalan selamanya — ada task yang perlu dijalankan sekali, selesai, lalu berhenti: migrasi data, generate report, kirim email batch, proses antrian. Untuk kebutuhan ini, Kubernetes menyediakan Job dan CronJob.

Job #

Job memastikan satu atau lebih Pod berhasil menyelesaikan tugasnya. Berbeda dari Deployment yang me-restart container yang keluar, Job menganggap exit code 0 sebagai keberhasilan dan berhenti membuat Pod baru setelah berhasil.

Struktur Manifest Job #

apiVersion: batch/v1
kind: Job
metadata:
  name: db-migration
  namespace: production
spec:
  completions: 1           # jumlah Pod yang harus berhasil selesai
  parallelism: 1           # berapa Pod yang berjalan bersamaan
  backoffLimit: 3          # maksimum retry jika Pod gagal
  activeDeadlineSeconds: 300   # maksimum durasi Job (dalam detik)

  template:
    spec:
      restartPolicy: Never     # Never atau OnFailure — BUKAN Always
      containers:
      - name: migrator
        image: my-app:v2
        command:
        - /app/migrate
        - up
        env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: app-secret
              key: DATABASE_URL
        resources:
          requests:
            cpu: "500m"
            memory: "256Mi"
          limits:
            cpu: "1000m"
            memory: "512Mi"

restartPolicy di Job harus Never atau OnFailure — tidak boleh Always. Dengan Never, jika container gagal Kubernetes membuat Pod baru (sampai backoffLimit tercapai). Dengan OnFailure, Kubernetes me-restart container yang sama dalam Pod yang sama.


Completions dan Parallelism #

Kombinasi dua field ini menentukan pola eksekusi Job:

completions: 1, parallelism: 1  (default)
  → Jalankan 1 Pod, selesai saat Pod berhasil
  → Pola: task tunggal

completions: 5, parallelism: 1
  → Jalankan 1 Pod dalam satu waktu
  → Total 5 Pod harus berhasil (satu per satu)
  → Pola: sequential batch

completions: 10, parallelism: 3
  → Jalankan 3 Pod secara bersamaan
  → Total 10 Pod harus berhasil
  → Pola: parallel batch

completions: tidak diset, parallelism: 3
  → Jalankan 3 Pod bersamaan, Job selesai ketika semua Pod selesai
  → Pola: work queue (setiap Pod mengambil task dari queue)

Contoh: Parallel Batch Processing #

spec:
  completions: 100       # proses 100 item
  parallelism: 10        # 10 worker bersamaan
  backoffLimit: 5

  template:
    spec:
      restartPolicy: Never
      containers:
      - name: processor
        image: my-processor:v1
        env:
        - name: JOB_COMPLETION_INDEX    # Kubernetes inject indeks otomatis (1.21+)
          valueFrom:
            fieldRef:
              fieldPath: metadata.annotations['batch.kubernetes.io/job-completion-index']
        # Processor menggunakan JOB_COMPLETION_INDEX untuk menentukan
        # item mana yang perlu diproses (item 0-9, 10-19, dst)

Failure Handling #

Jika Pod gagal (exit code != 0):

  backoffLimit: 3
    → Retry pertama: langsung
    → Retry kedua: tunggu 10 detik
    → Retry ketiga: tunggu 20 detik (exponential backoff)
    → Setelah 3 kali gagal: Job ditandai Failed

  activeDeadlineSeconds: 300
    → Jika Job belum selesai dalam 300 detik: hentikan semua Pod
    → Job ditandai Failed dengan reason: DeadlineExceeded
    → Berguna untuk menghindari Job yang hang selamanya
# Lihat status Job
kubectl get jobs

# Output:
# NAME           COMPLETIONS   DURATION   AGE
# db-migration   1/1           45s        2m     ← sukses
# data-cleanup   0/1           3m         3m     ← masih berjalan atau gagal

# Detail Job termasuk events
kubectl describe job db-migration

# Lihat log Pod dari Job yang sudah selesai
kubectl logs job/db-migration

Pembersihan Job Otomatis #

Job yang sudah selesai tidak otomatis dihapus — ia tetap ada beserta Pod-nya (dalam status Completed). Ini berguna untuk melihat log, tapi bisa mengotori cluster jika Job sering dijalankan.

spec:
  ttlSecondsAfterFinished: 3600    # hapus Job (dan Pod-nya) 1 jam setelah selesai
  # ttlSecondsAfterFinished: 0     # hapus langsung setelah selesai

CronJob #

CronJob menjalankan Job secara terjadwal, menggunakan sintaks cron yang sama dengan cron di Linux.

Struktur Manifest CronJob #

apiVersion: batch/v1
kind: CronJob
metadata:
  name: daily-report
  namespace: production
spec:
  schedule: "0 2 * * *"         # setiap hari jam 02:00
  timezone: "Asia/Jakarta"      # timezone (Kubernetes 1.25+)

  concurrencyPolicy: Forbid     # Allow | Forbid | Replace
  successfulJobsHistoryLimit: 3 # simpan log 3 Job terakhir yang sukses
  failedJobsHistoryLimit: 1     # simpan log 1 Job terakhir yang gagal

  jobTemplate:                  # template Job yang akan dibuat
    spec:
      activeDeadlineSeconds: 600
      backoffLimit: 2
      template:
        spec:
          restartPolicy: OnFailure
          containers:
          - name: reporter
            image: my-reporter:v1
            command:
            - /app/generate-report
            - --date=$(date +%Y-%m-%d)
            resources:
              requests:
                cpu: "200m"
                memory: "256Mi"
              limits:
                cpu: "500m"
                memory: "512Mi"

Sintaks Schedule Cron #

┌──────────── menit (0-59)
│ ┌────────── jam (0-23)
│ │ ┌──────── hari dalam bulan (1-31)
│ │ │ ┌────── bulan (1-12)
│ │ │ │ ┌──── hari dalam minggu (0-7, 0 dan 7 = Minggu)
│ │ │ │ │
* * * * *

Contoh jadwal umum:
"*/5 * * * *"    → setiap 5 menit
"0 * * * *"      → setiap jam tepat
"0 2 * * *"      → setiap hari jam 02:00
"0 2 * * 1"      → setiap Senin jam 02:00
"0 2 1 * *"      → setiap tanggal 1, jam 02:00
"0 2 * * 1-5"    → setiap hari kerja jam 02:00

Concurrency Policy #

CronJob punya field concurrencyPolicy untuk menangani situasi di mana jadwal baru tiba sebelum Job sebelumnya selesai:

Allow (default):
  → Boleh ada beberapa Job berjalan bersamaan
  → Gunakan untuk task yang benar-benar independen

Forbid:
  → Jika Job sebelumnya masih berjalan, jadwal baru di-skip
  → Gunakan untuk task yang tidak boleh berjalan bersamaan
    (misalnya: cleanup yang modifikasi database)

Replace:
  → Jika Job sebelumnya masih berjalan, hentikan dan ganti dengan yang baru
  → Gunakan untuk task di mana hanya yang terbaru yang relevan
    (misalnya: sync data yang selalu fresh dari awal)

Menjalankan CronJob Secara Manual #

Berguna untuk testing atau menjalankan task di luar jadwal:

# Trigger CronJob manual
kubectl create job --from=cronjob/daily-report manual-run-$(date +%Y%m%d)

# Pantau Job yang berjalan
kubectl get jobs
kubectl logs job/manual-run-20240115

Anti-Pattern: Job untuk Long-Running Service #

ANTI-PATTERN: gunakan Job untuk service yang seharusnya terus berjalan

spec:
  template:
    spec:
      restartPolicy: Never
      containers:
      - name: api-server       # ← SALAH: api server bukan task yang selesai
        image: my-api:v1

Masalah:
  → Job selesai ketika container exit → service mati dan tidak dijalankan ulang
  → Jika container crash, Job retry sampai backoffLimit lalu berhenti
  → Tidak ada self-healing seperti Deployment

BENAR: gunakan Deployment untuk long-running service

Ringkasan #

  • Job untuk task yang selesai, bukan service — exit code 0 berarti sukses; Kubernetes tidak me-restart Pod yang berhasil selesai.
  • restartPolicy: Never vs OnFailureNever membuat Pod baru saat gagal (cocok untuk task yang tidak boleh diulang di Pod yang sama), OnFailure me-restart container dalam Pod yang sama.
  • completions dan parallelism — kombinasi keduanya menentukan pola eksekusi: sequential, parallel, atau work queue.
  • activeDeadlineSeconds wajib untuk task produksi — mencegah Job yang hang selamanya karena bug atau resource starvation.
  • ttlSecondsAfterFinished untuk pembersihan otomatis — Job yang selesai tidak otomatis dihapus; tetapkan TTL agar cluster tidak penuh dengan Pod Completed.
  • concurrencyPolicy: Forbid untuk task yang tidak boleh overlap — penting untuk task yang memodifikasi data bersama seperti database cleanup atau report generation.

← Sebelumnya: DaemonSet   Berikutnya: Scheduler Workflow →

About | Author | Content Scope | Editorial Policy | Privacy Policy | Disclaimer | Contact