Skip to content

CKS Study Path (Certified Kubernetes Security Specialist)

The CKS is the only K8s cert that asks you to actually fix a broken cluster against a stopwatch. Multiple-choice study guides will not save you. This path assumes you can already pass CKA cold and are now adding the security layer on top.

What You're Walking Into

CKS is a CNCF cert administered by the Linux Foundation, currently aligned to Kubernetes v1.27+ as of 2025-2026. It's performance-based, not multiple-choice. You get a real cluster (actually six different clusters via context switching), a terminal, and approximately 17 questions to solve in 2 hours. Passing score is 67%.

Field Value
Vendor Cloud Native Computing Foundation (CNCF) / Linux Foundation
Code CKS
Version v1.27+ (curriculum and cluster version updated periodically)
Format Performance-based, live-terminal, browser-proctored
Questions ~17 tasks
Duration 2 hours
Passing 67%
Cost $395 USD list price (regularly discounted; bundle with CKA/CKAD often available)
Validity 2 years from pass date
Retake One free retake included with initial registration
Prerequisite CKA must be active at the time you take CKS. Not "recommended" — required.
Allowed during exam One browser tab to kubernetes.io/docs, github.com/kubernetes, kubernetes.io/blog, and the docs sites for the specific tools listed in the curriculum (Falco, Trivy, etc.)

Why this cert is different

Most security certs reward you for memorizing definitions. CKS rewards you for typing kubectl commands quickly while reading documentation in another tab. You will not be asked "what is a NetworkPolicy" — you will be given a cluster where two namespaces talk to each other when they shouldn't, and asked to write a NetworkPolicy YAML that fixes it, apply it, and verify.

The honest tradeoff: CKS is harder than written K8s certs because it punishes shallow knowledge brutally, but easier than something like OSCP because the scope is bounded. If you genuinely operate Kubernetes daily, 4 weeks of focused prep is realistic. If you've only used managed K8s through a UI, plan 6-8 weeks and budget time for cluster-building practice first.


Curriculum Overview

The published CKS curriculum has six domains. Weights below are the official CNCF percentages as of the v1.27+ refresh.

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%

Three domains tie at 20%. Together they're 60% of your score: microservice hardening, supply chain, and runtime security. If your study time is constrained, weight your prep accordingly.


Domain 1: Cluster Setup (15%)

Published objectives (approximately)

  • Use Network security policies to restrict cluster level access
  • Use CIS benchmark to review the security configuration of Kubernetes components (etcd, kubelet, kubeadm, kube-apiserver)
  • Properly set up Ingress with TLS
  • Protect node metadata and endpoints
  • Verify platform binaries before deploying

What this actually means in the exam

You'll get a cluster where the kube-apiserver has insecure flags, the kubelet exposes its read-only port, and metadata endpoints are reachable from pods. You fix them by editing /etc/kubernetes/manifests/kube-apiserver.yaml (the static pod manifest), restarting components, and proving via curl/kubectl that the change took effect.

Nexus chapter mapping

Labs

Hands-on practice (do this, don't just read about it)

  • kube-bench: run it against a kind cluster you built yourself. Then run it against a kind cluster created with default settings. Compare. The deltas are exam questions.
  • CIS Kubernetes Benchmark v1.8.0+: read the actual PDF from CIS, not a summary blog. The exam wording mirrors CIS wording.
  • NetworkPolicy with Calico or Cilium: kind ships with no CNI that supports NetworkPolicy by default. Install Calico. Practice writing default-deny then opening specific ingress/egress.
  • Ingress with cert-manager: deploy nginx-ingress, request a cert from a fake CA, terminate TLS. Do it from memory.
  • Metadata blocking: in a cloud node, curl http://169.254.169.254 from a pod. Then write a NetworkPolicy that blocks egress to that IP. Verify both states.

Honest take on tools

For CIS auditing, kube-bench is the only tool you need to know for the exam. Aqua's tool. It runs as a Job, dumps a report, you read it. Alternatives like kubeaudit exist but the exam will not ask about them.


Domain 2: Cluster Hardening (15%)

Published objectives (approximately)

  • Restrict access to Kubernetes API
  • Use Role Based Access Controls to minimize exposure
  • Exercise caution in using service accounts (e.g. disable defaults, minimize permissions on newly created ones)
  • Update Kubernetes frequently

What this actually means in the exam

RBAC questions dominate this domain. You'll be given a YAML for a Role that grants too much, and asked to scope it down. Or you'll be given a ServiceAccount that should not be auto-mounted into a pod, and asked to fix the pod spec. You will write kubectl auth can-i commands to verify your work.

Nexus chapter mapping

Labs

Hands-on practice

  • Disable automountServiceAccountToken on every default ServiceAccount in three different namespaces. Then redeploy a pod and prove the token is gone.
  • Write a Role that allows only get pods in ns-app for a SA named reader. Then write a RoleBinding. Then run kubectl auth can-i list pods --as=system:serviceaccount:ns-app:reader -n ns-app and expect no. And get pods should be yes. If you can do this in 90 seconds without docs, you're exam-ready for this objective.
  • Audit existing RBAC: install rbac-tool from Insight or use kubectl-who-can. The exam itself sticks to native kubectl, but these tools train your eye for what bad RBAC looks like.
  • Anonymous auth: confirm --anonymous-auth=false on the kube-apiserver. The default in modern kubeadm clusters is false, but the exam might give you a misconfigured one.

Honest take on tools

The exam tests you on native kubectl + RBAC YAML. Don't waste time learning OPA Gatekeeper for this domain (it's relevant to Domain 4). Just write Roles and RoleBindings until your fingers hurt.


Domain 3: System Hardening (10%)

Published objectives (approximately)

  • Minimize host OS footprint (reduce attack surface)
  • Minimize IAM roles
  • Minimize external access to the network
  • Appropriately use kernel hardening tools such as AppArmor, seccomp

What this actually means in the exam

This is the smallest domain at 10%, and it's heavily about AppArmor and seccomp profiles applied to pods. Expect to be given an existing AppArmor profile on a node and asked to attach it to a pod via annotations (the older way) or securityContext.appArmorProfile (the newer way introduced in 1.30+; check which form the exam version uses).

Nexus chapter mapping

Labs

Hands-on practice

  • Write a seccomp profile in JSON that blocks unshare and mount. Place it under /var/lib/kubelet/seccomp/profiles/. Apply it to a pod via securityContext.seccompProfile.type: Localhost. Run the syscall from inside the pod (use unshare -r /bin/sh) and verify it's blocked.
  • AppArmor: write a profile that denies write to /etc. Load it on a node with apparmor_parser. Apply it to a pod. Try to touch /etc/foo from inside the pod. Verify the deny.
  • runtime/default seccomp: set this on a pod. It's the easy mode default and the exam may accept it for partial credit on a "harden this pod" question. Know the difference between RuntimeDefault, Localhost, and Unconfined.
  • Minimize host OS: practice reading systemctl list-units --type=service --state=running on a node and explaining which services should not be there. The exam may ask you to disable an unnecessary service.

Honest take on tools

AppArmor vs seccomp vs SELinux: the exam covers AppArmor and seccomp. SELinux is mentioned in the curriculum but rarely tested deeply. Most exam clusters run Ubuntu, which uses AppArmor. Don't burn time learning SELinux policy authoring for this exam — that's a separate rabbit hole.


Domain 4: Minimize Microservice Vulnerabilities (20%)

Published objectives (approximately)

  • Use appropriate pod security standards (PSS / Pod Security Admission)
  • Manage Kubernetes secrets
  • Understand and use container runtime sandboxes in multi-tenant environments (e.g., gvisor, kata containers)
  • Implement pod-to-pod encryption using Cilium

What this actually means in the exam

Pod Security Admission replaced PodSecurityPolicy in 1.25. You'll label a namespace with pod-security.kubernetes.io/enforce: restricted and verify that a pod which violates the policy is rejected. Secrets questions are usually "this Secret is stored in plaintext at-rest in etcd, encrypt it" via EncryptionConfiguration.

Nexus chapter mapping

Labs

Hands-on practice

  • Pod Security Admission: label a namespace pod-security.kubernetes.io/enforce=baseline and pod-security.kubernetes.io/warn=restricted. Apply a privileged pod and watch it get rejected. Apply a baseline-compliant pod and watch it succeed but warn. This is exam currency.
  • Encrypt secrets at rest: write an EncryptionConfiguration YAML with aescbc provider, place it on the control plane node, point kube-apiserver at it via --encryption-provider-config, restart kube-apiserver, then kubectl get secrets <name> -o yaml and prove the data is encrypted in etcd by reading it directly with etcdctl.
  • gVisor (runsc) runtime: install it on a node, register a RuntimeClass, deploy a pod with runtimeClassName: gvisor. Run dmesg from inside the pod (it should fail because gVisor blocks it).
  • OPA Gatekeeper or Kyverno: write a policy that requires every pod to have runAsNonRoot: true. Apply a violating pod and watch the admission webhook reject it.

Honest take on policy engines

OPA Gatekeeper vs Kyverno: both are valid. CNCF's curriculum has historically leaned OPA Gatekeeper because OPA is also a CNCF graduated project. Kyverno is, in my opinion, friendlier for K8s-native YAML-based policies and is what most teams actually deploy in 2025-2026 because Rego is genuinely painful. For the exam: learn enough Gatekeeper to write a basic ConstraintTemplate and a Constraint. That is what's been historically tested. For the job: deploy Kyverno.

Honest take on sandboxes

gVisor vs Kata Containers: gVisor (Google) intercepts syscalls in userspace via runsc. Kata runs each pod in a lightweight VM. Kata gives stronger isolation but heavier overhead and worse compatibility with privileged workloads. gVisor is more commonly tested because it's easier to install on a single-node exam cluster. Know that both exist; deeply learn gVisor.

Honest take on secret management

The exam tests native K8s Secrets + etcd encryption. External secret managers (Vault, AWS Secrets Manager, External Secrets Operator) are not on the exam. Don't be that candidate who tries to install Vault during the test.


Domain 5: Supply Chain Security (20%)

Published objectives (approximately)

  • Minimize base image footprint
  • Secure your supply chain: whitelist allowed image registries, sign and validate images
  • Use static analysis of user workloads (e.g., Kubernetes resources, Docker files)
  • Scan images for known vulnerabilities

What this actually means in the exam

You'll get a Deployment YAML with a bloated ubuntu:latest base image and be asked to swap to a distroless or alpine variant. You'll get an ImagePolicyWebhook or OPA constraint that whitelists registry.example.com and have to enforce it. You'll run trivy image against a tarred image and report the highest CVSS finding.

Nexus chapter mapping

Labs

Hands-on practice

  • Trivy image scan: trivy image --severity HIGH,CRITICAL nginx:1.21. Read the output. Then scan nginx:1.27-alpine and compare CVE counts. The delta is the value of staying current.
  • Dockerfile hardening: take a Dockerfile that uses FROM ubuntu:latest, runs apt-get install for 200 packages, and ends with USER root. Rewrite it to use gcr.io/distroless/static-debian12 and USER 65532:65532. Build both, scan both, compare image size and CVE count.
  • ImagePolicyWebhook: configure the kube-apiserver with --admission-control-config-file pointing to a config that calls an external webhook. Or use OPA Gatekeeper with a constraint that blocks any image not from docker.io/library/*.
  • Cosign + image signing: sign an image with cosign, push to a local registry, then write an admission policy that requires a valid signature. Sigstore tooling is in the curriculum scope.
  • kubesec, Checkov: static analysis of YAML manifests. Run kubesec scan deployment.yaml and read the score. The exam uses kubesec specifically.

Honest take on image scanners

Trivy vs Grype vs Snyk: Trivy (Aqua) is the de-facto exam tool. Free, open source, scans images, filesystems, repos, and IaC. Grype (Anchore) is a strong alternative with arguably better SBOM-centric workflows. Snyk is paid SaaS and not on the exam. For CKS, learn Trivy syntax cold. Specifically: trivy image, trivy fs, trivy config, trivy k8s.

Honest take on base images

scratch vs distroless vs alpine: scratch is empty and only works for static binaries. Distroless (Google) gives you a minimal runtime but no shell — making forensics harder but attack surface smaller. Alpine is small but has had its share of CVEs and uses musl libc which trips up some Go binaries (DNS resolution). The exam-correct answer for "minimize footprint" is usually distroless or scratch. The job-correct answer depends on whether your team can debug a no-shell container at 2 AM.


Domain 6: Monitoring, Logging, and Runtime Security (20%)

Published objectives (approximately)

  • Perform behavioral analytics of syscall process and file activities at the host and container level to detect malicious activities
  • Detect threats within physical infrastructure, apps, networks, data, users, and workloads
  • Detect all phases of attack regardless where it occurs and how it spreads
  • Perform deep analytical investigation and identification of bad actors within environment
  • Ensure immutability of containers at runtime
  • Use Kubernetes audit logs to monitor access

What this actually means in the exam

Two big things: Falco rules and kube-apiserver audit policy. You'll be given a half-written Falco rule and asked to complete it so it triggers on a specific syscall. You'll be given an audit policy YAML and asked to log all secrets access at Metadata level but pods/exec at RequestResponse level. Container immutability questions are usually about readOnlyRootFilesystem: true in pod securityContext.

Nexus chapter mapping

Labs

Hands-on practice

  • Falco rule authoring: install Falco on a node. Read /etc/falco/falco_rules.yaml. Write a custom rule under /etc/falco/falco_rules.local.yaml that triggers on open of /etc/shadow from a container. Trigger it. Find the alert in journalctl -u falco.
  • Audit policy: write a Policy resource that logs:
  • secrets, configmaps at Metadata level
  • pods/exec, pods/attach, pods/portforward at RequestResponse level
  • everything else at None Apply it via --audit-policy-file and --audit-log-path flags on kube-apiserver. Verify the log is written. Read it.
  • Immutable containers: take a Deployment, add securityContext.readOnlyRootFilesystem: true. Watch the app crash because it tries to write to /tmp. Add an emptyDir volume mounted at /tmp. Watch it work. This pattern is exam currency.
  • Strace from outside: not on the exam directly, but practicing strace -p $(pidof nginx) on a pod's PID from the node teaches you what Falco is wrapping.

Honest take on runtime tools

Falco vs Tetragon: Falco (Sysdig, CNCF graduated) uses kernel modules or eBPF to watch syscalls and matches against a rule DSL. Tetragon (Isovalent/Cilium, also eBPF-based) is newer, integrates tightly with Cilium, and supports inline enforcement (kill the process), not just detection. For the exam: Falco only. Tetragon is genuinely better for production runtime defense in 2025-2026 in my opinion, especially if you're already on Cilium, but CKS has not adopted it yet.

Sysdig commercial vs Falco: Sysdig is the company behind Falco. Their commercial product wraps Falco with a UI, threat feeds, and SIEM integration. Exam doesn't care.


Realistic Study Schedule

These timelines assume you already hold an active CKA. If you don't, stop reading this and go pass CKA first. CKS without CKA fundamentals is impossible.

Track A: Daily K8s operator (4 weeks)

You troubleshoot production K8s weekly. You can write a Deployment YAML from memory. You know the difference between a Service and an Ingress without thinking.

Week Focus Deliverable
1 Domains 1 + 2 (Cluster Setup + Hardening). kube-bench, RBAC, NetworkPolicies. A locally hardened kind cluster scoring ≥90% on kube-bench.
2 Domains 3 + 4 (System Hardening + Microservice). seccomp, AppArmor, PSA, secret encryption. One pod hardened to restricted PSA with custom seccomp + AppArmor.
3 Domains 5 + 6 (Supply Chain + Runtime). Trivy, image signing, Falco, audit policy. Working Falco install with a custom rule that detects shadow file access; a working audit policy.
4 Killer.sh simulator x2. Speed drills. Weak-area review. Two full Killer.sh runs with score ≥75%.

Track B: Managed K8s consumer (6-8 weeks)

You use EKS/GKE/AKS through cloud consoles. You've never bootstrapped a cluster with kubeadm. You know what a pod is but rarely write YAML by hand.

Week Focus Deliverable
1 Pre-work: build a 3-node kubeadm cluster on Vagrant or LXC. Repeat from scratch until you can do it in 30 minutes. Working cluster you destroyed and rebuilt three times.
2 Domain 1 (Cluster Setup). CIS benchmark, kube-bench, ingress TLS, metadata blocking. kube-bench score ≥85% on your hand-built cluster.
3 Domain 2 (Cluster Hardening). RBAC YAML until your fingers hurt. 20 RBAC scenarios solved without docs.
4 Domain 3 (System Hardening). AppArmor + seccomp profiles. Custom seccomp profile blocking unshare applied to a running pod.
5 Domain 4 (Microservice Vulns). PSA, secret encryption, gVisor, OPA Gatekeeper basics. Fully encrypted-at-rest secrets verified via etcdctl.
6 Domain 5 (Supply Chain). Trivy, distroless, image admission policies. Hardened Dockerfile with ≤5 CRITICAL CVEs.
7 Domain 6 (Runtime). Falco rules, audit policy, immutable containers. Custom Falco rule + custom audit policy both live and producing alerts.
8 Killer.sh x2, speed drills, exam booking. ≥70% on second Killer.sh attempt.

Hours per week

Plan for 8-12 hours/week. Of that, at least 60% must be hands-on terminal time. Reading without typing is wasted time on this exam. Watch a video, then immediately replicate what you saw on your own cluster.

What "ready" looks like

You're ready when you can:

  1. Solve any Killer.sh question in under the suggested time without consulting docs except for syntax confirmation.
  2. Write a NetworkPolicy YAML, RBAC Role + RoleBinding, and Pod securityContext from memory.
  3. Bookmark the kubernetes.io docs sections you'll need (NetworkPolicy, RBAC, Pod Security, Audit, Encryption Configuration) so you can navigate to them in <5 seconds during the exam.

Exam-Day Tactics (Killer.sh-Style)

Killer.sh is the practice simulator that comes free with your CKS exam registration (two attempts, each active for 36 hours). It is harder than the real exam. This is a deliberate gift. If you score 50% on Killer.sh, you'll likely pass the real CKS at 67%. If you score 70% on Killer.sh, you'll comfortably pass.

Tactical advice that actually moves the needle

  • Set up your aliases on the very first question. The exam now ships with alias k=kubectl pre-configured in some environments, but always verify. Add export do='--dry-run=client -o yaml' and export now='--grace-period=0 --force'. Save 30 seconds per question across 17 questions equals ~8 minutes — could be a full extra question.
  • Use kubectl explain constantly. k explain pod.spec.securityContext --recursive | less shows you every field. The exam allows it. Faster than the docs tab for syntax lookups.
  • Always switch context first. Each question specifies which cluster/context to use. Run kubectl config use-context <name> before anything else. Forgetting this and modifying the wrong cluster is the most common way candidates lose points.
  • Read the question twice. Then read it once more. CKS questions are precise. "Modify the Deployment named X in namespace Y" means exactly that pod, exactly that namespace. If you fix the wrong one, zero credit.
  • Flag and skip. If a question takes longer than 8 minutes, flag it and move on. 17 questions in 120 minutes means 7 minutes average. Easy questions take 3 minutes; gnarly ones take 12. Don't let one question eat your exam.
  • Verify your work. Every question has a verification step you should do yourself. After applying a NetworkPolicy, run a curl from a pod to prove it's blocked. After fixing RBAC, run kubectl auth can-i. Submitting a fix without verifying is how you lose points to typos.
  • Don't memorize YAML — bookmark and copy. The kubernetes.io docs has working examples for every resource type. Find them in advance. Know which page each lives on. Copy, modify, paste. Faster than typing from scratch.
  • vim or nano, your choice. Both are installed. The exam terminal has reasonable defaults but check if set paste or equivalent is needed before pasting YAML. Mangled indentation kills you.
  • The PSI proctor will be picky. Clear your desk. Multiple monitors are a no. ID needs to be the exact name on your CNCF account.

Image scanning

  • Trivy (Aqua, free, open source): Exam-tested. Daily-driver good. Fast, accurate, scans almost everything (images, fs, IaC, K8s). Recommended.
  • Grype (Anchore, free, open source): Strong alternative. Better integration with Syft for SBOM generation. Slightly slower in my experience.
  • Clair (RedHat/Quay): Designed for registry-side scanning. Heavier to operate. Skip unless you're running Quay.
  • Snyk (commercial SaaS): Excellent UX, dev-friendly. Costs money. Not relevant to CKS exam.

Runtime security

  • Falco (Sysdig, CNCF graduated, free): Exam-tested. eBPF or kernel module. Detect-only (no inline kill). Solid rule DSL. Recommended for exam and reasonable for production detection.
  • Tetragon (Isovalent/Cilium, free): eBPF-native, supports inline enforcement, integrates with Cilium policies. My recommendation for production in 2026 if you're already on Cilium. Not on the exam.
  • Sysdig Secure (commercial): Falco wrapped with UI, threat intel, response automation. Worth the money for SOC teams who don't want to operate Falco raw.

Policy engines

  • OPA Gatekeeper (CNCF graduated, free): Exam-tested. Rego language. Powerful but Rego is genuinely painful to debug. Required for exam.
  • Kyverno (CNCF graduated, free): K8s-native YAML policies. Easier to write, easier to debug, faster to ship. Recommended for production, especially if your team is YAML-fluent but not Rego-fluent.
  • PSA (Pod Security Admission): Built-in to K8s. Three tiers: privileged, baseline, restricted. Exam-tested. Use it. It replaced PodSecurityPolicy.

CIS benchmark scanning

  • kube-bench (Aqua, free): Exam-tested. Only tool you need. Run as a Job, read the output.

Vulnerability discovery on a live cluster

  • kube-hunter (Aqua, free): Active and passive K8s pentest tool. Mentioned in CKS curriculum. Run it against your kind cluster to see what an attacker sees.

SBOM generation

  • Syft (Anchore, free): Generates SBOMs in SPDX or CycloneDX. Pairs with Grype.
  • Trivy (also generates SBOMs): One-stop shop. My pick if you're already using Trivy.

Secrets at rest

  • Native EncryptionConfiguration with aescbc or aesgcm: Exam-tested. Sufficient for the exam.
  • KMS provider (AWS KMS, GCP KMS, Azure Key Vault, HashiCorp Vault): Production-grade. Mentioned in curriculum but rarely deeply tested.
  • External Secrets Operator + Vault: My production recommendation. Not on exam.

Image signing

  • Cosign / Sigstore: Exam-relevant. Easy CLI, no key infrastructure required for keyless signing.
  • Notary v2: OCI-native. Less common in practice than Cosign.

Common Pitfalls Real Candidates Hit

These are repeated patterns from candidate write-ups and forum threads — not invented stats, just patterns I've seen recur.

  1. Treating CKS like a written exam. Reading three CKS books and zero hands-on terminal hours equals failure. The exam doesn't ask you to define things; it asks you to do them. Type more, read less.

  2. Skipping the kubectl config use-context step. You will modify the wrong cluster. You will lose points. Every. Single. Question. Switch contexts first.

  3. Forgetting to verify. You apply a NetworkPolicy and assume it works. The grader checks whether traffic is actually blocked. If you didn't kubectl exec into a pod and curl the target to prove the block, the grader's automated check is the only verification — and if it fails, you lose all the points even though the YAML "looks right."

  4. Spending 20 minutes on one Falco rule. The runtime domain is 20% of the exam — about 3-4 questions. One Falco question is worth ~5% of your total grade. Don't bleed time.

  5. Not knowing where the docs are. The exam allows kubernetes.io/docs and the docs sites for specific tools. If you've never used the K8s docs before exam day, you'll fumble the navigation. Practice docs-driven solving during prep.

  6. Ignoring the audit log question. Every CKS exam in recent memory has included at least one audit policy question. Practice writing audit Policy YAML until you can do it cold.

  7. Stale curriculum. The CNCF refreshes the CKS curriculum roughly annually with new K8s versions. Pod Security Admission replaced PodSecurityPolicy in 1.25 — anyone studying from a 2022 book is wasting time. Always check the official curriculum PDF on cncf.io/training before you start.

  8. Underestimating Killer.sh. Candidates see their first Killer.sh score (often 30-40%) and panic, then either give up or push the exam date. Killer.sh is intentionally harder than the real exam. A Killer.sh score of 50% suggests you're pass-ready.

  9. Booking the exam before you're ready. The free retake softens this, but burning a retake on an unprepared first attempt is still a waste. Take Killer.sh first, hit ~50%, then book.

  10. Forgetting that kubectl is fast and you are slow. Practice typing common patterns (NetworkPolicy YAML, RBAC Role, Pod with securityContext) until your fingers know them. The exam clock is unforgiving.


After CKS: Where to Go Next

CKS unlocks several legitimate paths. None are "do this next" universal — pick the one that matches your actual job direction.

If you don't already hold them

  • CKA (Certified Kubernetes Administrator): Required prerequisite for CKS, so by definition you have it. Mentioned for completeness.
  • CKAD (Certified Kubernetes Application Developer): Worth holding if you write apps that run on K8s, otherwise skip.

Cloud-specific Kubernetes certs

  • AWS Certified Security – Specialty (SCS-C02) or its EKS-focused content. Useful if EKS is your daily driver.
  • Google Professional Cloud Security Engineer: GKE-heavy security cert. Solid for GKE shops.
  • Azure AZ-500 (Azure Security Engineer Associate): AKS coverage included. Good for Azure-first orgs.

Honest take: cloud security certs overlap heavily with CKS on the K8s portion but add cloud IAM, KMS, and networking depth. Pick the one matching your cloud, not all three.

Adjacent cloud-native security certs

  • PCNSE (Prisma Cloud Native Security Engineer) or similar vendor certs: Vendor-locked but useful if your org uses that vendor.
  • GCSA (GIAC Cloud Security Automation): SANS, expensive, deep on infrastructure-as-code security.

Offensive K8s direction

  • Hack The Box Certified Web Exploitation Expert or TCM Security Practical Network Penetration Tester: not K8s-specific but the methodology overlaps.
  • OSCP (PEN-200): General offensive cert. If you want to red-team K8s for a living, this plus CKS is a strong combo.
  • CSTM (Certified Security Testing Master) or GMOB / GCIH for IR-leaning offense.

What I'd actually recommend

If you just passed CKS and your job is K8s ops:

  1. Go deeper on Cilium + Tetragon (eBPF networking and security). Out of scope for CKS but where the industry is moving in 2026.
  2. Learn OPA + Conftest for IaC policy enforcement upstream of K8s.
  3. Pick up External Secrets Operator + Vault for production-grade secrets.
  4. Read every post-mortem you can find on K8s security incidents (Tesla cryptojacking, the Argo CD CVEs, the etcd exposure incidents). Pattern-match real-world failure modes.

If you just passed CKS and your job is offensive:

  1. Study container escape techniques cold (CVE-2022-0185, CVE-2024-21626 runc, etc.).
  2. Practice K8s pivoting from a compromised pod — service account token abuse, kubelet API abuse, etcd direct read.
  3. Stand up a deliberately vulnerable cluster (Bust-a-Kube, Kubernetes Goat) and exploit it end to end.

Mapped Resources Summary

Resource Purpose
Ch 51: Kubernetes Security Primary CKS chapter; covers all six domains
Ch 46: Cloud & Container Red Team Container runtime hardening, base image strategy
Ch 46: Cloud & Container Red Team Attack perspective: what you're hardening against
Ch 54: SBOM Operations Supply chain anchor for Domain 5
Ch 35: DevSecOps Pipeline CI/CD-integrated scanning patterns
Ch 24: Supply Chain Attacks Threat model context for Domain 5
Ch 32: Applied Cryptography KMS, envelope encryption for secret-at-rest
Ch 5: Detection Engineering Falco rule authoring methodology
Ch 38: Advanced Threat Hunting Behavioral baseline for runtime detection
Lab 21: Cloud Container Security Hands-on hardening
Lab 26: Container & K8s Red Team Attack-side perspective
Lab 27: K8s Attack & Defense Full attack-fix-verify loop

One-Page Ready Check

Before booking the exam, confirm you can do all of these from memory in under the listed time:

  • [ ] Build a kubeadm cluster from scratch on Linux nodes (30 min)
  • [ ] Run kube-bench and interpret the output (10 min)
  • [ ] Write and apply a NetworkPolicy that default-denies ingress in a namespace, then opens one specific path (5 min)
  • [ ] Write a Role + RoleBinding scoped to one verb on one resource for one ServiceAccount (3 min)
  • [ ] Disable automountServiceAccountToken on a pod and verify (2 min)
  • [ ] Apply a custom seccomp profile to a pod and verify a blocked syscall (8 min)
  • [ ] Apply Pod Security Admission restricted to a namespace and prove a privileged pod is rejected (5 min)
  • [ ] Configure EncryptionConfiguration for secrets and verify with etcdctl (15 min)
  • [ ] Scan a container image with Trivy and identify CRITICAL CVEs (3 min)
  • [ ] Write a Falco rule that detects a specific file access (10 min)
  • [ ] Write a kube-apiserver audit Policy and verify the log (12 min)
  • [ ] Mark a container as readOnlyRootFilesystem: true and add the volumes it needs to still function (5 min)

If any of these take 2x the time listed or you can't do them without docs, that's your weak spot. Drill it.

Pass rate optimism: candidates who systematically check each of these boxes generally report passing. Candidates who skip the verification steps or skip Killer.sh report failing. The exam is fair but unforgiving.


YAML Patterns You Should Have Memorized

The exam clock punishes candidates who type from scratch. These are the patterns that appear with high frequency in exam questions and Killer.sh — practice them until you can write each in under two minutes without reference.

Default-deny NetworkPolicy

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: app
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

Then open one path with a second policy:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
  namespace: app
spec:
  podSelector:
    matchLabels:
      app: backend
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - protocol: TCP
      port: 8080

The trap: forgetting that policyTypes: [Ingress, Egress] with no rules means deny-all-egress including DNS. Most candidates lose points by breaking DNS resolution. Add a separate egress allow for kube-dns on port 53/UDP.

RBAC Role + RoleBinding for a ServiceAccount

apiVersion: v1
kind: ServiceAccount
metadata:
  name: pod-reader-sa
  namespace: app
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-reader
  namespace: app
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-reader-binding
  namespace: app
subjects:
- kind: ServiceAccount
  name: pod-reader-sa
  namespace: app
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

Verify:

kubectl auth can-i list pods --as=system:serviceaccount:app:pod-reader-sa -n app
# yes
kubectl auth can-i create pods --as=system:serviceaccount:app:pod-reader-sa -n app
# no

Hardened Pod securityContext (PSA-restricted compliant)

apiVersion: v1
kind: Pod
metadata:
  name: hardened
  namespace: app
spec:
  automountServiceAccountToken: false
  securityContext:
    runAsNonRoot: true
    runAsUser: 65532
    runAsGroup: 65532
    fsGroup: 65532
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: app
    image: registry.example.com/distroless-app:1.0
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop: ["ALL"]
    volumeMounts:
    - name: tmp
      mountPath: /tmp
  volumes:
  - name: tmp
    emptyDir: {}

This pod will pass pod-security.kubernetes.io/enforce: restricted. If your exam question is "harden this pod to pass restricted PSA," this template is your answer.

EncryptionConfiguration for secrets at rest

apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
  - secrets
  providers:
  - aescbc:
      keys:
      - name: key1
        secret: <base64-encoded 32-byte key>
  - identity: {}

Place at /etc/kubernetes/enc/enc.yaml (any path works as long as kube-apiserver can read it). Add to kube-apiserver static pod manifest:

spec:
  containers:
  - command:
    - kube-apiserver
    - --encryption-provider-config=/etc/kubernetes/enc/enc.yaml
    volumeMounts:
    - name: enc
      mountPath: /etc/kubernetes/enc
      readOnly: true
  volumes:
  - name: enc
    hostPath:
      path: /etc/kubernetes/enc
      type: DirectoryOrCreate

After restart, force re-encryption of existing secrets:

kubectl get secrets --all-namespaces -o json | kubectl replace -f -

Verify with etcdctl that the data is no longer plaintext:

ETCDCTL_API=3 etcdctl \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key \
  get /registry/secrets/default/<secret-name>

You should see k8s:enc:aescbc:v1:key1: as the prefix. If you see plaintext, you forgot to re-encrypt.

Audit Policy YAML

apiVersion: audit.k8s.io/v1
kind: Policy
omitStages:
- RequestReceived
rules:
- level: RequestResponse
  resources:
  - group: ""
    resources: ["pods/exec", "pods/attach", "pods/portforward"]
- level: Metadata
  resources:
  - group: ""
    resources: ["secrets", "configmaps"]
- level: None
  users: ["system:kube-proxy"]
- level: Metadata

Wire into kube-apiserver:

--audit-policy-file=/etc/kubernetes/audit/policy.yaml
--audit-log-path=/var/log/kubernetes/audit.log
--audit-log-maxage=30
--audit-log-maxbackup=10
--audit-log-maxsize=100

Mount the volumes (audit policy file and log directory) into the static pod manifest. Restart. Tail the log to verify entries appear.

Falco custom rule

- rule: Read sensitive file in container
  desc: Detect read of /etc/shadow from inside a container
  condition: >
    open_read and container and fd.name in (/etc/shadow)
  output: >
    Sensitive file read in container
    (user=%user.name container=%container.name file=%fd.name)
  priority: WARNING
  tags: [filesystem, secrets]

Place at /etc/falco/falco_rules.local.yaml. Restart falco. Trigger by exec'ing into a pod and running cat /etc/shadow (or head /etc/shadow). Check journalctl -u falco -f for the alert.

OPA Gatekeeper ConstraintTemplate + Constraint

ConstraintTemplate (defines the policy logic in Rego):

apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8srequiredlabels
spec:
  crd:
    spec:
      names:
        kind: K8sRequiredLabels
      validation:
        openAPIV3Schema:
          type: object
          properties:
            labels:
              type: array
              items:
                type: string
  targets:
  - target: admission.k8s.gatekeeper.sh
    rego: |
      package k8srequiredlabels
      violation[{"msg": msg}] {
        required := input.parameters.labels
        provided := input.review.object.metadata.labels
        missing := required[_]
        not provided[missing]
        msg := sprintf("Missing required label: %v", [missing])
      }

Constraint (applies the policy with parameters):

apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: ns-must-have-owner
spec:
  match:
    kinds:
    - apiGroups: [""]
      kinds: ["Namespace"]
  parameters:
    labels: ["owner"]

Apply both. Try to create a namespace without the owner label. The webhook should reject it.


Cluster Lab Setup for Practice

Don't pay for managed K8s during prep. Build local clusters. Two approaches that work:

Option A: kind (Kubernetes in Docker)

Fastest to spin up, lightest on resources. Single binary install.

kind create cluster --name cks-prep --config kind-config.yaml

Where kind-config.yaml defines a 3-node cluster:

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker

Tradeoff: kind doesn't behave exactly like a real kubeadm cluster. The control plane runs in a container. You can't easily edit /etc/kubernetes/manifests/kube-apiserver.yaml because the control plane process is wrapped. For exercises that require touching static pod manifests, kind is awkward.

Option B: kubeadm on multipass / vagrant / lxc

Slower setup but mirrors the real exam environment. You get real nodes, real systemd, real /etc/kubernetes/manifests/, real kubelet.

# On each node, after multipass launch ubuntu instances:
sudo apt-get update && sudo apt-get install -y kubeadm kubelet kubectl
# On control plane:
sudo kubeadm init --pod-network-cidr=10.244.0.0/16
# Apply Calico for NetworkPolicy support:
kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.26.0/manifests/calico.yaml
# On workers, run the join command kubeadm printed.

This is the right environment for exam prep. Use it.

Option C: Killercoda free K8s playgrounds

killercoda.com (same company as Killer.sh) offers free interactive K8s scenarios in browser. Useful for spot-practice when you don't want to spin up a local cluster. Not a replacement for real practice clusters but good for short drills.


Quick-Reference: kube-apiserver Hardening Flags

CIS benchmark items that frequently appear on the exam, with the correct flag setting. Memorize the direction of each (some default to insecure, some default to secure).

Flag Secure setting Why
--anonymous-auth false Prevent unauthenticated API access
--insecure-port removed in 1.20+ If somehow present, set to 0
--profiling false Disable Go profiling endpoints
--audit-log-path set to a path Required for audit logging
--audit-log-maxage 30 (or per CIS) Log retention
--audit-log-maxbackup 10 Log rotation
--audit-log-maxsize 100 Per-file size cap
--encryption-provider-config path to config Required for secret encryption
--authorization-mode Node,RBAC Never AlwaysAllow
--enable-admission-plugins include NodeRestriction, PodSecurity, ImagePolicyWebhook (when applicable) Defense in depth
--service-account-key-file set SA token verification
--service-account-lookup true Validate SA tokens against API
--kubelet-certificate-authority set Verify kubelet cert chain
--tls-cert-file / --tls-private-key-file set API server TLS
--client-ca-file set Client cert verification
--etcd-cafile / --etcd-certfile / --etcd-keyfile set mTLS to etcd

The exam often phrases these as "the kube-apiserver is configured insecurely. Fix it." Open /etc/kubernetes/manifests/kube-apiserver.yaml, edit the flag, save. The kubelet detects the manifest change and restarts the static pod within ~30 seconds. Don't systemctl restart kubelet unless you're sure — it's usually unnecessary.


kubelet Hardening Flags

Edit /var/lib/kubelet/config.yaml (or the systemd dropin at /etc/systemd/system/kubelet.service.d/10-kubeadm.conf).

Setting Secure value Why
authentication.anonymous.enabled false No anonymous kubelet API
authentication.webhook.enabled true Use SubjectAccessReview
authorization.mode Webhook Never AlwaysAllow
readOnlyPort 0 Disable the unauthenticated read-only port
protectKernelDefaults true Refuse to start if kernel sysctls don't match expected secure defaults
streamingConnectionIdleTimeout 5m (or per CIS) Close idle exec/attach streams
tlsCertFile / tlsPrivateKeyFile set kubelet API TLS
clientCAFile set Verify clients (e.g., kube-apiserver)
eventRecordQPS 0 (per CIS, unlimited recording) Don't drop security-relevant events
makeIPTablesUtilChains true Manage iptables chains for service routing

After editing kubelet config: systemctl restart kubelet and verify with systemctl status kubelet. If kubelet refuses to start, you have a typo. Roll back, fix, retry.


Practice Drill: Solve This in 10 Minutes

A representative CKS-style exam question, written in the same style as Killer.sh:

Context: cluster cluster1, namespace prod.

A Deployment named payments is running with overprivileged RBAC. The ServiceAccount payments-sa currently has cluster-admin via a ClusterRoleBinding named payments-admin-binding.

Tasks: 1. Remove the cluster-admin binding for payments-sa. 2. Create a Role in the prod namespace named payments-role that grants only get and list on pods and configmaps. 3. Bind the Role to payments-sa with a RoleBinding named payments-binding. 4. Verify payments-sa can get pods in prod but cannot delete pods or access any other namespace.

Do not modify the Deployment itself.

Solution path (under 10 minutes if drilled):

kubectl config use-context cluster1
kubectl delete clusterrolebinding payments-admin-binding

cat <<EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: payments-role
  namespace: prod
rules:
- apiGroups: [""]
  resources: ["pods", "configmaps"]
  verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: payments-binding
  namespace: prod
subjects:
- kind: ServiceAccount
  name: payments-sa
  namespace: prod
roleRef:
  kind: Role
  name: payments-role
  apiGroup: rbac.authorization.k8s.io
EOF

kubectl auth can-i get pods --as=system:serviceaccount:prod:payments-sa -n prod
# expected: yes
kubectl auth can-i delete pods --as=system:serviceaccount:prod:payments-sa -n prod
# expected: no
kubectl auth can-i get pods --as=system:serviceaccount:prod:payments-sa -n default
# expected: no

If you can do this drill cleanly in 10 minutes from a cold start (no docs except for syntax), you are exam-pace for this domain. If it takes 20 minutes, drill RBAC YAML more.