TT Lab
Get started
Learn Learning paths Courses

CKAD — Kubernetes Application Developer

Pod Design — Labels, Commands, Jobs, CronJobs

Continue in TT Lab

Goal

You set a Pod's metadata (labels and annotations) and its execution method (command/args/env/restartPolicy) directly, and fill in the key fields of the batch workloads Job and CronJob.

Why it matters

Half of the CKAD questions come down to "which field does this value go in?" Labels and annotations are both string maps under metadata, but their roles are opposite. A label is a value that a selector picks, so Services, Deployments, and NetworkPolicies all look at it. An annotation is a note that a selector never looks at, so it holds settings that tools read (change-cause, controller hints). If you confuse the two, you get the incident where a Service has no endpoints attached.

The same goes for command and args. They override the image's ENTRYPOINT and CMD respectively; they are not simply "a command and its arguments." If you change only command, the CMD is still appended and you get a strange combination; if you change only args, the new arguments are appended to the original ENTRYPOINT.

A Job is a controller that "counts successes." Where a Deployment maintains "how many are running right now," a Job counts "how many times it has succeeded so far." That is why, if you set the Pod's restartPolicy to Always, the Pod never ends and neither does the Job.

Steps

  1. Create the namespace ckad-design, then create a Pod web in it. Image nginx:1.27, labels app=web and tier=frontend.
  2. Add the annotation owner=platform-team to the Pod web. In the same namespace, create a Pod api — image nginx:1.27, labels app=api and tier=backend.
  3. Create a Pod runner. Image busybox:1.36, command is ["/bin/sh"], args is ["-c", "sleep 3600"].
  4. Create a Pod envtest. Image busybox:1.36, label tier=backend. Set the environment variables APP_ENV=production and APP_TIER=backend as fixed values, and have POD_NAME reference metadata.name through the Downward API. command is ["/bin/sh","-c","sleep 3600"].
  5. Create a Pod oneshot. Image busybox:1.36, restartPolicy is Never, command is ["/bin/sh","-c","echo done"].
  6. Create a Job batch-sum. completions: 4, parallelism: 2, backoffLimit: 3, the Pod's restartPolicy is OnFailure, container image busybox:1.36.
  7. Create a CronJob nightly-report. schedule: "17 3 * * *", concurrencyPolicy: Forbid, startingDeadlineSeconds: 120, successfulJobsHistoryLimit: 3, container image busybox:1.36, the Pod's restartPolicy is OnFailure.
  8. In the ckad-design namespace, save only the names of the Pods with the label tier=backend to /root/ckad-design/backend-pods.txt, one per line (names only, without the pod/ prefix).

Notes

Namespace and first Pod

Create the namespace ckad-design, then create a Pod web in it. Image nginx:1.27, labels app=web and tier=frontend.

Create the namespace first, then create the Pod in it. Put the labels in metadata.labels. It is quicker to give kubectl run the --labels flag, or to extract a skeleton with --dry-run=client -o yaml and edit it.

Telling labels and annotations apart

Add the annotation owner=platform-team to the Pod web. In the same namespace, create a Pod api — image nginx:1.27, labels app=api and tier=backend.

A label is a value a selector picks; an annotation is a note a selector does not look at. You can add them later to an existing Pod with kubectl label and kubectl annotate.

Overriding image defaults with command and args

Create a Pod runner. Image busybox:1.36, command is ["/bin/sh"], args is ["-c", "sleep 3600"].

command overrides the Dockerfile's ENTRYPOINT and args overrides CMD. Both are YAML string arrays, and to use shell syntax (;, &&) you have to invoke a shell yourself.

Environment variables and the Downward API

Create a Pod envtest. Image busybox:1.36, label tier=backend. Set the environment variables APP_ENV=production and APP_TIER=backend as fixed values, and have POD_NAME reference metadata.name through the Downward API. command is ["/bin/sh","-c","sleep 3600"].

Fixed values go in env[].value; the Pod's own metadata comes in through env[].valueFrom.fieldRef.fieldPath. The field path for the Pod name starts with metadata..

Making a one-shot Pod with restartPolicy

Create a Pod oneshot. Image busybox:1.36, restartPolicy is Never, command is ["/bin/sh","-c","echo done"].

spec.restartPolicy is a Pod-level field. The default Always is for long-running work; for a task that runs once and ends, use a different value. You cannot modify this field after creation, so delete the Pod and create it again.

A Job's completion count and parallelism

Create a Job batch-sum. completions: 4, parallelism: 2, backoffLimit: 3, the Pod's restartPolicy is OnFailure, container image busybox:1.36.

completions is how many successes are needed in total for the Job to finish, and parallelism is how many to run at the same time. backoffLimit is the upper bound on failure retries, and its default is 6. There are only two values you can use for a Job Pod's restartPolicy.

CronJob schedule and concurrency policy

Create a CronJob nightly-report. schedule: "17 3 * * *", concurrencyPolicy: Forbid, startingDeadlineSeconds: 120, successfulJobsHistoryLimit: 3, container image busybox:1.36, the Pod's restartPolicy is OnFailure.

schedule is a five-field cron expression (minute, hour, day of month, month, day of week). concurrencyPolicy is the behavior when the previous run has not finished yet, and startingDeadlineSeconds is how many seconds late the Job may still start when the scheduled time has been missed.

Listing with a label selector (comprehensive)

In the ckad-design namespace, save only the names of the Pods with the label tier=backend to /root/ckad-design/backend-pods.txt, one per line (names only, without the pod/ prefix).

Filter with kubectl get pods -l key=value (the placeholders are the label key and value), and keep only the names with -o name or -o jsonpath. -o name produces the pod/이름 form (the placeholder is the Pod name), so you have to cut off the prefix. The file must contain only the names, one per line.