Kubernetes Jobs and CronJobs for CKAD Preparation
Kubernetes Job, CronJob, batch workloads, scheduled workloads

π Hi! Iβm Dani, a passionate automation, Ansible, DevOps, and Cloud technologies enthusiast. I currently work as a Middleware Solutions Architect at Atradius, leading middleware automation and optimizing IT infrastructure. π‘ My Story: I started my career specializing in Oracle Middleware, working with technologies such as WebLogic, Oracle Database, Oracle iPlanet Web Server, and Oracle JDK. Over time, my focus shifted towards deployment automation, continuous integration, and process optimization in complex enterprise environments. π Impact & Achievements: β Direct the automation of Oracle Fusion Middleware (FMW) with Ansible, streamlining the installation, configuration, and patching processes for Oracle WebLogic, SOA Suite, and OSB. β Lead IBM WebSphere Application Server (WAS) automation with Ansible and AWX, including installation, configuration, certificates, and deployments, reducing implementation times by 70%. β Integrated Azure DevOps with AWX, eliminating manual deployment tasks and reducing human intervention to a simple approval step. β Mentor and train teams on Ansible automation, fostering continuous improvement and knowledge transfer. ππ₯ In my free time, I enjoy playing padel and basketball, always looking for new challenges and improvements, both in sports and technology. I also love building web applications with Oracle APEX, bringing ideas to life through low-code development. π₯ Letβs connect! π§ Email: dbenitez.vk@gmail.com π LinkedIn: https://www.linkedin.com/in/danielbenitezaguila π» GitHub: https://github.com/dbeniteza
Introduction
As part of my CKAD preparation journey, I moved from Kubernetes architecture fundamentals to application design concepts. This chapter introduced workloads with a defined lifespan, including Jobs and CronJobs, as well as labels, resource limits, init containers, and Custom Resource Definitions (CRDs).
Rather than following the exercises mechanically, I focused on understanding how Kubernetes behaves when workloads complete successfully, exceed deadlines, consume excessive resources, or fail during initialization.
Creating a Job
Jobs are designed for workloads that run to completion instead of running indefinitely.
Example:
apiVersion: batch/v1
kind: Job
metadata:
name: sleep
spec:
template:
spec:
containers:
- name: sleep
image: busybox
command: ["/bin/sleep"]
args: ["5"]
restartPolicy: Never
Apply it:
kubectl apply -f job.yaml
job.batch/sleep created
kubectl get job
NAME STATUS COMPLETIONS DURATION AGE
sleep Complete 1/1 8s 41s
kubectl describe jobs.batch sleep
Name: sleep
Namespace: default
Selector: batch.kubernetes.io/controller-uid=115537d3-a8b4-487e-b88e-d29e35dbf107
Labels: batch.kubernetes.io/controller-uid=115537d3-a8b4-487e-b88e-d29e35dbf107
batch.kubernetes.io/job-name=sleepy
controller-uid=115537d3-a8b4-487e-b88e-d29e35dbf107
job-name=sleep
Annotations: <none>
Parallelism: 1
Completions: 1
[...]
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal SuccessfulCreate 86s job-controller Created pod: sleep-gqblf
Normal Completed 78s job-controller Job completed
Unlike Pods or Deployments, a Job reaches a terminal state once its objective is completed.
kubectl get jobs.batch sleep -o yaml
apiVersion: batch/v1
kind: Job
metadata:
creationTimestamp: "2026-06-22T14:06:44Z"
generation: 1
labels:
batch.kubernetes.io/controller-uid: 115537d3-a8b4-487e-b88e-d29e35dbf107
batch.kubernetes.io/job-name: sleepy
controller-uid: 115537d3-a8b4-487e-b88e-d29e35dbf107
job-name: sleepy
name: sleepy
namespace: default
resourceVersion: "2634111"
uid: 115537d3-a8b4-487e-b88e-d29e35dbf107
spec:
backoffLimit: 6
completionMode: NonIndexed
completions: 1
manualSelector: false
parallelism: 1
kubectl delete jobs.batch sleep
job.batch "sleep" deleted from default namespace
Running Multiple Completions
A Job can require multiple successful executions before Kubernetes considers it complete.
Example:
apiVersion: batch/v1
kind: Job
metadata:
name: sleep
spec:
completions: 5
template:
spec:
containers:
- name: resting
image: busybox
command: ["/bin/sleep"]
args: ["3"]
restartPolicy: Never
This instructs Kubernetes to successfully execute the workload five times.
Monitoring the Job:
kubectl create -f job.yaml
job.batch/sleep created
kubectl get jobs.batch
NAME STATUS COMPLETIONS DURATION AGE
sleep Running 2/5 16s 16s
kubectl get jobs.batch
NAME STATUS COMPLETIONS DURATION AGE
sleep Complete 5/5 35s 44s
kubectl delete jobs.batch sleep
job.batch "sleep" deleted from default namespace
Lesson learned:
completionscontrols how many successful runs are required.Kubernetes tracks each successful execution.
Parallel Job Execution
Jobs can execute multiple Pods simultaneously.
Example:
apiVersion: batch/v1
kind: Job
metadata:
name: sleep
spec:
completions: 5
parallelism: 2
template:
spec:
containers:
- name: resting
image: busybox
command: ["/bin/sleep"]
args: ["3"]
restartPolicy: Never
With this configuration Kubernetes runs two Pods at a time until all required completions are reached.
Checking the Pods:
kubectl create -f job.yaml
job.batch/sleep created
kubectl get pods
NAME READY STATUS RESTARTS AGE
sleep-87nkk 0/1 Completed 0 13s
sleep-k6n5v 0/1 Completed 0 13s
sleep-mddp4 0/1 Completed 0 5s
sleep-xsth8 1/1 Running 0 3s
kubectl get jobs
NAME STATUS COMPLETIONS DURATION AGE
sleep Complete 5/5 22s 25s
You may see both completed and running Pods simultaneously. Lesson learned:
completionsdefines how much work must be done.parallelismdefines how much work can occur concurrently.
Setting Job Deadlines
Sometimes a workload should be stopped if it runs too long.
Example:
apiVersion: batch/v1
kind: Job
metadata:
name: sleep
spec:
completions: 5
parallelism: 2
activeDeadlineSeconds: 15
template:
spec:
containers:
- name: resting
image: busybox
command: ["/bin/sleep"]
args: ["3"]
restartPolicy: Never
If the Job exceeds this duration, Kubernetes terminates it.
Inspecting the Job:
kubectl create -f job.yaml
job.batch/sleep created
kubectl get jobs
NAME STATUS COMPLETIONS DURATION AGE
sleep Running 0/5 5s 5s
kubectl get jobs
NAME STATUS COMPLETIONS DURATION AGE
sleep Running 2/5 12s 12s
kubectl get job sleep -o yaml
apiVersion: batch/v1
kind: Job
[β¦]
status:
conditions:
- lastProbeTime: "2026-06-22T14:20:43Z"
lastTransitionTime: "2026-06-22T14:20:43Z"
message: Job was active longer than specified deadline
reason: DeadlineExceeded
status: "True"
type: FailureTarget
- lastProbeTime: "2026-06-22T14:20:45Z"
lastTransitionTime: "2026-06-22T14:20:45Z"
message: Job was active longer than specified deadline
reason: DeadlineExceeded
status: "True"
type: Failed
failed: 1
The status section may contain: reason: DeadlineExceeded
Lesson learned:
Jobs can be automatically terminated.
Kubernetes records deadline violations in the Job status.
Scheduling Work with CronJobs
CronJobs execute Jobs based on a schedule.
Example:
apiVersion: batch/v1
kind: CronJob
metadata:
name: sleep
spec:
schedule: "*/2 * * * *"
jobTemplate:
spec:
template:
spec:
containers:
- name: resting
image: busybox
command: ["/bin/sleep"]
args: ["3"]
restartPolicy: Never
Create it:
kubectl create -f cronjob.yaml
cronjob.batch/sleep created
kubectl get cronjobs.batch
NAME SCHEDULE TIMEZONE SUSPEND ACTIVE LAST SCHEDULE AGE
sleep */2 * * * * <none> False 0 <none> 20s
kubectl get jobs.batch
NAME STATUS COMPLETIONS DURATION AGE
sleep-29702316 Running 0/1 0s 0s
After the scheduled interval, Jobs begin appearing automatically.
kubectl get cronjobs.batch
NAME SCHEDULE TIMEZONE SUSPEND ACTIVE LAST SCHEDULE AGE
sleep */2 * * * * <none> False 0 111s 2m33s
kubectl get jobs.batch
NAME STATUS COMPLETIONS DURATION AGE
sleep-29702316 Complete 1/1 7s 114s
kubectl get jobs.batch
NAME STATUS COMPLETIONS DURATION AGE
sleep-29702316 Complete 1/1 7s 2m39s
sleep-29702318 Complete 1/1 6s 39s
Lesson learned:
CronJobs create Jobs.
Jobs create Pods.
The schedule uses standard cron syntax.
Limiting CronJob Runtime
A scheduled workload should not run indefinitely.
Example:
apiVersion: batch/v1
kind: CronJob
metadata:
name: sleep
spec:
schedule: "*/2 * * * *"
jobTemplate:
spec:
template:
spec:
activeDeadlineSeconds: 10
containers:
- name: resting
image: busybox
command: ["/bin/sleep"]
args: ["30"]
restartPolicy: Never
activeDeadlineSeconds: 10 combined with a longer sleep duration args: ["30"], this allows testing automatic termination.
The exercise demonstrated that scheduling and runtime restrictions can be combined.
kubectl create -f cronjob.yaml
cronjob.batch/sleep created
sleep 120 ; kubectl get jobs
NAME STATUS COMPLETIONS DURATION AGE
sleep-29702322 Running 0/1 2m7s 2m7s
sleep-29702324 Running 0/1 7s 7s
kubectl get cronjobs.batch
NAME SCHEDULE TIMEZONE SUSPEND ACTIVE LAST SCHEDULE AGE
sleep */2 * * * * <none> False 2 39s 2m49s
kubectl get jobs
NAME STATUS COMPLETIONS DURATION AGE
sleep-29702322 Running 0/1 2m48s 2m48s
sleep-29702324 Running 0/1 48s 48s
My Kubernetes Troubleshooting Checklist
When troubleshooting Jobs and CronJobs, I found myself repeatedly using:
kubectl describe pod <pod-name>
kubectl get jobs
kubectl get cronjobs
Common indicators:
Status | Typical Cause |
Complete | Job finished successfully |
DeadlineExceeded | Job exceeded runtime limit |
Running | Workload still executing |
Failed | Job execution failed |
Key Takeaways
After completing these workload-focused exercises, a few concepts became much clearer:
Jobs are for finite workloads.
CronJobs automate recurring tasks.
Completions and parallelism control Job execution.
activeDeadlineSeconds enforces runtime limits.
CronJobs create Jobs, and Jobs create Pods.
Scheduled workloads can be controlled and terminated automatically.
These concepts form an important foundation for CKAD topics such as batch processing, scheduled workloads, and application lifecycle management.ent, scheduling, troubleshooting, and workload design.



