Job: Sekali Jalan Sampai Selesai
apiVersion: batch/v1
kind: Job
metadata:
name: migrasi-basisdata
spec:
backoffLimit: 3 # coba ulang maksimal 3 kali
activeDeadlineSeconds: 600 # batas waktu keseluruhan
ttlSecondsAfterFinished: 3600 # hapus otomatis setelah 1 jam
template:
spec:
restartPolicy: Never # atau OnFailure — TIDAK BOLEH Always
containers:
- name: migrasi
image: registry.contoh.com/pesanan:2.4.0
command: ["./migrate", "up"]
Tanpa ini, setiap Job yang selesai beserta pod-nya tetap tersimpan selamanya di kluster. Sebuah CronJob yang berjalan tiap lima menit akan menumpuk ribuan objek dalam sebulan, membebani etcd dan membuat kubectl get pods tidak terbaca.
Job Paralel
spec: completions: 100 # total pekerjaan yang harus selesai parallelism: 10 # berapa yang berjalan bersamaan # Atau mode indeks — tiap pod tahu nomor dirinya completionMode: Indexed # Tersedia sebagai variabel JOB_COMPLETION_INDEX
CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
name: laporan-harian
spec:
schedule: "0 7 * * 1-5" # 07:00 Senin–Jumat
timeZone: "Asia/Jakarta"
concurrencyPolicy: Forbid # jangan tumpang tindih
startingDeadlineSeconds: 300
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 3
jobTemplate:
spec:
backoffLimit: 2
template:
spec:
restartPolicy: OnFailure
containers:
- name: laporan
image: registry.contoh.com/laporan:1.2.0
| concurrencyPolicy | Perilaku bila jadwal tiba saat yang sebelumnya masih jalan |
|---|---|
Allow | Jalankan bersamaan (bawaan) — sering menyebabkan masalah |
Forbid | Lewati jadwal ini |
Replace | Hentikan yang lama, mulai yang baru |
Bila sebuah laporan biasanya selesai dalam 3 menit tetapi suatu hari melambat menjadi 20 menit, dengan jadwal tiap 5 menit Anda akan punya empat proses berjalan bersamaan — saling berebut database dan mungkin menghasilkan data ganda. Untuk hampir semua tugas terjadwal, Forbid adalah pilihan yang benar.
Dalam keadaan tertentu — control plane sibuk, node bermasalah — sebuah jadwal bisa terlewat atau terjadi dua kali. Tugas terjadwal Anda harus idempoten. Jangan menulis tugas yang mengasumsikan ia berjalan tepat satu kali, terutama untuk hal seperti penagihan.
DaemonSet
Menjalankan tepat satu pod di setiap node — dipakai untuk agen infrastruktur.
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: pengumpul-log
spec:
selector:
matchLabels: { app: pengumpul-log }
template:
metadata:
labels: { app: pengumpul-log }
spec:
tolerations:
- operator: Exists # jalan di SEMUA node, termasuk yang ber-taint
containers:
- name: agen
image: grafana/alloy:latest
volumeMounts:
- name: log-kontainer
mountPath: /var/log/containers
readOnly: true
volumes:
- name: log-kontainer
hostPath:
path: /var/log/containers
Kegunaan umum: pengumpul log (Alloy, Fluent Bit), eksportir metrik (node-exporter), plugin jaringan (Calico, Cilium), driver penyimpanan CSI, dan agen keamanan.
Node control plane biasanya diberi taint agar beban kerja biasa tidak ditempatkan di sana. Bila agen pemantauan Anda perlu ikut memantau node tersebut, DaemonSet-nya harus punya toleration yang sesuai — kalau tidak, ada bagian kluster yang tidak terpantau tanpa Anda sadari.
Init Container
spec:
initContainers:
- name: tunggu-basisdata
image: busybox:1.36
command:
- sh
- -c
- |
until nc -z postgres 5432; do
echo "menunggu basis data…"
sleep 2
done
- name: jalankan-migrasi
image: registry.contoh.com/pesanan:2.4.0
command: ["./migrate", "up"]
containers:
- name: api
image: registry.contoh.com/pesanan:2.4.0
Init container berjalan berurutan sampai selesai sebelum kontainer utama dimulai. Bila salah satu gagal, pod di-restart dan seluruh rangkaian diulang.
Deployment dengan 3 replika berarti 3 pod menjalankan migrasi secara bersamaan. Sebagian alat migrasi punya penguncian dan akan aman; sebagian lagi akan merusak skema. Cara yang benar: jalankan migrasi sebagai Job terpisah sebelum rilis — atau, dalam Helm, sebagai pre-upgrade hook. Init container hanya tepat untuk menunggu kesiapan dependensi.
kubectl get jobs,cronjobs
kubectl get pods -l job-name=migrasi-basisdata
kubectl logs job/migrasi-basisdata
kubectl create job --from=cronjob/laporan-harian uji-manual
kubectl patch cronjob laporan-harian -p '{"spec":{"suspend":true}}'