Cours

Real cluster in five minutes

Workflow: spin up a disposable three-node kind cluster to practice against a real control plane.

With Docker or Podman and kind installed:

kind create cluster --name kubelab --config examples/kind-cka-lab.yaml
kubectl cluster-info --context kind-kubelab
kubectl apply -f examples/deployment-ready.yaml
kubectl get pods,svc -n app

Delete it when finished:

kind delete cluster --name kubelab

Use the simulator for fast feedback and repeatable drills; use a real disposable cluster for admission control, CNI behavior, CSI provisioning, image pulls, controller timing, upgrades, etcd restore, Helm releases, runtime security, and unfamiliar commands.

Kubernetes mental model

Tracks: All tracks — Level: Beginner — ~28 min

Replace “a server running a container” with a declarative control-loop model: desired state is stored in the API and controllers continuously reconcile reality.

Objectives

  • Explain desired state, reconciliation and eventual consistency
  • Trace a request from kubectl to a running container
  • Distinguish control-plane responsibilities from node responsibilities
Reconciliation path
intent → observation → action
kubectlclient API serverdesired state etcdpersistence controllersreconcile kubeletnode action observed status returns through the API

The API is the product

Every durable cluster action becomes an API object. kubectl is one client; controllers, operators and CI systems are other clients. Objects contain desired state in spec and observed state in status.

  • You submit intent, not a shell script for the cluster
  • Controllers watch objects and take idempotent actions
  • The scheduler selects a node; the kubelet makes the Pod real

Control loops, not orchestration scripts

A controller compares desired and current state, then moves current state closer to desired state. Because every loop can retry, Kubernetes remains useful through temporary failures and restarts.

Command drills

Inspect cluster endpoints

kubectl cluster-info

See API resource types

kubectl api-resources

Inspect server/client versions

kubectl version

Tips

  • When troubleshooting, ask which control loop owns the failed object.
  • Read Events and status conditions before changing anything.

Sources

API objects and YAML fluency

Tracks: All tracks — Level: Beginner — ~36 min

Read, generate, validate and edit Kubernetes manifests quickly. Learn the small set of fields shared by nearly every object and how API version, kind and metadata determine identity.

Objectives

  • Recognize apiVersion, kind, metadata, spec and status
  • Generate safe YAML from imperative commands
  • Use dry-run and server-side validation to shorten feedback loops
Declarative object
spec and status converge
YAMLapiVersion · kind API pipelineauth · admit · validate specdesired statusobserved loopretry

Object identity

An object is addressed by API group/version, kind, namespace and name. Namespaced resources live inside a namespace; cluster-scoped resources do not.

Declarative workflow

Keep a manifest as the source of truth, preview changes, then apply. Prefer small, reviewable edits and inspect the generated diff before an exam task mutates production-like objects.

  • Generate with --dry-run=client -o yaml
  • Validate with kubectl apply --dry-run=server
  • Review with kubectl diff -f file.yaml

Command drills

Generate a Deployment manifest

kubectl create deployment web --image=nginx:1.27 --dry-run=client -o yaml > web.yaml

Validate against the API server

kubectl apply --dry-run=server -f web.yaml

Explain a field

kubectl explain deployment.spec.strategy --recursive

Tips

  • Do not memorize whole manifests; memorize object skeletons and use kubectl explain.
  • Check indentation and whether a field belongs under Pod spec or container spec.

Sources

kubectl speed and precision

Tracks: All tracks — Level: Beginner — ~42 min

Develop a repeatable command workflow: scope correctly, generate rather than type, use structured output, patch narrowly, and inspect the right evidence before acting.

Objectives

  • Switch contexts and namespaces safely
  • Use selectors, JSONPath and custom columns
  • Patch, replace and apply resources with the correct semantics
Declarative object
spec and status converge
YAMLapiVersion · kind API pipelineauth · admit · validate specdesired statusobserved loopretry

Scope first

Many exam mistakes are correct commands in the wrong namespace or context. Put the namespace in the command until the task is complete; avoid silently changing global context.

Query structured data

Wide tables are useful, but JSONPath and custom columns answer exact questions. Combine selectors with output formatting to avoid manually scanning long object lists.

Choose mutation semantics

apply reconciles a declarative file; patch changes selected fields; replace sends a complete object; edit opens the live object. Prefer the least broad operation that solves the task.

Command drills

Select and format Pods

kubectl get pods -A -l app=web -o custom-columns='NS:.metadata.namespace,NAME:.metadata.name,NODE:.spec.nodeName,READY:.status.containerStatuses[*].ready'

Read a Secret value

kubectl get secret api-key -o jsonpath='{.data.token}' | base64 -d; echo

Patch replicas

kubectl patch deployment web -p '{"spec":{"replicas":4}}'

Tips

  • Use aliases only after verifying them in the exam shell.
  • Append --show-labels when selectors are not matching.

Sources

Namespaces, labels and ownership

Tracks: All tracks — Level: Beginner — ~30 min

Organize resources for humans and controllers. Use namespaces for scope, labels for selection, annotations for non-identifying metadata, and owner references for garbage collection.

Objectives

  • Choose labels that remain useful as applications evolve
  • Diagnose empty selectors and mismatched Services
  • Explain cascading deletion through owner references
Selection graph
labels bind independent objects
Serviceselector app=web Deploymenttemplate app=web Pod Aapp=web Pod Bapp=web Pod Capp=other Pod C remains outside the selection set

Namespaces are scope, not walls

Namespaces partition names and support policy or quota attachment, but they are not by themselves a security boundary. Network and authorization policy still matter.

Labels drive behavior

Services, Deployments and NetworkPolicies select objects by labels. A single typo can produce a healthy-looking controller with no traffic path.

Ownership creates object graphs

A Deployment owns ReplicaSets; ReplicaSets own Pods. Garbage collection uses owner references to remove dependents when appropriate.

Command drills

Apply labels

kubectl label pod web-0 app=web tier=frontend --overwrite

Find by expression

kubectl get pods -l 'app=web,tier in (frontend,edge)'

Show owners

kubectl get pod web-0 -o jsonpath='{.metadata.ownerReferences}'

Tips

  • For a Service with no endpoints, compare its selector to Pod labels character for character.
  • Use annotations for build IDs, contacts and tooling metadata that should not select objects.

Sources

Pods, containers and lifecycle

Tracks: All tracks — Level: Intermediate — ~45 min

Understand the smallest schedulable unit, its shared namespaces and volumes, restart behavior, phases, conditions, termination, and the signals that explain why a Pod is not Ready.

Objectives

  • Differentiate Pod phase, container state and readiness
  • Use logs, previous logs, Events and exit codes
  • Predict restart behavior from restartPolicy and controller ownership
Pod lifecycle signals
phase is only the outer layer
Pendingschedule · pull Runningcontainer states Readytraffic=yes NotReadytraffic=no Terminatinggrace period

A Pod is a shared execution envelope

Containers in a Pod share the network namespace and can share mounted volumes. They are co-scheduled and usually represent one application instance.

State has layers

Pod phase is intentionally coarse. Container statuses include waiting, running and terminated states with reasons and exit codes. Conditions such as PodScheduled and Ready expose control-loop progress.

Termination is a protocol

On deletion, kubelet runs preStop if configured, sends a termination signal, waits for the grace period, then force-kills remaining processes. Readiness should turn false before traffic reaches a terminating endpoint.

Command drills

Inspect status and events

kubectl describe pod web

Read a crashed container

kubectl logs web -c app --previous

Watch transitions

kubectl get pods -w

Tips

  • CrashLoopBackOff is a delay, not the root cause; inspect the previous termination state.
  • Pending often means scheduling or volume attachment, not an image problem.

Sources

Controllers and workload selection

Tracks: All tracks — Level: Intermediate — ~48 min

Select the controller that matches identity, placement and completion semantics: Deployment, StatefulSet, DaemonSet, Job or CronJob.

Objectives

  • Choose a controller from workload requirements
  • Trace Deployment → ReplicaSet → Pod ownership
  • Explain rollout, parallelism, stable identity and node-wide placement
Controller ownership
controllers replace, place or complete
Desired stateworkload object Deploymentreplaceable StatefulSetstable identity Jobcompletion Podweb-7cPoddb-0Podtask-x Observestatus

Deployment for replaceable replicas

Deployments manage stateless or externally stateful replicas and support declarative rolling updates and rollbacks.

StatefulSet for stable identity

StatefulSets provide ordinal names, ordered behavior and stable volume claim templates. They do not make an application stateful by themselves.

DaemonSet and batch

DaemonSets place a copy on eligible nodes. Jobs run to completion; CronJobs create Jobs on a schedule. Completion and retry semantics matter more than process uptime.

Command drills

Create and scale a Deployment

kubectl create deployment api --image=nginx:1.27 && kubectl scale deployment api --replicas=3

Create a one-shot Job

kubectl create job checksum --image=busybox:1.36 -- sh -c "sha256sum /etc/hosts"

Create a CronJob

kubectl create cronjob heartbeat --image=busybox:1.36 --schedule="*/5 * * * *" -- date

Tips

  • A naked Pod is rarely the right exam answer when self-healing is requested.
  • Use ownerReferences to identify the controller before deleting or editing a generated Pod.

Sources

Configuration, resources and health

Tracks: All tracks — Level: Intermediate — ~52 min

Make applications configurable, schedulable and observable using ConfigMaps, Secrets, requests, limits and three distinct probe types.

Objectives

  • Inject configuration as environment variables or files
  • Calculate scheduling from requests and enforcement from limits
  • Choose startup, readiness and liveness probes without creating restart loops
Application health gates
startup → readiness → liveness
Containerprocess startupProbeinitialized? readinessProbesend traffic? livenessProberestart? Startedprobe stops Endpointready set Kubeletrestart Serviceroute

Configuration is data

ConfigMaps hold non-confidential configuration. Secrets provide a dedicated API and access controls, but base64 is encoding rather than encryption. Mounts update differently from environment variables.

Requests and limits solve different problems

The scheduler places Pods using requests. The runtime enforces limits: CPU is throttled and memory overuse can lead to OOM termination. LimitRange and ResourceQuota can set policy at namespace scope.

Probes answer different questions

Startup: has a slow application initialized? Readiness: should it receive traffic now? Liveness: should kubelet restart it? A weak liveness probe can turn dependency failure into an outage.

Command drills

Create a ConfigMap

kubectl create configmap app-config --from-literal=MODE=prod

Set resources

kubectl set resources deployment api --requests=cpu=100m,memory=128Mi --limits=cpu=500m,memory=256Mi

Inspect usage

kubectl top pod -A --sort-by=memory

Tips

  • Do not use liveness to test an external dependency.
  • A Pod can be Running and still not be Ready.

Sources

Services, DNS and traffic flow

Tracks: All tracks — Level: Intermediate — ~50 min

Follow a request from a client through cluster DNS and a Service to a ready Pod. Understand ClusterIP, NodePort, LoadBalancer, headless Services and endpoint discovery.

Objectives

  • Resolve Service DNS names across namespaces
  • Compare Service types and headless discovery
  • Debug selectors, EndpointSlices, ports and targetPorts
Service traffic path
DNS → virtual IP → ready endpoint
Client Podfrontend CoreDNSapi.backend Service10.96.0.42:80 Pod A10.244.2.8:8080 Pod B10.244.1.7:8080 NotReadyexcluded

A Service is a stable virtual frontend

Pods are ephemeral; a Service provides a stable name and virtual IP over a changing set of ready endpoints. EndpointSlices carry those backends.

DNS encodes scope

Within the same namespace, clients can use the short Service name. Across namespaces, use service.namespace or the full cluster domain.

Ports have two perspectives

port is the Service-facing port; targetPort is the Pod-facing port. targetPort may be a number or a named container port.

Command drills

Expose a Deployment

kubectl expose deployment web --port=80 --target-port=8080

Inspect endpoints

kubectl get service,endpointslice -l kubernetes.io/service-name=web

Test DNS

kubectl run dns-test --rm -it --restart=Never --image=busybox:1.36 -- nslookup web.default.svc.cluster.local

Tips

  • When a Service has no endpoints, debug labels before kube-proxy.
  • Readiness-gated Pods are omitted from normal ready endpoints.

Sources

Control-plane and node architecture

Tracks: CKA — Level: Intermediate — ~58 min

Operate Kubernetes as a distributed system. Learn component responsibilities, static Pods, leader election, health endpoints and the dependency chain that turns API intent into node activity.

Objectives

  • Map failures to API server, etcd, scheduler, controller manager, kubelet, runtime or network layer
  • Recognize static Pod manifests and mirror Pods
  • Use component logs, health endpoints and system services
Reconciliation path
intent → observation → action
kubectlclient API serverdesired state etcdpersistence controllersreconcile kubeletnode action observed status returns through the API

API server at the center

Control-plane components communicate through the API rather than directly mutating each other. The API server authenticates, authorizes, admits, validates and persists requests.

Node execution path

The kubelet watches assigned Pods, asks the CRI runtime to create sandboxes and containers, mounts CSI volumes and relies on CNI for Pod networking.

Static control-plane Pods

kubeadm commonly runs API server, controller manager, scheduler and local etcd as static Pods. The kubelet reads manifests from a configured path; editing a manifest causes recreation.

Command drills

Find static Pod path

grep -n staticPodPath /var/lib/kubelet/config.yaml

Inspect control-plane Pods

kubectl -n kube-system get pods -o wide

Check kubelet

systemctl status kubelet && journalctl -u kubelet -n 100 --no-pager

Tips

  • If kubectl cannot reach the API, move one layer down: systemd, static manifests, container runtime.
  • Back up a manifest before editing it under exam pressure.

Sources

Bootstrap clusters with kubeadm

Tracks: CKA — Level: Advanced — ~62 min

Prepare hosts, initialize a control plane, install a pod network, join workers and retrieve the evidence needed when bootstrap fails.

Objectives

  • Sequence runtime, kubelet, kubeadm and CNI installation
  • Use init, token and join workflows
  • Diagnose preflight, certificate, runtime and CNI failures
Reconciliation path
intent → observation → action
kubectlclient API serverdesired state etcdpersistence controllersreconcile kubeletnode action observed status returns through the API

Bootstrap sequence matters

Nodes need a compatible CRI runtime, kubelet and kubeadm. kubeadm init creates certificates, kubeconfigs and static Pod manifests, then uploads configuration and prints a join command.

CNI completes networking

CoreDNS commonly remains Pending until a compatible CNI plugin is installed. The selected Pod CIDR must align with the network add-on configuration.

Join is authenticated discovery

A bootstrap token and CA pin allow a node to discover the cluster securely. Tokens expire; kubeadm can create a new token and print a complete join command.

Command drills

Initialize a control plane

sudo kubeadm init --pod-network-cidr=10.244.0.0/16

Set admin kubeconfig

mkdir -p $HOME/.kube && sudo cp /etc/kubernetes/admin.conf $HOME/.kube/config && sudo chown $(id -u):$(id -g) $HOME/.kube/config

Print a fresh join command

kubeadm token create --print-join-command

Tips

  • Do not repeatedly run init over a partial cluster; read preflight output and use kubeadm reset only deliberately.
  • Verify swap/runtime/cgroup configuration when kubelet does not become healthy.

Sources

Lifecycle, upgrades and high availability

Tracks: CKA — Level: Advanced — ~64 min

Plan safe version changes and resilient control planes. Apply version-skew rules, drain nodes, upgrade kubeadm and kubelet in sequence, and reason about stacked versus external etcd.

Objectives

  • Perform a kubeadm upgrade in the correct order
  • Use cordon, drain and uncordon safely
  • Compare stacked-etcd and external-etcd HA topologies
Reconciliation path
intent → observation → action
kubectlclient API serverdesired state etcdpersistence controllersreconcile kubeletnode action observed status returns through the API

Upgrade one minor step at a time

Read the target-version instructions, upgrade the first control plane with kubeadm upgrade plan/apply, then upgrade other control-plane nodes and workers. kubelet and kubectl packages follow the control-plane step.

Drain respects workload policy

cordon prevents new scheduling. drain evicts managed Pods while respecting PodDisruptionBudgets, with explicit handling for DaemonSets and local data.

HA needs redundant state and an endpoint

Multiple API servers sit behind a stable load-balanced endpoint. Stacked etcd simplifies operations; external etcd separates failure domains at higher operational cost.

Command drills

Prepare a node

kubectl cordon worker-1 && kubectl drain worker-1 --ignore-daemonsets --delete-emptydir-data

Plan control-plane upgrade

sudo kubeadm upgrade plan

Return node to service

kubectl uncordon worker-1

Tips

  • Check PodDisruptionBudgets before draining.
  • Never upgrade every control-plane member simultaneously.

Sources

Authentication, authorization and RBAC

Tracks: CKA — Level: Intermediate — ~56 min

Translate access requirements into the least-privilege Role, ClusterRole, RoleBinding or ClusterRoleBinding, then test effective permissions instead of assuming them.

Objectives

  • Distinguish authentication, authorization and admission
  • Choose namespace-scoped versus cluster-scoped RBAC objects
  • Verify permissions with kubectl auth can-i and impersonation
Access decision
identity → rules → admission
Requestverb + resource Authenticatewho? Authorizemay they? Admissionis it allowed? RBAC bindingsubject → role API objectpersist

Three gates

Authentication establishes identity. Authorization decides whether that identity may perform the verb on the resource. Admission can validate or mutate an authorized request.

Rules grant; they do not deny

RBAC rules are additive. Roles contain rules; bindings connect subjects to roles. A RoleBinding can bind a ClusterRole while limiting it to one namespace.

ServiceAccounts are workload identities

Pods use ServiceAccounts to access the API. Avoid default broad bindings and disable automatic token mounting where API access is unnecessary.

Command drills

Create a namespace Role

kubectl create role pod-reader --verb=get,list,watch --resource=pods -n team-a

Bind a ServiceAccount

kubectl create rolebinding reader --role=pod-reader --serviceaccount=team-a:reporter -n team-a

Test effective access

kubectl auth can-i delete pods -n team-a --as=system:serviceaccount:team-a:reporter

Tips

  • Use API resource names such as deployments and subresources such as pods/log.
  • A ClusterRoleBinding grants cluster-wide scope; confirm that this is intended.

Sources

Scheduling, placement and admission

Tracks: CKA — Level: Advanced — ~60 min

Control placement using node selectors, affinity, anti-affinity, topology spread, taints, tolerations and resource requests, while recognizing admission-time policy failures.

Objectives

  • Explain the filter-and-score scheduling cycle
  • Combine hard and soft placement constraints
  • Diagnose Pending Pods from events and scheduler evidence
Scheduler filter and score
constraints first, preferences second
Pending Podrequests + rules Filterhard constraints Scorepreferences worker-1rejected worker-2score 82 worker-3score 64

Hard constraints filter; preferences score

required affinity and nodeSelector eliminate nodes. preferred affinity influences ranking. Topology spread distributes replicas across labeled failure domains.

Taints repel; tolerations permit

A toleration allows but does not force placement. NoSchedule blocks new placement; NoExecute can evict existing Pods that lack a matching toleration.

Admission happens before scheduling

Quota, policy and webhook errors can reject a Pod before it exists. A Pending Pod, by contrast, has passed admission and is waiting for scheduling or dependencies.

Command drills

Taint a node

kubectl taint nodes worker-2 dedicated=gpu:NoSchedule

Label a topology domain

kubectl label node worker-1 topology.kubernetes.io/zone=zone-a

Read scheduling failure

kubectl describe pod pending-app | sed -n '/Events:/,$p'

Tips

  • Do not add a toleration when the task actually requires positive attraction; pair it with affinity or selector.
  • Check allocatable resources, not node capacity alone.

Sources

Persistent storage and dynamic provisioning

Tracks: CKA — Level: Advanced — ~66 min

Bind application claims to durable volumes, select access and volume modes, understand reclaim policy, and debug Pending claims or mount failures.

Objectives

  • Trace StorageClass → PVC → PV → Pod
  • Choose access mode, volumeMode and reclaim policy
  • Diagnose binding, topology and mount errors
Persistent storage chain
claim → class → provisioner → volume
Podmount PVC2Gi · RWO StorageClassfast CSI driverprovision PVbound volume

Claims separate consumers from infrastructure

A PVC requests capacity, access mode and optionally a StorageClass. A matching PV may be pre-created or dynamically provisioned.

Binding is specific

Storage class, requested capacity, access modes, selectors and topology influence matching. WaitForFirstConsumer delays provisioning or binding until scheduling provides topology context.

Deletion behavior is policy

Retain preserves the backing storage for manual recovery. Delete removes dynamically provisioned assets when the claim is deleted, subject to driver behavior and finalizers.

Command drills

List the storage chain

kubectl get storageclass,pv,pvc -A

Inspect a Pending claim

kubectl describe pvc data -n app

Create a quick PVC manifest

cat <<'EOF' > pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data
spec:
  accessModes: [ReadWriteOnce]
  resources:
    requests:
      storage: 2Gi
EOF

Tips

  • A PVC can be Bound while the Pod still fails to mount; inspect Pod Events and CSI components.
  • ReadWriteOnce means one node at a time, not necessarily one Pod.

Sources

Cluster networking, CNI and CoreDNS

Tracks: CKA — Level: Advanced — ~62 min

Reason from the Kubernetes network model down through CNI, routes, service forwarding and DNS. Isolate failures by testing each hop rather than changing multiple layers.

Objectives

  • State the pod-to-pod network requirements
  • Differentiate CNI, kube-proxy/service implementation and CoreDNS responsibilities
  • Use endpoint, route and DNS evidence to locate a failure
Service traffic path
DNS → virtual IP → ready endpoint
Client Podfrontend CoreDNSapi.backend Service10.96.0.42:80 Pod A10.244.2.8:8080 Pod B10.244.1.7:8080 NotReadyexcluded

Every Pod gets a routable identity

The Kubernetes model expects Pods to communicate without application-level NAT. A CNI implementation allocates addresses and establishes connectivity according to its design.

Service forwarding is separate

kube-proxy or an alternative data plane watches Services and EndpointSlices and programs packet handling. A working Pod network does not prove Service virtual IPs work.

DNS is an application in the cluster

CoreDNS is typically a Deployment exposed by the kube-dns Service. Debug its Pods, Service, endpoints, configuration and upstream resolution like any other workload.

Command drills

Check network system Pods

kubectl -n kube-system get pods -o wide

Inspect DNS

kubectl -n kube-system get deploy,svc,endpointslice -l k8s-app=kube-dns

Test path from a Pod

kubectl run netcheck --rm -it --restart=Never --image=nicolaka/netshoot -- bash

Tips

  • Separate Pod-IP, Service-IP and DNS tests; each removes a layer of uncertainty.
  • A NetworkPolicy only has effect when the network implementation enforces it.

Sources

Ingress, Gateway API and NetworkPolicy

Tracks: CKA — Level: Advanced — ~64 min

Publish HTTP traffic and restrict east-west flows. Compare Ingress and Gateway API resources, then build default-deny and explicit-allow NetworkPolicies with correct selectors.

Objectives

  • Map external HTTP routing from listener to backend Service
  • Use GatewayClass, Gateway, HTTPRoute and ReferenceGrant concepts
  • Compose ingress and egress NetworkPolicies safely
Service traffic path
DNS → virtual IP → ready endpoint
Client Podfrontend CoreDNSapi.backend Service10.96.0.42:80 Pod A10.244.2.8:8080 Pod B10.244.1.7:8080 NotReadyexcluded

Resources need controllers

Ingress and Gateway API objects describe intent; a matching controller implements it. Creating an Ingress alone does not create a data plane.

Gateway API separates roles

Infrastructure providers manage GatewayClasses; cluster operators manage Gateways; application teams attach Routes. This structure supports richer and more portable traffic policy.

NetworkPolicy is additive

Once a Pod is selected for an ingress or egress policy, allowed traffic is the union of matching policies. A connection requires both source egress and destination ingress to permit it when both are isolated.

Command drills

List routes and gateways

kubectl get gatewayclass,gateway,httproute -A

Create an Ingress skeleton

kubectl create ingress web --rule="example.test/=web:80" --dry-run=client -o yaml

Find selected policy Pods

kubectl get pods -n app -l role=db --show-labels

Tips

  • Start policy tasks by identifying selected destination Pods and their namespace labels.
  • Do not confuse an empty podSelector, which selects all Pods, with an omitted policyTypes decision.

Sources

CRDs, operators, Helm and Kustomize

Tracks: CKA — Level: Intermediate — ~58 min

Extend and package Kubernetes without losing sight of the resulting API objects. Inspect CRDs and operator ownership, render Helm charts, and build Kustomize overlays before applying them.

Objectives

  • Explain CRD versus controller/operator roles
  • Render and inspect Helm releases
  • Use Kustomize bases, overlays and patches
Declarative object
spec and status converge
YAMLapiVersion · kind API pipelineauth · admit · validate specdesired statusobserved loopretry

CRDs add nouns; controllers add behavior

A CustomResourceDefinition registers a new API type. A controller watches instances and implements reconciliation. Installing only the CRD does not implement the product.

Helm templates packages

A chart renders parameterized manifests and tracks releases. Use helm template or install --dry-run to inspect output before applying.

Kustomize transforms plain YAML

Bases contain reusable resources; overlays apply patches, names, labels and image changes without introducing a templating language. kubectl includes a kustomize integration.

Command drills

Discover custom APIs

kubectl api-resources --api-group=apiextensions.k8s.io && kubectl get crd

Render a chart

helm template demo ./chart -f values-prod.yaml > rendered.yaml

Preview an overlay

kubectl kustomize overlays/prod | less

Tips

  • After Helm failure, inspect the rendered Kubernetes resources rather than treating Helm as a black box.
  • Know whether a task asks you to change source files or only live resources.

Sources

Systematic troubleshooting and etcd recovery

Tracks: CKA — Level: Advanced — ~78 min

Use a layered incident method under time pressure: scope, observe, form a narrow hypothesis, test it, make one reversible change, and verify end-to-end. Include node, workload, network and control-plane recovery.

Objectives

  • Build a fast triage sequence from cluster to container
  • Read Events, logs, status conditions and system journals
  • Snapshot and restore etcd with correct endpoints and certificates
Troubleshooting funnel
scope → evidence → hypothesis → verify
Scopecontext · nodes Observestatus · events Hypothesisone cause Changesmall Verifypath failed verification returns to evidence, not guessing

Start broad, then descend

Confirm context and scope; inspect nodes and system Pods; locate failing namespaces; read object status and Events; then inspect logs, dependencies and host services.

Preserve evidence

Capture current YAML, logs and timestamps before deleting or restarting. Recreating a Pod can erase the clue you need.

etcd recovery is configuration recovery

A snapshot is only useful if you know the endpoints, CA, client certificate and key, and how the API server will be redirected to the restored data directory. Verify snapshot status before relying on it.

Command drills

Fast cluster triage

kubectl get nodes; kubectl get pods -A -o wide | grep -v Running

Sort recent events

kubectl get events -A --sort-by=.lastTimestamp | tail -40

Snapshot etcd

ETCDCTL_API=3 etcdctl snapshot save /opt/backup.db --endpoints=https://127.0.0.1:2379 --cacert=/etc/kubernetes/pki/etcd/ca.crt --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key

Tips

  • Do not “fix” by deleting evidence until you have read status, events and previous logs.
  • After every change, verify the user-visible path, not merely object existence.

Sources

Images, containers and workload design

Tracks: CKAD — Level: Intermediate — ~52 min

Turn application requirements into the right image and workload design. Control entrypoints, arguments, image pulls, restart behavior and controller selection.

Objectives

  • Override image command and arguments correctly
  • Choose Deployment, StatefulSet, DaemonSet, Job or CronJob
  • Use image tags and pull policy predictably
Controller ownership
controllers replace, place or complete
Desired stateworkload object Deploymentreplaceable StatefulSetstable identity Jobcompletion Podweb-7cPoddb-0Podtask-x Observestatus

Command maps to ENTRYPOINT; args maps to CMD

Kubernetes command replaces the image entrypoint and args replaces its default arguments. The fields are arrays and do not automatically run through a shell.

Make images exam-friendly

Use small, known images for diagnostics, pin versions when reproducibility matters, and know that imagePullPolicy defaults depend partly on the tag at object creation.

Controller semantics are part of application design

Long-running replaceable replicas fit Deployments; stable identities fit StatefulSets; node agents fit DaemonSets; finite work fits Jobs.

Command drills

Override command safely

kubectl run worker --image=busybox:1.36 --restart=Never --command -- sh -c 'echo ready; sleep 3600'

Generate a Job

kubectl create job report --image=busybox:1.36 -- date --dry-run=client -o yaml

Inspect image state

kubectl get pod worker -o jsonpath='{.status.containerStatuses[0].imageID}'

Tips

  • Use sh -c only when shell expansion or compound commands are actually needed.
  • Do not mutate a controller-owned Pod to make a durable application change.

Sources

  • Images — Official documentation
  • Workloads — Official documentation
  • Jobs — Official documentation
Multi-container Pod patterns

Tracks: CKAD — Level: Intermediate — ~56 min

Design init, sidecar, adapter and ambassador patterns using shared networking, process lifecycle and volumes. Keep containers cohesive and know when they should not share a Pod.

Objectives

  • Implement ordered initialization with init containers
  • Share data through emptyDir and communicate over localhost
  • Model sidecars with lifecycle-aware behavior
Controller ownership
controllers replace, place or complete
Desired stateworkload object Deploymentreplaceable StatefulSetstable identity Jobcompletion Podweb-7cPoddb-0Podtask-x Observestatus

Init containers establish preconditions

Traditional init containers run sequentially and must complete before app containers start. They are ideal for one-time configuration generation or dependency checks.

Sidecars support the application continuously

A sidecar can proxy, synchronize, collect or transform data for the main application. Current Kubernetes supports sidecar-style init containers with restartPolicy Always, giving lifecycle ordering.

Pod boundaries matter

Containers should share a Pod when they require the same lifecycle and node, communicate tightly, or share local volumes. Independent scaling is a reason to separate them.

Command drills

Inspect all containers

kubectl get pod app -o jsonpath='{.spec.initContainers[*].name}{"\n"}{.spec.containers[*].name}{"\n"}'

Read sidecar logs

kubectl logs app -c log-agent

Copy from shared volume

kubectl exec app -c web -- cat /var/log/shared/access.log

Tips

  • Always specify -c when a Pod has multiple containers.
  • A sidecar that never exits can block Job completion unless lifecycle is modeled correctly.

Sources

Application data and volumes

Tracks: CKAD — Level: Intermediate — ~48 min

Attach ephemeral, projected and persistent data to containers. Use emptyDir for Pod-lifetime sharing, ConfigMap/Secret projections for configuration, and PVCs for durable storage.

Objectives

  • Select emptyDir, configMap, secret, projected or persistentVolumeClaim
  • Mount one key with subPath and understand update trade-offs
  • Share data safely between containers
Persistent storage chain
claim → class → provisioner → volume
Podmount PVC2Gi · RWO StorageClassfast CSI driverprovision PVbound volume

Volume lifetime follows its source

emptyDir lives for the Pod lifetime and survives container restarts. PVC-backed storage can outlive the Pod. Projected volumes combine several sources into one mount.

Mount paths can hide image data

Mounting a volume on a non-empty image directory obscures existing files at that path. subPath targets one file or directory but does not receive atomic projected-volume updates.

Permissions are application behavior

SecurityContext fields such as fsGroup and runAsUser influence access. Verify ownership and mode inside the container rather than assuming a mount problem is a storage problem.

Command drills

Inspect mounts

kubectl get pod app -o jsonpath='{range .spec.containers[*]}{.name}{": "}{.volumeMounts}{"\n"}{end}'

Create a ConfigMap from files

kubectl create configmap web-config --from-file=nginx.conf

Check mounted data

kubectl exec app -- ls -la /etc/app && kubectl exec app -- cat /etc/app/config.yaml

Tips

  • emptyDir is deleted when the Pod is removed, even if a new controller Pod has the same name pattern.
  • Use readOnly mounts where write access is not required.

Sources

Rollouts, release strategies and packaging

Tracks: CKAD — Level: Advanced — ~64 min

Deliver changes safely with rolling updates, rollback, blue/green and canary patterns. Use Helm and Kustomize as manifest-generation tools, then verify the actual rollout.

Objectives

  • Tune maxSurge and maxUnavailable
  • Implement blue/green and canary routing using labels and replicas
  • Render Helm charts and Kustomize overlays before deployment
Rolling update
capacity shifts without a hard cutover
Deploymentdesired=4 Old RSnginx:1.26 New RSnginx:1.27 oldreadyoldready newreadynewready Serviceready

RollingUpdate controls capacity during change

maxSurge allows extra Pods above desired replicas; maxUnavailable permits temporary reduction. Readiness gates whether new replicas count as available.

Blue/green changes selection

Run two versions with distinct labels and switch the Service selector after validating green. Keep rollback cheap by retaining blue briefly.

Canary changes proportion

A simple Kubernetes canary uses two controllers selected by one Service, with replica ratio approximating traffic share. More exact weighting requires a capable gateway or service mesh.

Command drills

Update and observe

kubectl set image deployment/web web=nginx:1.27 && kubectl rollout status deployment/web

Rollback

kubectl rollout history deployment/web && kubectl rollout undo deployment/web

Render then diff

helm template shop ./chart -f values.yaml | kubectl diff -f -

Tips

  • Record the original image before changing it.
  • A rollout can complete while the application is functionally wrong; test through the Service.

Sources

Observability, debugging and API maintenance

Tracks: CKAD — Level: Advanced — ~60 min

Build a fast application-debugging ladder using status, Events, logs, exec, ephemeral debugging, metrics and API discovery. Recognize deprecated resources before an upgrade.

Objectives

  • Interpret waiting and terminated container states
  • Choose logs, exec, port-forward, debug or metrics for the question
  • Find preferred and deprecated API versions
Troubleshooting funnel
scope → evidence → hypothesis → verify
Scopecontext · nodes Observestatus · events Hypothesisone cause Changesmall Verifypath failed verification returns to evidence, not guessing

Observe before entering the container

Object status, conditions, Events and logs are lower-impact and often sufficient. exec is useful when the image contains tools; kubectl debug can add an ephemeral diagnostic container when it does not.

Metrics answer capacity, not causality

kubectl top depends on a metrics pipeline and helps identify pressure. It does not replace application metrics, traces or logs.

APIs evolve

Use api-resources, explain and server dry-run to confirm current resource versions. Before a cluster upgrade, find manifests using removed APIs and migrate them.

Command drills

Debug a minimal image

kubectl debug -it pod/web --image=nicolaka/netshoot --target=web

Forward a local port

kubectl port-forward service/web 8080:80

Find served versions

kubectl api-resources -o wide | grep -i ingress

Tips

  • For multi-container Pods, name the container for logs and exec.
  • An empty log can mean the process never started; inspect container state and Events.

Sources

Application configuration and least privilege

Tracks: CKAD — Level: Advanced — ~68 min

Compose ConfigMaps, Secrets, ServiceAccounts, resource policies and SecurityContexts so an application receives only the data, compute and kernel privileges it needs.

Objectives

  • Mount and inject configuration with correct update behavior
  • Create a dedicated ServiceAccount and narrow RBAC
  • Apply non-root, capability and filesystem restrictions
Layered workload security
identity · admission · runtime · network
Workloadleast privilege Supply chainsigned imageAdmissionpolicyNetworkdefault denyRuntimedetection

Separate configuration by sensitivity and lifecycle

Use ConfigMaps for non-secret values and Secrets for confidential material, then limit who can read them. Environment variables are captured at process start; projected volumes can update.

Identity should be explicit

Assign a dedicated ServiceAccount and set automountServiceAccountToken false unless API access is needed. Bind only required verbs and resource names.

Harden from defaults

Set runAsNonRoot, disallow privilege escalation, drop capabilities, use a read-only root filesystem where possible and select RuntimeDefault seccomp. Confirm the image supports those constraints.

Command drills

Create a generic Secret

kubectl create secret generic db-creds --from-literal=username=app --from-literal=password=change-me

Create a ServiceAccount

kubectl create serviceaccount api -n app

Test workload access

kubectl auth can-i get secrets -n app --as=system:serviceaccount:app:api

Tips

  • Secret values appear redacted in describe but remain retrievable by authorized API users.
  • A secure context that prevents startup is still a failure; test image compatibility.

Sources

Application networking and policy

Tracks: CKAD — Level: Advanced — ~58 min

Expose applications with Services and Ingress, preserve named ports and readiness semantics, and constrain application traffic with selectors-based NetworkPolicies.

Objectives

  • Build a Service that selects the intended Pods
  • Route HTTP host/path rules to Service backends
  • Create default-deny plus narrowly scoped allows
Service traffic path
DNS → virtual IP → ready endpoint
Client Podfrontend CoreDNSapi.backend Service10.96.0.42:80 Pod A10.244.2.8:8080 Pod B10.244.1.7:8080 NotReadyexcluded

Names decouple ports

A Service targetPort can reference a named container port, allowing Pods to change port numbers while preserving the Service contract.

Ingress routes HTTP; Service reaches Pods

An Ingress rule points to a Service and port, not directly to Pod labels. Debug the chain independently: controller, rule, Service, EndpointSlice, Pod readiness.

Policy identities are labels

NetworkPolicy selects source and destination Pods and can combine podSelector, namespaceSelector and ipBlock. Validate namespace labels rather than assuming namespace names are directly selectable.

Command drills

Expose by named port

kubectl expose deployment api --name=api --port=80 --target-port=http

Inspect full route

kubectl describe ingress web; kubectl get svc,endpointslice -l kubernetes.io/service-name=web

Label a namespace for policy

kubectl label namespace frontend access=api --overwrite

Tips

  • Test policies from a real source Pod; object creation alone does not prove enforcement.
  • A Service selector should match the template labels of its controller, not a transient Pod-only label.

Sources

Secure cluster setup and network boundaries

Tracks: CKS — Level: Advanced — ~68 min

Establish a defensible baseline: verify binaries and images, protect API endpoints, apply network restrictions, use appropriate Ingress TLS, and benchmark configuration against recognized guidance.

Objectives

  • Identify exposed control-plane and node ports
  • Apply default-deny network posture with required exceptions
  • Use TLS and security benchmarks as verification tools, not blind scripts
Layered workload security
identity · admission · runtime · network
Workloadleast privilege Supply chainsigned imageAdmissionpolicyNetworkdefault denyRuntimedetection

Reduce reachable attack surface

Control-plane, etcd and kubelet endpoints should be reachable only from required peers and administrators. Bind addresses, firewalls and cloud security groups are part of the security boundary.

Default deny creates an explicit graph

Start with namespace-level ingress and egress isolation, then allow DNS, required frontends, dependencies and external destinations. Test both allowed and denied flows.

Benchmarks need context

CIS-style checks identify risky settings but may not match every distribution. Read the finding, locate the effective config, make a targeted change and verify the component still functions.

Command drills

List listening sockets

sudo ss -lntup

Inspect API server flags

sudo grep -E -- '--(authorization-mode|anonymous-auth|profiling|audit)' /etc/kubernetes/manifests/kube-apiserver.yaml

Inspect TLS certificate

openssl x509 -in /etc/kubernetes/pki/apiserver.crt -noout -subject -issuer -dates

Tips

  • Do not expose etcd or kubelet APIs to untrusted networks.
  • NetworkPolicy does not protect traffic outside its enforcement domain; host firewalling still matters.

Sources

API server, RBAC and admission hardening

Tracks: CKS — Level: Advanced — ~72 min

Harden identities and request handling: disable unnecessary anonymous access, narrow RBAC, rotate credentials, protect kubeconfigs and use admission controls to stop unsafe objects.

Objectives

  • Audit broad ClusterRoleBindings and risky verbs
  • Restrict ServiceAccount token exposure
  • Configure validating/mutating or built-in admission policy safely
Access decision
identity → rules → admission
Requestverb + resource Authenticatewho? Authorizemay they? Admissionis it allowed? RBAC bindingsubject → role API objectpersist

Authorization boundaries deserve inspection

Look for cluster-admin bindings, wildcard resources or verbs, create on rolebindings, impersonate, bind and escalate. These permissions can become privilege-escalation paths.

Credentials are files and API objects

Protect admin.conf, kubelet client keys, bootstrap tokens and service-account signing keys. Remove expired bootstrap credentials and avoid copying admin kubeconfigs to convenience locations.

Admission is a policy choke point

Admission occurs after authorization but before persistence. Built-in plugins and webhooks can enforce namespace policy, resource standards and image or configuration constraints. Failure policy affects availability versus enforcement.

Command drills

Find broad bindings

kubectl get clusterrolebindings -o json | jq -r '.items[] | select(.roleRef.name=="cluster-admin") | .metadata.name'

Review API access

kubectl auth can-i --list --as=system:serviceaccount:app:worker -n app

List webhook policies

kubectl get validatingwebhookconfigurations,mutatingwebhookconfigurations

Tips

  • Permissions to create Pods can often become access to mounted credentials or node capabilities; evaluate indirect escalation.
  • Back up static manifests before hardening flags.

Sources

Node, kernel and runtime hardening

Tracks: CKS — Level: Advanced — ~66 min

Reduce host attack surface through least-installed software, protected services, kernel controls, strong systemd configuration, container runtime hygiene and workload confinement with seccomp or AppArmor.

Objectives

  • Inspect services, packages, sockets and file permissions
  • Apply seccomp and AppArmor profiles
  • Differentiate container policy from host hardening
Layered workload security
identity · admission · runtime · network
Workloadleast privilege Supply chainsigned imageAdmissionpolicyNetworkdefault denyRuntimedetection

Nodes are security domains

A privileged container or kubelet credential compromise can expose every workload on a node. Minimize installed tools, patch the OS and runtime, and restrict administrative access.

Systemd and files carry trust

Review service users, capabilities, environment files, drop-ins and writable paths. Kubernetes PKI, manifests and kubeconfigs require restrictive ownership and modes.

Kernel mediation limits damage

seccomp limits syscalls; AppArmor or SELinux limits resource access; Linux capabilities split root privilege. These controls complement rather than replace non-root execution.

Command drills

Inventory services

systemctl --type=service --state=running

Check sensitive permissions

stat -c "%a %U:%G %n" /etc/kubernetes/admin.conf /etc/kubernetes/pki/ca.key

Inspect seccomp state

kubectl get pod app -o jsonpath='{.spec.securityContext.seccompProfile.type}'

Tips

  • Do not install troubleshooting packages permanently on hardened nodes when a controlled debug method is available.
  • Test profiles in audit/complain mode where appropriate before enforcing.

Sources

Pod Security Standards and secret hygiene

Tracks: CKS — Level: Advanced — ~72 min

Constrain workload privilege and reduce credential blast radius using Pod Security Standards, namespace enforcement, strict SecurityContexts, secret minimization and isolated ServiceAccounts.

Objectives

  • Apply Baseline or Restricted Pod Security profiles
  • Eliminate privileged, host namespace and dangerous capability settings
  • Limit secret visibility and token use
Layered workload security
identity · admission · runtime · network
Workloadleast privilege Supply chainsigned imageAdmissionpolicyNetworkdefault denyRuntimedetection

Restricted is a concrete target

The Restricted profile disallows privileged containers, host namespaces, unrestricted privilege escalation and unsafe capabilities, while requiring non-root and seccomp settings in supported forms.

Namespace labels turn standards into admission

Pod Security Admission can enforce, audit and warn at selected versions. Apply labels deliberately and test existing workloads before moving enforce levels.

Secrets need end-to-end controls

Use authorization, encryption at rest, restricted mounts, external secret systems where required and rotation. Avoid placing secrets in image layers, command arguments or logs.

Command drills

Enforce restricted policy

kubectl label namespace app pod-security.kubernetes.io/enforce=restricted pod-security.kubernetes.io/enforce-version=latest --overwrite

Find privileged workloads

kubectl get pods -A -o json | jq -r '.items[] | select(any(.spec.containers[]?; .securityContext.privileged==true)) | [.metadata.namespace,.metadata.name] | @tsv'

Disable token mount

kubectl patch serviceaccount default -n app -p '{"automountServiceAccountToken":false}'

Tips

  • Apply warn/audit first when hardening a namespace with unknown workloads.
  • Base64 output is not evidence of secret encryption at rest.

Sources

Network isolation and service encryption

Tracks: CKS — Level: Advanced — ~64 min

Build explicit east-west trust using NetworkPolicy and understand where transport encryption, service-mesh identities or CNI features are required beyond policy alone.

Objectives

  • Create namespace and workload-level default-deny policy
  • Allow DNS and exact service dependencies
  • Distinguish network authorization from encryption and identity
Layered workload security
identity · admission · runtime · network
Workloadleast privilege Supply chainsigned imageAdmissionpolicyNetworkdefault denyRuntimedetection

Policy says who may connect

NetworkPolicy controls allowed directions and peers based on labels, namespaces or IP ranges. It does not encrypt payloads and cannot authenticate application identity beyond selectors.

Encryption protects data in transit

TLS or mTLS protects confidentiality and integrity. Service meshes and some CNI data planes can issue workload identities and transparently encrypt traffic, but operational verification remains necessary.

Test negative paths

Security validation needs proof that disallowed traffic fails as well as proof that required traffic succeeds. Use disposable source Pods and record both results.

Command drills

Test TCP reachability

kubectl run probe --rm -it --restart=Never --image=nicolaka/netshoot -n frontend -- curl -m 3 http://api.backend.svc:8080/health

Inspect policies

kubectl get networkpolicy -A -o wide

Inspect a TLS peer

openssl s_client -connect api.example.test:443 -servername api.example.test </dev/null

Tips

  • Allow egress to cluster DNS explicitly after default-deny.
  • A successful TCP connection does not prove certificate identity was verified.

Sources

Image provenance, scanning and policy

Tracks: CKS — Level: Advanced — ~74 min

Secure the path from source to running image: minimize build context, pin and scan dependencies, sign artifacts, verify provenance and enforce trusted registries or signatures.

Objectives

  • Identify vulnerable or misconfigured images with a scanner
  • Verify image signatures and attestations
  • Design an admission policy for approved provenance
Artifact trust path
source → build → scan → sign → admit
Sourcecommit Buildimage ScanCVEs Signidentity Admitverify RunPod

Digests create immutable references

Tags can be moved; digests identify exact content. Pin critical deployment artifacts and keep a controlled update mechanism rather than remaining permanently stale.

Scanning is triage

A vulnerability scanner compares packages and metadata to advisory databases. Prioritize exploitable, reachable findings and rebuild from maintained bases; do not treat a zero-finding report as proof of safety.

Signatures connect artifact to identity

Sigstore tooling can sign and verify images and attestations. Enforcement belongs at deployment admission or an equivalent policy point, with trusted identities and failure behavior defined.

Command drills

Scan an image

trivy image --severity HIGH,CRITICAL --ignore-unfixed nginx:1.27

Verify a keyless signature

cosign verify ghcr.io/example/app@sha256:DIGEST --certificate-identity=builder@example.com --certificate-oidc-issuer=https://token.actions.githubusercontent.com

Inspect running image digests

kubectl get pods -A -o custom-columns='NS:.metadata.namespace,NAME:.metadata.name,IMAGEID:.status.containerStatuses[*].imageID'

Tips

  • Do not copy a signature-verification identity pattern without checking issuer and subject.
  • Scan the manifest and configuration as well as the package contents.

Sources

Audit, detection and incident response

Tracks: CKS — Level: Advanced — ~78 min

Detect and investigate suspicious cluster and container behavior using API audit logs, runtime rules, immutable evidence and a containment-first response sequence.

Objectives

  • Configure and read Kubernetes audit policy output
  • Use Falco-style runtime detections and tune actionable rules
  • Contain a compromised workload while preserving evidence
Detection to containment
signal becomes an evidence-backed response
Syscallevent Rulematch Alertcontext Evidencelogs · YAML Containnetwork · token Rebuildtrusted

Audit logs explain API activity

An audit policy selects stages and detail levels for requests. RequestResponse is powerful but can expose sensitive data and increase volume; choose levels by resource and risk.

Runtime detection observes behavior

Falco and similar tools evaluate system activity against rules such as unexpected shells, sensitive-file reads or outbound tools in containers. Good rules include useful context and tolerable noise.

Response is a controlled sequence

Scope the incident, preserve manifests/logs/audit evidence, isolate network and credentials, stop harmful execution, rotate affected secrets, rebuild from trusted artifacts and verify recovery. Avoid destroying the evidence trail first.

Command drills

Filter audit activity

jq 'select(.verb=="create" and .objectRef.resource=="pods") | {ts:.requestReceivedTimestamp,user:.user.username,ns:.objectRef.namespace,name:.objectRef.name}' /var/log/kubernetes/audit.log

Inspect Falco events

journalctl -u falco --since "10 minutes ago" --no-pager

Capture a workload

kubectl get pod suspect -n app -o yaml > /opt/ir/suspect-pod.yaml && kubectl logs suspect -n app --all-containers > /opt/ir/suspect.log

Tips

  • Isolate before deleting when the workload is actively harmful, but preserve enough evidence to explain entry and scope.
  • Audit policy changes require API server configuration and restart behavior awareness.

Sources

deployment-ready.yaml — Deployment, requests/limits, readiness/startup probes, Service

File: examples/deployment-ready.yaml — Deployment, requests/limits, readiness/startup probes, Service.

Read the manifest, predict the resulting objects, apply it to a disposable practice cluster, inspect events and status, then delete it. Never apply training examples unchanged to production.

apiVersion: v1
kind: Namespace
metadata:
  name: app
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: app
  labels:
    app: web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: web
          image: nginx:1.27
          ports:
            - name: http
              containerPort: 80
          resources:
            requests:
              cpu: 100m
              memory: 64Mi
            limits:
              cpu: 300m
              memory: 128Mi
          startupProbe:
            httpGet:
              path: /
              port: http
            periodSeconds: 2
            failureThreshold: 30
          readinessProbe:
            httpGet:
              path: /
              port: http
            periodSeconds: 5
            failureThreshold: 3
---
apiVersion: v1
kind: Service
metadata:
  name: web
  namespace: app
spec:
  selector:
    app: web
  ports:
    - name: http
      port: 80
      targetPort: http
service-and-ingress.yaml — Service discovery and Ingress routing

File: examples/service-and-ingress.yaml — Service discovery and Ingress routing.

Read the manifest, predict the resulting objects, apply it to a disposable practice cluster, inspect events and status, then delete it. Never apply training examples unchanged to production.

apiVersion: v1
kind: Service
metadata:
  name: api
  namespace: app
spec:
  selector:
    app: api
  ports:
    - name: http
      port: 80
      targetPort: 8080
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: api
  namespace: app
spec:
  rules:
    - host: app.example.test
      http:
        paths:
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: api
                port:
                  number: 80
gateway-route.yaml — Gateway API HTTPRoute structure

File: examples/gateway-route.yaml — Gateway API HTTPRoute structure.

Read the manifest, predict the resulting objects, apply it to a disposable practice cluster, inspect events and status, then delete it. Never apply training examples unchanged to production.

# Requires Gateway API CRDs and a Gateway named public in namespace app.
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: api
  namespace: app
spec:
  parentRefs:
    - name: public
  hostnames:
    - app.example.test
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /api
      backendRefs:
        - name: api
          port: 80
network-policy-default-deny.yaml — Namespace isolation baseline

File: examples/network-policy-default-deny.yaml — Namespace isolation baseline.

Read the manifest, predict the resulting objects, apply it to a disposable practice cluster, inspect events and status, then delete it. Never apply training examples unchanged to production.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny
  namespace: backend
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress
network-policy-exact-allow.yaml — Namespace + Pod selectors and DNS egress

File: examples/network-policy-exact-allow.yaml — Namespace + Pod selectors and DNS egress.

Read the manifest, predict the resulting objects, apply it to a disposable practice cluster, inspect events and status, then delete it. Never apply training examples unchanged to production.

# Namespace frontend must carry the standard label
# kubernetes.io/metadata.name=frontend.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: api-ingress-from-frontend
  namespace: backend
spec:
  podSelector:
    matchLabels:
      app: api
  policyTypes:
    - Ingress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: frontend
          podSelector:
            matchLabels:
              role: client
      ports:
        - protocol: TCP
          port: 8080
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: dns-egress
  namespace: backend
spec:
  podSelector: {}
  policyTypes:
    - Egress
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kube-system
      ports:
        - protocol: UDP
          port: 53
        - protocol: TCP
          port: 53
rbac-reader.yaml — Least-privilege ServiceAccount, Role, RoleBinding

File: examples/rbac-reader.yaml — Least-privilege ServiceAccount, Role, RoleBinding.

Read the manifest, predict the resulting objects, apply it to a disposable practice cluster, inspect events and status, then delete it. Never apply training examples unchanged to production.

apiVersion: v1
kind: Namespace
metadata:
  name: finance
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: auditor
  namespace: finance
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-auditor
  namespace: finance
rules:
  - apiGroups: [""]
    resources: ["pods", "pods/log"]
    verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: auditor
  namespace: finance
subjects:
  - kind: ServiceAccount
    name: auditor
    namespace: finance
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: pod-auditor
pvc-deployment.yaml — Dynamic claim and volume mount

File: examples/pvc-deployment.yaml — Dynamic claim and volume mount.

Read the manifest, predict the resulting objects, apply it to a disposable practice cluster, inspect events and status, then delete it. Never apply training examples unchanged to production.

# Replace storageClassName if your cluster does not provide "fast".
apiVersion: v1
kind: Namespace
metadata:
  name: database
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: data
  namespace: database
spec:
  storageClassName: fast
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: database
  namespace: database
spec:
  replicas: 1
  selector:
    matchLabels:
      app: database
  template:
    metadata:
      labels:
        app: database
    spec:
      containers:
        - name: database
          image: postgres:17
          env:
            - name: POSTGRES_PASSWORD
              value: training-only
          volumeMounts:
            - name: data
              mountPath: /var/lib/postgresql/data
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: data
restricted-deployment.yaml — Restricted-style workload security context

File: examples/restricted-deployment.yaml — Restricted-style workload security context.

Read the manifest, predict the resulting objects, apply it to a disposable practice cluster, inspect events and status, then delete it. Never apply training examples unchanged to production.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: payments
  namespace: secure
spec:
  replicas: 1
  selector:
    matchLabels:
      app: payments
  template:
    metadata:
      labels:
        app: payments
    spec:
      securityContext:
        runAsNonRoot: true
        seccompProfile:
          type: RuntimeDefault
      containers:
        - name: payments
          image: nginxinc/nginx-unprivileged:1.27
          securityContext:
            allowPrivilegeEscalation: false
            readOnlyRootFilesystem: true
            capabilities:
              drop:
                - ALL
          volumeMounts:
            - name: cache
              mountPath: /var/cache/nginx
            - name: run
              mountPath: /var/run
      volumes:
        - name: cache
          emptyDir: {}
        - name: run
          emptyDir: {}
multicontainer-pod.yaml — Init container, sidecar, and shared emptyDir volumes

File: examples/multicontainer-pod.yaml — Init container, sidecar, and shared emptyDir volumes.

Read the manifest, predict the resulting objects, apply it to a disposable practice cluster, inspect events and status, then delete it. Never apply training examples unchanged to production.

apiVersion: v1
kind: Pod
metadata:
  name: web-composite
  namespace: app
spec:
  restartPolicy: Always
  volumes:
    - name: html
      emptyDir: {}
    - name: logs
      emptyDir: {}
  initContainers:
    - name: seed
      image: busybox:1.36
      command: ["sh", "-c", "printf 'ready from init\\n' > /work/index.html"]
      volumeMounts:
        - name: html
          mountPath: /work
  containers:
    - name: web
      image: nginx:1.27
      volumeMounts:
        - name: html
          mountPath: /usr/share/nginx/html
        - name: logs
          mountPath: /var/log/nginx
    - name: heartbeat
      image: busybox:1.36
      command: ["sh", "-c", "while true; do date -Iseconds >> /logs/heartbeat.log; sleep 10; done"]
      volumeMounts:
        - name: logs
          mountPath: /logs
job-cronjob.yaml — Parallel Job and controlled CronJob

File: examples/job-cronjob.yaml — Parallel Job and controlled CronJob.

Read the manifest, predict the resulting objects, apply it to a disposable practice cluster, inspect events and status, then delete it. Never apply training examples unchanged to production.

apiVersion: batch/v1
kind: Job
metadata:
  name: checksum
  namespace: batch
spec:
  completions: 3
  parallelism: 2
  template:
    spec:
      restartPolicy: Never
      containers:
        - name: checksum
          image: busybox:1.36
          command: ["sha256sum", "/etc/hosts"]
---
apiVersion: batch/v1
kind: CronJob
metadata:
  name: cleanup
  namespace: batch
spec:
  schedule: "*/15 * * * *"
  concurrencyPolicy: Forbid
  successfulJobsHistoryLimit: 2
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: Never
          containers:
            - name: cleanup
              image: busybox:1.36
              command: ["sh", "-c", "echo cleanup"]
kind-cka-lab.yaml — Three-node disposable kind cluster

File: examples/kind-cka-lab.yaml — Three-node disposable kind cluster.

Read the manifest, predict the resulting objects, apply it to a disposable practice cluster, inspect events and status, then delete it. Never apply training examples unchanged to production.

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
  - role: control-plane
  - role: worker
    labels:
      workload: general
  - role: worker
    labels:
      workload: analytics
kustomize/ — Base and production overlay

Files: examples/kustomize/ — Base and production overlay.

A minimal kustomize tree: a reusable base plus a production overlay that patches replicas and resources. Render each with kubectl kustomize and diff the outputs before applying to a disposable practice cluster.

kustomize/
├── base/
│   ├── deployment.yaml
│   ├── kustomization.yaml
│   └── service.yaml
└── overlays/
    └── prod/
        ├── kustomization.yaml
        └── resources-patch.yaml

kustomize/base/deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
spec:
  replicas: 1
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      containers:
        - name: api
          image: nginx:1.27
          resources:
            requests:
              cpu: 50m
              memory: 32Mi

kustomize/base/kustomization.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: app
resources:
  - deployment.yaml
  - service.yaml
commonLabels:
  app.kubernetes.io/managed-by: kustomize

kustomize/base/service.yaml

apiVersion: v1
kind: Service
metadata:
  name: api
spec:
  selector:
    app: api
  ports:
    - port: 80
      targetPort: 80

kustomize/overlays/prod/kustomization.yaml

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - ../../base
namePrefix: prod-
replicas:
  - name: api
    count: 3
images:
  - name: nginx
    newTag: "1.27"
patches:
  - path: resources-patch.yaml

kustomize/overlays/prod/resources-patch.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: api
spec:
  template:
    spec:
      containers:
        - name: api
          resources:
            requests:
              cpu: 200m
              memory: 128Mi
            limits:
              cpu: 500m
              memory: 256Mi
CKA — 6-week study plan

Exam: Certified Kubernetes Administrator (CKA) — v1.352 hours

Build, operate, upgrade, secure, network, store and troubleshoot production-style Kubernetes clusters.

Domain weights

DomainWeight
Storage10%
Troubleshooting30%
Workloads & Scheduling15%
Cluster Architecture, Installation & Configuration25%
Services & Networking20%

6-week plan

WeekFocusOutputs
1Core objects and kubectlComplete foundation lessons 1–5; Finish Labs 1–5; Build a personal kubectl alias sheet
2Workloads, scheduling and storageComplete controller and health lessons; Finish rollout, scheduling and PVC labs; Practice YAML generation without notes
3Architecture and lifecycleStudy component failure paths; Run kubeadm and upgrade scenarios in a real playground; Repeat RBAC lab from memory
4NetworkingTrace Service → EndpointSlice → Pod; Write three NetworkPolicies; Practice Ingress and Gateway API
5Troubleshooting under timeComplete node repair and incident drills; Practice etcd snapshot/restore on a disposable cluster; Run first timed mock
6Exam simulation and reviewRun two full timed mocks; Review every failed validator; Repeat weak domains at command-line speed
CKAD — 6-week study plan

Exam: Certified Kubernetes Application Developer (CKAD) — v1.352 hours

Design, configure, deploy, observe and troubleshoot cloud-native applications on Kubernetes.

Domain weights

DomainWeight
Application Design and Build20%
Application Deployment20%
Application Observability and Maintenance15%
Application Environment, Configuration and Security25%
Services and Networking20%

6-week plan

WeekFocusOutputs
1Manifest and kubectl fluencyComplete foundation lessons; Generate Pod/Deployment/Service YAML quickly; Finish Labs 1–5
2Application designSelect workload types from scenarios; Build init and sidecar patterns; Practice volumes and command overrides
3Deployment and packagingPerform rollouts and rollback; Build blue/green and canary examples; Render Helm and Kustomize changes
4Configuration and securityComplete configuration and Restricted-profile labs; Practice ServiceAccounts/RBAC; Tune probes and resources
5Networking and debuggingDebug Service chains; Write NetworkPolicies; Use logs, exec, debug and port-forward
6Timed application tasksRun two timed mocks; Reduce manifest editing time; Repeat every missed task from a clean reset
CKS — 6-week study plan

Exam: Certified Kubernetes Security Specialist (CKS) — v1.352 hours

Harden clusters and workloads, secure the supply chain, and detect suspicious runtime behavior.

Prerequisite: An active CKA certification is required.

Domain weights

DomainWeight
Cluster Setup15%
Cluster Hardening15%
System Hardening10%
Minimize Microservice Vulnerabilities20%
Supply Chain Security20%
Monitoring, Logging and Runtime Security20%

6-week plan

WeekFocusOutputs
1CKA prerequisite refreshReview architecture, RBAC, networking and troubleshooting; Complete CKA RBAC and NetworkPolicy labs; Verify command fluency
2Cluster and host hardeningAudit API server and node exposure; Practice seccomp/AppArmor tasks; Review sensitive file permissions
3Workload isolationEnforce Pod Security Standards; Build default-deny policies; Remove unnecessary ServiceAccount tokens
4Supply chainScan images and manifests; Verify signatures and identities; Design admission enforcement
5Audit and runtime responseRead audit records; Tune runtime detections; Run evidence-preserving containment lab
6Timed security incidentsRun two timed mocks; Repeat hardening changes on a disposable cluster; Document rollback for every control-plane edit