Choose the Right Workload Resource

KubernetesBeginner
Practice Now

Introduction

CKAD tasks often expect you to choose the right Kubernetes workload resource before you write a manifest. A Pod is the smallest runnable unit, a Deployment keeps long-running application replicas available, a Job runs work to completion, and a CronJob stores a scheduled Job template.

In this lab, you will compare these resources through observable behavior instead of memorizing definitions. You will see that a standalone Pod does not come back after deletion, a Deployment recreates its Pod, a Job finishes and records success, and a CronJob stores schedule information for recurring work.

Prepare a Workload Comparison Namespace

In this step, you will prepare a clean namespace for comparing workload resources.

Start in /home/labex/project. You will create small manifests in this directory as you compare workload behavior.

mkdir -p /home/labex/project
cd /home/labex/project

Check that the Kubernetes API server is reachable. If the VM has just started and the node is not ready yet, wait a few seconds and run the command again.

kubectl get nodes --request-timeout=5s

Expected output includes:

NAME         STATUS   ROLES           AGE   VERSION
labex-v135   Ready    control-plane   ...   v1.35...

Workloads create Pods, so wait until the cluster networking Pod is Ready.

kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s

Expected output:

pod/calico-node-... condition met

Create a namespace named ckad-prep-workloads:

kubectl create namespace ckad-prep-workloads

Set this namespace as the current context namespace:

kubectl config set-context --current --namespace=ckad-prep-workloads

Confirm the current namespace:

kubectl config view --minify --output 'jsonpath={..namespace}'; echo

Expected output:

ckad-prep-workloads

Compare a Pod with a Deployment

In this step, you will compare a standalone Pod with a Deployment by deleting both Pods and watching what Kubernetes does next.

A standalone Pod is useful when you need one directly managed runtime unit for a very small task or inspection. A Deployment is better for a long-running application because a Deployment owns a ReplicaSet, and the ReplicaSet keeps the requested number of Pods running.

Create a standalone Pod manifest. The container sleeps so the Pod stays running long enough to observe it. The terminationGracePeriodSeconds: 0 field keeps this lab quick when you delete the Pod later.

cat > standalone-pod.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
  name: standalone-task
  labels:
    app: standalone-task
    workload.labex.io/intent: direct-pod
spec:
  terminationGracePeriodSeconds: 0
  containers:
  - name: sleeper
    image: busybox:1.36
    command: ["/bin/sh", "-c", "sleep 3600"]
EOF

Create a Deployment manifest. This Deployment asks Kubernetes to keep one managed-worker Pod running, and its Pod template uses the same quick termination setting.

cat > managed-deployment.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: managed-worker
  labels:
    workload.labex.io/intent: long-running
spec:
  replicas: 1
  selector:
    matchLabels:
      app: managed-worker
  template:
    metadata:
      labels:
        app: managed-worker
    spec:
      terminationGracePeriodSeconds: 0
      containers:
      - name: sleeper
        image: busybox:1.36
        command: ["/bin/sh", "-c", "sleep 3600"]
EOF

Apply both manifests:

kubectl apply -f standalone-pod.yaml
kubectl apply -f managed-deployment.yaml

Expected output:

pod/standalone-task created
deployment.apps/managed-worker created

Wait until both workloads are ready:

kubectl wait --for=condition=Ready pod/standalone-task --timeout=120s
kubectl wait --for=condition=Available deployment/managed-worker --timeout=120s

Expected output:

pod/standalone-task condition met
deployment.apps/managed-worker condition met

Capture the current Deployment Pod name, then delete the standalone Pod and the Deployment-owned Pod:

managed_pod="$(kubectl get pods -l app=managed-worker -o 'jsonpath={.items[0].metadata.name}')"
kubectl delete pod standalone-task "$managed_pod"

Expected output includes:

pod "standalone-task" deleted
pod "managed-worker-..." deleted

Wait for the Deployment to become available again:

kubectl wait --for=condition=Available deployment/managed-worker --timeout=120s

Expected output:

deployment.apps/managed-worker condition met

List the Pods. The standalone Pod should be gone, while a new managed-worker Pod should exist.

kubectl get pods

Expected output includes a managed-worker Pod, but not standalone-task:

NAME                              READY   STATUS    RESTARTS   AGE
managed-worker-...                1/1     Running   0          ...

Choose a Job for Completion

In this step, you will choose a Job for work that should finish successfully instead of running forever.

A Deployment is a good fit when the desired state is "keep this application running." A Job is a better fit when the desired state is "run this task until it completes." This is why migrations, batch processing, and one-time maintenance commands usually map to Jobs.

Create a Job named schema-migration:

kubectl create job schema-migration --image=busybox:1.36 -- /bin/sh -c 'echo migration-start; echo migration-complete'

Expected output:

job.batch/schema-migration created

Wait until the Job reaches the Complete condition:

kubectl wait --for=condition=Complete job/schema-migration --timeout=120s

Expected output:

job.batch/schema-migration condition met

Inspect the Job summary. COMPLETIONS should show 1/1, which means the task ran successfully once.

kubectl get job schema-migration

Expected output includes:

NAME               STATUS     COMPLETIONS   DURATION   AGE
schema-migration   Complete   1/1           ...        ...

Read the Job logs:

kubectl logs job/schema-migration

Expected output:

migration-start
migration-complete

Choose a CronJob for Recurring Work

In this step, you will choose a CronJob for work that should run on a schedule.

A CronJob is a scheduled Job template. It is the right choice when the task should repeat later, not just complete once. To keep this guided lab deterministic, you will create the CronJob in a suspended state. That lets you inspect the schedule and template without waiting for a clock boundary.

Create cleanup-cronjob.yaml:

cat > cleanup-cronjob.yaml <<'EOF'
apiVersion: batch/v1
kind: CronJob
metadata:
  name: cleanup-schedule
  labels:
    workload.labex.io/intent: recurring-task
spec:
  schedule: "*/5 * * * *"
  suspend: true
  successfulJobsHistoryLimit: 1
  failedJobsHistoryLimit: 1
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
          - name: cleanup
            image: busybox:1.36
            command:
            - /bin/sh
            - -c
            - 'echo cleanup-ready'
EOF

Apply the manifest:

kubectl apply -f cleanup-cronjob.yaml

Expected output:

cronjob.batch/cleanup-schedule created

Inspect the CronJob summary. SUSPEND is True because this lab uses the CronJob definition to learn the resource choice without waiting for scheduled Jobs.

kubectl get cronjob cleanup-schedule

Expected output includes:

NAME               SCHEDULE      TIMEZONE   SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cleanup-schedule   */5 * * * *   <none>     True      0        <none>          ...

Read the schedule and the template image directly from the object:

kubectl get cronjob cleanup-schedule -o 'jsonpath={.spec.schedule}{" "}{.spec.suspend}{" "}{.spec.jobTemplate.spec.template.spec.containers[0].image}{"\n"}'

Expected output:

*/5 * * * * true busybox:1.36

List the workload resources you created in this lab. This view connects the resource type to the intended behavior: a Deployment for a long-running replica, a Job for completion, and a CronJob for recurrence.

kubectl get deployment,job,cronjob

Expected output includes:

NAME                             READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/managed-worker   1/1     1            1           ...

NAME                         STATUS     COMPLETIONS   DURATION   AGE
job.batch/schema-migration   Complete   1/1           ...        ...

NAME                               SCHEDULE      TIMEZONE   SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob.batch/cleanup-schedule     */5 * * * *   <none>     True      0        <none>          ...

Summary

You compared Kubernetes workload resources by behavior. A standalone Pod did not come back after deletion, a Deployment recreated its Pod to keep one replica available, a Job ran a task to successful completion, and a CronJob stored a recurring Job template. These observations help you choose the right resource before writing a CKAD-style manifest.