Application Design and Build
Package code into containers and run it with the right workload, multi-container, batch, and storage patterns.
The full loop: understand → drill the commands → prove it under the clock. Every objective below is taught here and practised in the drills.
1Understand it
Containers & images
A container packages your app with everything it needs, code, runtime, libraries, into one isolated, portable unit. A Dockerfile builds an image; a running copy of that image is a container.
- Dockerfile → image (build once) → container (run many).
- Images are layered and immutable; tag with versions, not just :latest.
- Multi-stage builds keep final images small by discarding build tools.
Choosing the right workload
Kubernetes has a controller for each kind of app. A Deployment runs stateless apps; a StatefulSet runs apps that need stable names and their own storage (databases); a DaemonSet runs one Pod on every node (agents); a Job/CronJob runs batch work once or on a schedule.
- Deployment: stateless, interchangeable replicas.
- StatefulSet: stable network IDs + per-Pod persistent storage.
- DaemonSet: exactly one Pod per (matching) node.
- Job / CronJob: run-to-completion / scheduled batch work.
Pods, the smallest unit
A Pod is the smallest thing Kubernetes runs. It wraps one or more containers that share the same network address and can share storage. Most Pods hold a single container; in production a controller like a Deployment manages them for you.
- Containers in a Pod share the Pod's IP and localhost.
- A Pod is ephemeral, if it dies it is replaced, not resurrected.
- kubectl run / create generate Pods or higher-level objects.
Multi-container patterns
Sometimes a Pod runs a helper beside the main app. An init container runs to completion before the app starts (setup); a sidecar runs alongside the app for its whole life (logging, proxying). They compose behaviour without changing the main app.
- initContainers run sequentially to completion before app containers start.
- Sidecars (log shipper, Istio proxy) share the Pod lifecycle and volumes.
- Patterns: sidecar, ambassador (proxy outbound), adapter (reshape output).
Init container that waits for a dependency
spec:
initContainers:
- name: wait-db
image: busybox:1.36
command: ['sh','-c','until nc -z db 5432; do sleep 2; done']
containers:
- name: app
image: myapp:1.0Jobs & CronJobs
A Job runs a Pod until a task completes successfully, then stops, ideal for batch work like a migration. A CronJob runs Jobs on a schedule, like cron on Linux.
- Job: completions and parallelism control how many Pods run/succeed.
- backoffLimit caps retries on failure.
- CronJob uses standard cron syntax in spec.schedule.
Volumes, ephemeral & persistent
Containers lose their files when they restart, so Pods use Volumes for storage. An emptyDir lasts as long as the Pod and is shared between its containers (scratch space). For storage that survives the Pod, a PersistentVolumeClaim (PVC) requests durable storage, which Kubernetes binds to a PersistentVolume (PV).
- emptyDir: Pod-lifetime, shared across the Pod's containers.
- PVC requests storage; a PV (often auto-provisioned via a StorageClass) fulfils it.
- Always two halves: spec.volumes (define) + container.volumeMounts (use).
- Access modes: RWO (one node), ROX (many read), RWX (many read/write).
Mount a PVC for durable storage (swap for emptyDir = scratch)
spec:
containers:
- name: app
image: nginx
volumeMounts:
- name: data
mountPath: /usr/share/nginx/html
volumes:
- name: data
persistentVolumeClaim:
claimName: web-pvc
# emptyDir: {} # <- use this instead for pod-lifetime scratch2 Drill the commands & prove it
Mastery, 0/6 objectives
An objective turns green only when you've solved every drill in it, not just one.
- Create Pods imperatively with kubectl run: images, env vars, commands/args, labels, and restart policy0/7
- Generate YAML manifests with --dry-run=client -o yaml and redirect to file for editing0/3
- Create and manage Deployments: image, replicas, scale, and expose as a Service0/5
- Create Jobs and CronJobs, including --from=cronjob, schedules, and correct restartPolicy0/5
- Inspect Pod volume and multi-container fields via kubectl explain (emptyDir, hostPath, shared volumes)0/2
- Manage labels on running objects with kubectl label, including overwrite semantics0/2
Create a single Pod named web running image nginx:1.27 (a bare Pod, not a Deployment).
Drills check the command pattern deterministically, there is often more than one correct form. For full fidelity, pair this with real-cluster reps (the killer.sh simulator is included free with your exam registration).