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
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
- Kubernetes components — Official documentation
- Kubernetes concepts — Official documentation
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
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
- Understanding Kubernetes objects — Official documentation
- Kubernetes API overview — Official documentation
- kubectl quick reference — Official documentation
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
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
- kubectl quick reference — Official documentation
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
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
- Namespaces — Official documentation
- Labels and selectors — Official documentation
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
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
- Pods — Official documentation
- Pod lifecycle — Official documentation
- Debugging running Pods — Official documentation
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
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
- Workloads — Official documentation
- Deployments — Official documentation
- StatefulSets — Official documentation
- DaemonSets — Official documentation
- Jobs — Official documentation
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
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
- ConfigMaps — Official documentation
- Secrets — Official documentation
- Resource management for Pods and containers — Official documentation
- Configure liveness, readiness and startup probes — Official documentation
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
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
- Service — Official documentation
- Services, Load Balancing, and Networking — Official documentation
- DNS for Services and Pods — Official documentation
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
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
- Kubernetes components — Official documentation
- Debugging Kubernetes nodes with crictl — Official documentation
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
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
- Creating a cluster with kubeadm — Official documentation
- Cluster networking — Official documentation
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
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
- Upgrading kubeadm clusters — Official documentation
- Creating highly available clusters with kubeadm — Official documentation
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
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
- Using RBAC authorization — Official documentation
- RBAC good practices — Official documentation
- Service Accounts — Official documentation
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
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
- Scheduling, Preemption and Eviction — Official documentation
- Taints and tolerations — Official documentation
- Admission controllers — Official documentation
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
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
- Persistent Volumes — Official documentation
- Storage Classes — Official documentation
- Dynamic Volume Provisioning — Official documentation
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
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
- Cluster networking — Official documentation
- Debugging DNS resolution — Official documentation
- Service — Official documentation
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
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
- Ingress — Official documentation
- Gateway API — Official documentation
- Network Policies — Official documentation
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
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
- Custom Resources — Official documentation
- Helm documentation — Official project documentation
- Declarative Management with Kustomize — Official documentation
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
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
- Troubleshooting clusters — Official documentation
- Debugging running Pods — Official documentation
- Debugging Kubernetes nodes with crictl — Official documentation
- Operating etcd clusters for Kubernetes — Official documentation
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
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
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
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
- Init Containers — Official documentation
- Sidecar Containers — Official documentation
- Pods — Official documentation
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
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
- Persistent Volumes — Official documentation
- ConfigMaps — Official documentation
- Secrets — Official documentation
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
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
- Deployments — Official documentation
- Helm documentation — Official project documentation
- Declarative Management with Kustomize — Official documentation
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
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
- Debugging running Pods — Official documentation
- Deprecated API Migration Guide — Official documentation
- Resource management for Pods and containers — Official documentation
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
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
- ConfigMaps — Official documentation
- Secrets — Official documentation
- Service Accounts — Official documentation
- Security Context — Official documentation
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
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
- Service — Official documentation
- Ingress — Official documentation
- Network Policies — Official documentation
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
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
- Security Checklist — Official documentation
- PKI certificates and requirements — Official documentation
- Network Policies — Official documentation
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
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
- Controlling access to the Kubernetes API — Official documentation
- RBAC good practices — Official documentation
- Admission controllers — Official documentation
- Service Accounts — Official documentation
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
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
- Restrict a container syscall with seccomp — Official documentation
- Restrict a container access to resources with AppArmor — Official documentation
- Security Context — Official documentation
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
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
- Pod Security Standards — Official documentation
- Enforce Pod Security Standards with namespace labels — Official documentation
- Secrets — Official documentation
- Encrypting Confidential Data at Rest — Official documentation
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
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
- Network Policies — Official documentation
- Security Checklist — Official documentation
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
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
- Trivy documentation — Official project documentation
- Cosign documentation — Official project documentation
- Images — Official documentation
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
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
- Auditing — Official documentation
- Falco documentation — Official project documentation
- Security Checklist — Official documentation
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 sharedemptyDirvolumes.
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.35 — 2 hours
Build, operate, upgrade, secure, network, store and troubleshoot production-style Kubernetes clusters.
Domain weights
| Domain | Weight |
|---|---|
| Storage | 10% |
| Troubleshooting | 30% |
| Workloads & Scheduling | 15% |
| Cluster Architecture, Installation & Configuration | 25% |
| Services & Networking | 20% |
6-week plan
| Week | Focus | Outputs |
|---|---|---|
| 1 | Core objects and kubectl | Complete foundation lessons 1–5; Finish Labs 1–5; Build a personal kubectl alias sheet |
| 2 | Workloads, scheduling and storage | Complete controller and health lessons; Finish rollout, scheduling and PVC labs; Practice YAML generation without notes |
| 3 | Architecture and lifecycle | Study component failure paths; Run kubeadm and upgrade scenarios in a real playground; Repeat RBAC lab from memory |
| 4 | Networking | Trace Service → EndpointSlice → Pod; Write three NetworkPolicies; Practice Ingress and Gateway API |
| 5 | Troubleshooting under time | Complete node repair and incident drills; Practice etcd snapshot/restore on a disposable cluster; Run first timed mock |
| 6 | Exam simulation and review | Run 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.35 — 2 hours
Design, configure, deploy, observe and troubleshoot cloud-native applications on Kubernetes.
Domain weights
| Domain | Weight |
|---|---|
| Application Design and Build | 20% |
| Application Deployment | 20% |
| Application Observability and Maintenance | 15% |
| Application Environment, Configuration and Security | 25% |
| Services and Networking | 20% |
6-week plan
| Week | Focus | Outputs |
|---|---|---|
| 1 | Manifest and kubectl fluency | Complete foundation lessons; Generate Pod/Deployment/Service YAML quickly; Finish Labs 1–5 |
| 2 | Application design | Select workload types from scenarios; Build init and sidecar patterns; Practice volumes and command overrides |
| 3 | Deployment and packaging | Perform rollouts and rollback; Build blue/green and canary examples; Render Helm and Kustomize changes |
| 4 | Configuration and security | Complete configuration and Restricted-profile labs; Practice ServiceAccounts/RBAC; Tune probes and resources |
| 5 | Networking and debugging | Debug Service chains; Write NetworkPolicies; Use logs, exec, debug and port-forward |
| 6 | Timed application tasks | Run 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.35 — 2 hours
Harden clusters and workloads, secure the supply chain, and detect suspicious runtime behavior.
Prerequisite: An active CKA certification is required.
Domain weights
| Domain | Weight |
|---|---|
| Cluster Setup | 15% |
| Cluster Hardening | 15% |
| System Hardening | 10% |
| Minimize Microservice Vulnerabilities | 20% |
| Supply Chain Security | 20% |
| Monitoring, Logging and Runtime Security | 20% |
6-week plan
| Week | Focus | Outputs |
|---|---|---|
| 1 | CKA prerequisite refresh | Review architecture, RBAC, networking and troubleshooting; Complete CKA RBAC and NetworkPolicy labs; Verify command fluency |
| 2 | Cluster and host hardening | Audit API server and node exposure; Practice seccomp/AppArmor tasks; Review sensitive file permissions |
| 3 | Workload isolation | Enforce Pod Security Standards; Build default-deny policies; Remove unnecessary ServiceAccount tokens |
| 4 | Supply chain | Scan images and manifests; Verify signatures and identities; Design admission enforcement |
| 5 | Audit and runtime response | Read audit records; Tune runtime detections; Run evidence-preserving containment lab |
| 6 | Timed security incidents | Run two timed mocks; Repeat hardening changes on a disposable cluster; Document rollback for every control-plane edit |