Cloud AI Campus
  • Career paths
  • Learning paths
  • Hands-on Labs
Log in Sign up

๐Ÿงช Hands-on lab · 30 min

Jobs and CronJobs

  1. 1. Run a Job to completion
  2. 2. Inspect the Job's output
  3. 3. Schedule a CronJob
  4. 4. Wait for the first run, read its logs
  5. 5. Clean up

Run a Job to completion

A Job runs one or more pods, retries them on failure, and stops once a target number of completions is reached. It's the right controller for batch work: data migrations, one-off backups, sending a report at midnight.

Look at the manifest:

cat jobs/example-job.yaml

It runs a Perl container that prints ฯ€ to 200 digits and exits. The spec sets backoffLimit: 2, so Kubernetes will retry up to two times before marking the Job failed.

Submit it:

kubectl apply -f jobs/example-job.yaml

Watch the Job's pod:

kubectl get pods -l job-name=example-job

STATUS progresses ContainerCreating โ†’ Running โ†’ Completed. That's success. A pod that exits with code 0 satisfies the Job; restart isn't applied.

Confirm the Job recorded a completion:

kubectl get job example-job

COMPLETIONS shows 1/1. Click Verify step.

Hint

`kubectl apply -f jobs/example-job.yaml` runs a Perl pod that prints pi to 200 digits.

Inspect the Job's output

The pod is Completed but it's still in the cluster โ€” Kubernetes keeps successful Job pods around so you can read their logs.

Find the pod the Job created:

kubectl get pods -l job-name=example-job

Read its stdout:

kubectl logs -l job-name=example-job

You should see the digits of ฯ€:

3.14159265358979323846264338327950288419716939937510...

kubectl describe shows the Job's status timeline โ€” when it started, when it succeeded, and any retries that happened along the way:

kubectl describe job example-job

Jobs with parallelism: N run multiple pods at once; with completions: M they require M successes before the Job is done. Together they let you express map-style fanouts (parallelism=10, completions=10 runs 10 pods in parallel, all of which must succeed).

Click Verify step once you've seen the ฯ€ output.

Hint

`kubectl logs -l job-name=example-job` reads from the completed pod.

Schedule a CronJob

A CronJob is the controller-of-controllers: every time its schedule fires, it creates a Job, which creates pods. Schedules use standard cron syntax.

Look at the manifest:

cat jobs/example-cronjob.yaml

schedule: "*/1 * * * *" means "run every minute". The pod just prints the current date and a greeting.

Apply it:

kubectl apply -f jobs/example-cronjob.yaml

Confirm the CronJob exists:

kubectl get cronjob hello

The SCHEDULE, LAST SCHEDULE, and ACTIVE columns describe what's about to happen and what's currently running.

Click Verify step.

Hint

`kubectl apply -f jobs/example-cronjob.yaml` schedules `hello` to run every minute.

Wait for the first run, read its logs

Cron fires on minute boundaries. Depending on when you applied the CronJob, you may need to wait up to ~60 seconds for the first Job to land.

Watch for the first scheduled Job to appear:

kubectl get jobs -w

(Press Ctrl-C to stop watching once you see a hello-<timestamp> Job.)

List the most recent jobs:

kubectl get jobs --sort-by=.metadata.creationTimestamp

Pick the last hello-... Job and read its logs through its pod:

last_job=$(kubectl get jobs --sort-by=.metadata.creationTimestamp -o name | tail -1)
kubectl logs -l "job-name=$(basename $last_job)"

You'll see the date string and Hello from CronJob.

CronJobs are great for housekeeping (snapshots, GC, certificate renewals). They have two well-known pitfalls: overlapping runs (set concurrencyPolicy: Forbid if your work isn't safe to run twice) and Kubernetes' default to keep the last 3 successful Job records (successfulJobsHistoryLimit).

Click Verify step when at least one hello-* Job has completed.

Hint

After a minute, `kubectl get jobs` will show a Job named `hello-<timestamp>`; tail its logs.

Clean up

CronJobs run forever. Stop the schedule and tidy up the leftover Jobs and pods.

Delete the CronJob โ€” that also stops future runs:

kubectl delete cronjob hello

Delete the one-shot Job from step 1:

kubectl delete job example-job

Confirm everything's gone:

kubectl get cronjob,job

Output should be No resources found in default namespace.

Deleting a CronJob does not delete the Jobs it already created. If you want them gone too, add a label selector like kubectl delete job -l owned-by=hello (when you set such labels on the Job template) or delete by name.

Click Verify step.

Hint

`kubectl delete cronjob hello` removes the schedule; `kubectl delete job example-job` removes the one-shot.

© 2026 Cloud AI Campus