# Demonstration: Watching a Job Actually Complete ## Creating the Job ``` $ kubectl apply -f pi-job.yaml job.batch/pi-job created $ kubectl get jobs NAME COMPLETIONS DURATION AGE pi-job 0/1 3s 3s $ kubectl get pods NAME READY STATUS RESTARTS AGE pi-job-8x2kq 1/1 Running 0 3s ``` The Job's own status (`0/1` completions) is tracked separately from its Pod's status — this matters because a Job can retry a FAILED Pod attempt without that looking like the healthy restart behavior you'd see on a Deployment. ## Once the Pod's process actually exits successfully ``` $ kubectl get pods NAME READY STATUS RESTARTS AGE pi-job-8x2kq 0/1 Completed 0 8s $ kubectl get jobs NAME COMPLETIONS DURATION AGE pi-job 1/1 7s 8s ``` `STATUS: Completed` — not `Running`, not `CrashLoopBackOff`. This is the ONE status a long-running Deployment's Pod is never supposed to reach on its own; for a Job, it's success. The Job object itself now reports `1/1` and stops — nothing recreates this Pod, because "finished successfully" is the desired end state here, unlike a Deployment where exiting is always treated as something to fix. ## What a FAILING Job attempt looks like, briefly ``` $ kubectl get pods NAME READY STATUS RESTARTS AGE bad-job-abc12 0/1 Error 0 5s bad-job-def34 0/1 Error 0 2s $ kubectl describe job bad-job ... Events: Warning BackoffLimitExceeded Job has reached the specified backoff limit ``` Two DIFFERENT Pods (`abc12`, `def34`), not one Pod restarting twice — each failed attempt gets its own new Pod, up to `backoffLimit`. Once that limit is hit, the Job stops retrying and reports the failure via Events rather than trying forever. ## Instructor Notes **Demo script:** Run the successful case live; showing the FAILING case is optional if time is short, but the `Completed` vs `Running`/`Error` distinction is worth pausing on regardless. **Approximate timing:** 8 minutes live; 5 minutes self-paced. **Common misconception to preempt:** students who've only seen Deployments sometimes expect `kubectl get pods` to show the Job's Pod disappear once it's done. It doesn't, by default — it stays as `Completed` until manually cleaned up or a TTL is configured, which is worth mentioning briefly (not a hands-on topic here). **Optional extension:** ask what `kubectl get pods` would show for a CronJob's Pods across several scheduled runs (answer: one Completed Pod per past run, accumulating — the same "nothing auto-cleans this up" behavior, multiplied by the schedule).