Job และ CronJob
ไอเดียในหนึ่งประโยค
หัวข้อที่มีชื่อว่า “ไอเดียในหนึ่งประโยค”Job รัน Pod หนึ่งตัวหรือมากกว่าจนกว่างานจะสำเร็จ ไม่ใช่ปล่อยให้รันตลอดไป ส่วน CronJob create Job ให้อัตโนมัติตาม schedule แบบ cron
Job: รันจนจบงาน ไม่ใช่รันตลอดไป
หัวข้อที่มีชื่อว่า “Job: รันจนจบงาน ไม่ใช่รันตลอดไป”Pod ของ Deployment มีไว้ให้รันไม่มีกำหนด ส่วน Pod ของ Job มีไว้ให้ จบงาน Job จะนับจำนวนที่สำเร็จและ retry เมื่อพังจนถึง limit ที่กำหนด แทนที่จะ restart Pod ไปเรื่อย ๆ แบบ controller ที่รันระยะยาว
apiVersion: batch/v1kind: Jobmetadata: name: report-backfillspec: completions: 5 parallelism: 2 backoffLimit: 3 activeDeadlineSeconds: 600 template: spec: restartPolicy: OnFailure containers: - name: backfill image: myregistry/report-backfill:1.0.0 args: ['--month=2026-06']completions: 5 หมายความว่า Job จะยังไม่จบจนกว่า Pod 5 ตัวจะ exit สำเร็จ parallelism: 2 จำกัดว่า Pod พวกนั้นรันพร้อมกันได้กี่ตัว backoffLimit: 3 คือจำนวนครั้งที่ยอมให้พังได้ก่อนที่ Job จะยอมแพ้แล้วตีตัวเองเป็น Failed activeDeadlineSeconds: 600 คือ timeout รวมของทั้ง Job นับเป็นเวลาจริง พอเกินก็ terminate ทันทีไม่สนว่าสำเร็จไปกี่ตัวแล้ว สังเกต restartPolicy: OnFailure ด้วย Pod template ของ Job ต้องใช้ OnFailure หรือ Never เท่านั้น ห้ามใช้ Always เพราะจุดประสงค์ทั้งหมดของ Job คือหยุดเมื่องานเสร็จ
# Watch completions accumulate, then check the Job's final statuskubectl get job report-backfill --watchkubectl describe job report-backfill
# Logs from a finished Job's Podskubectl logs -l job-name=report-backfill --tail=100CronJob: ตั้งเวลารัน Job
หัวข้อที่มีชื่อว่า “CronJob: ตั้งเวลารัน Job”CronJob ไม่ได้รัน Pod เองตรง ๆ แต่จะ create Job ตาม schedule แล้ว Job นั้นก็ create Pod เหมือนกับที่คุณ submit Job ด้วยมือตอนนั้นเป๊ะ ๆ
apiVersion: batch/v1kind: CronJobmetadata: name: nightly-reportspec: schedule: '0 2 * * *' concurrencyPolicy: Forbid startingDeadlineSeconds: 300 successfulJobsHistoryLimit: 3 failedJobsHistoryLimit: 1 jobTemplate: spec: backoffLimit: 2 template: spec: restartPolicy: OnFailure containers: - name: report image: myregistry/nightly-report:1.0.0schedule: '0 2 * * *' รันตอน 02:00 ทุกวัน ตาม cron syntax มาตรฐาน concurrencyPolicy ตัดสินว่าจะทำยังไงถ้า run ก่อนหน้ายังไม่จบตอนที่ run ถัดไปถึงกำหนด Allow (ค่า default) ปล่อยให้รันคู่กันไปเลย Forbid ข้าม run ใหม่ไปทั้งหมด และ Replace ยกเลิก Job ที่ยังรันอยู่แล้วเริ่ม Job ใหม่แทนที่ startingDeadlineSeconds กำหนดว่า run ที่พลาดเวลาไปแล้วยังเริ่มได้ช้าสุดแค่ไหน successfulJobsHistoryLimit กับ failedJobsHistoryLimit คุมว่า CronJob จะเก็บ Job object เก่าไว้ให้ตรวจสอบกี่ตัวก่อนจะ garbage-collect ทิ้ง
flowchart LR cj["CronJob nightly-report (schedule: 0 2 * * *)"] -->|creates| j["Job nightly-report-29102026"] j -->|creates| p1["Pod (runs to completion)"] j -->|creates| p2["Pod (runs to completion)"] p1 --> done["Succeeded, Pods stop"] p2 --> done
จัดการ Job และ CronJob
หัวข้อที่มีชื่อว่า “จัดการ Job และ CronJob”# List CronJobs and the Jobs they have createdkubectl get cronjob nightly-reportkubectl get jobs --selector=job-name
# Trigger one ad-hoc run right now, without waiting for the schedulekubectl create job nightly-report-manual --from=cronjob/nightly-reportเพราะ schedule ของ CronJob ยิงซ้ำได้หลายรอบ successfulJobsHistoryLimit/failedJobsHistoryLimit เลยสำคัญในทางปฏิบัติ ถ้าไม่ตั้งไว้ Job และ Pod object เก่าจะสะสมไปเรื่อย ๆ ทุกคืน