Skip to main content

Command Palette

Search for a command to run...

Kubernetes Jobs and CronJobs for CKAD Preparation

Kubernetes Job, CronJob, batch workloads, scheduled workloads

Updated
β€’6 min read
Kubernetes Jobs and CronJobs for CKAD Preparation
D

πŸ‘‹ 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:

  • completions controls 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:

  • completions defines how much work must be done.

  • parallelism defines 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.