Home / devops-containers / Certified Kubernetes Security Specialist (CKS) / Cheat Sheet
Certified Kubernetes Security Specialist (CKS)

CKS Cheat Sheet

CKS Tests Hardening a Live Cluster Under the Clock — Not Security Theory

CKS is a hands-on, two-hour lab of 15–20 tasks for CKA holders. The grader checks only final files, flags and objects, so make the smallest correct change, back up manifests and verify every result.

Check Your Readiness →
Among the harder certs
Avg: Not published by CNCF / The Linux Foundation
Pass: 750 / 1000
Most candidates understand Certified Kubernetes Security Specialist (CKS) concepts — and still fail. This exam tests how you apply knowledge under pressure.

CKS Curriculum Domain Map (v1.34 outline, v1.35 environment)

Sixty percent of the score sits in workload, supply chain and runtime tasks. Each task names a host and namespace; work there exactly. Editing static Pod manifests in /etc/kubernetes/manifests is routine, and one YAML error takes the API server down.

  1. 01
    Minimize Microservice Vulnerabilities (20%) — Pod Security Admission, Restricted fields, EncryptionConfiguration, RuntimeClass, Istio and Cilium encryption
  2. 02
    Supply Chain Security (20%) — multi-stage and distroless images, SBOMs, Trivy, Kubesec, KubeLinter, ImagePolicyWebhook, signatures
  3. 03
    Monitoring, Logging and Runtime Security (20%) — Falco rules, crictl mapping, audit policy levels, read-only root filesystems
  4. 04
    Cluster Setup (15%) — default-deny and metadata-blocking policies, kube-bench, kubelet config, Ingress TLS, binary checksums
  5. 05
    Cluster Hardening (15%) — least-privilege RBAC, service account tokens, anonymous auth, NodeRestriction, one-minor-step upgrades
  6. 06
    System Hardening (10%) — AppArmor and seccomp profiles, removing services and packages, node port exposure

Wrong instinct vs correct approach

Pods in namespace payments must reach the internet but never 169.254.169.254, using one policy
✕ Wrong instinct

An ingress rule denying the metadata IP

✓ Correct approach

Metadata is reached outbound, so write an Egress policy selecting all Pods with ipBlock 0.0.0.0/0 and except 169.254.169.254/32. Remember any egress default-deny elsewhere also blocks DNS on port 53.

Deployment web never calls the API but mounts the default service account token; others need tokens
✕ Wrong instinct

Set automountServiceAccountToken false on the default ServiceAccount

✓ Correct approach

Set automountServiceAccountToken: false in web's Pod template spec, which overrides the account setting without affecting neighbours. Existing Pods keep their tokens until the rollout recreates them.

Delete only Pods in namespace web whose running images have CRITICAL vulnerabilities
✕ Wrong instinct

Scan the image tags listed in the manifest files on disk

✓ Correct approach

Read images from the running Pods with kubectl get pods -o jsonpath, then run trivy image --severity CRITICAL on each. Delete only the failing Pods; removing compliant ones fails grading.

ImagePolicyWebhook must deny all Pods whenever its backend service is unreachable
✕ Wrong instinct

Enable the plugin and keep the default admission config

✓ Correct approach

Set defaultAllow: false so the control fails closed, add ImagePolicyWebhook to --enable-admission-plugins, point --admission-control-config-file at the config, and mount that directory plus the backend kubeconfig into the API server Pod.

Know these cold

  • ▸ Back up any static Pod manifest outside /etc/kubernetes/manifests before editing it
  • ▸ Two list items in a NetworkPolicy from block are ORed; one item with both selectors is ANDed
  • ▸ Kubelet hardening — nonymous.enabled false, authorization.mode Webhook, readOnlyPort 0, then restart kubelet
  • ▸ --authorization-mode Node,RBAC with NodeRestriction; AlwaysAllow first approves everything
  • ▸ kubectl auth can-i --list --as=system:serviceaccount:ns:name checks the real subject
  • ▸ list on secrets returns their data; escalate, bind and impersonate are escalation verbs
  • ▸ kubeadm upgrades one minor version at a time, control plane before kubelets
  • ▸ readOnlyRootFilesystem is container-level; add emptyDir volumes for paths the app writes
  • ▸ PeerAuthentication STRICT enforces Istio mTLS only where sidecars exist; Cilium encrypts with WireGuard or IPsec
  • ▸ Verify binaries with sha512sum against the .sha512 file published on dl.k8s.io

Can you answer these without checking your notes?

In this scenario: "Pods in namespace payments must reach the internet but never 169.254.169.254, using one policy" — what should you do first?
Metadata is reached outbound, so write an Egress policy selecting all Pods with ipBlock 0.0.0.0/0 and except 169.254.169.254/32. Remember any egress default-deny elsewhere also blocks DNS on port 53.
In this scenario: "Deployment web never calls the API but mounts the default service account token; others need tokens" — what should you do first?
Set automountServiceAccountToken: false in web's Pod template spec, which overrides the account setting without affecting neighbours. Existing Pods keep their tokens until the rollout recreates them.
In this scenario: "Delete only Pods in namespace web whose running images have CRITICAL vulnerabilities" — what should you do first?
Read images from the running Pods with kubectl get pods -o jsonpath, then run trivy image --severity CRITICAL on each. Delete only the failing Pods; removing compliant ones fails grading.

Common Exam Mistakes — What candidates get wrong

Enabling Secret encryption but leaving existing Secrets in plain text

The first provider in EncryptionConfiguration encrypts writes, so aescbc must precede identity. Mount the file into the kube-apiserver static Pod, then rewrite old Secrets with kubectl get secrets -A -o json | kubectl replace -f - and confirm k8s:enc in etcdctl.

Missing the seccomp profile when fixing Pods for Restricted enforcement

Restricted needs runAsNonRoot true, allowPrivilegeEscalation false, capabilities drop ALL and seccompProfile RuntimeDefault or Localhost. Rejections surface in ReplicaSet events, not kubectl apply output, and the Deployment template must carry the fix.

Deleting the Pod named in a Falco alert

Map the container ID with crictl inspect, find the owning Deployment, and run kubectl scale --replicas=0. Deleting the Pod only lets its ReplicaSet start a replacement, and the grader sees the workload still running.

Ordering audit policy rules with a catch-all or None rule first

Audit rules are first-match. Put specific rules, such as Secrets at Metadata, above the default. Logging Secrets at Request or RequestResponse writes their values into the log. Add hostPath mounts for the policy file and log directory.

Writing seccomp localhostProfile as an absolute path

Localhost seccomp paths are relative to /var/lib/kubelet/seccomp, e.g. profiles/restrict.json. AppArmor Localhost uses the profile name declared inside the file, loaded with apparmor_parser on every node the Pod can land on.

Resources to help you pass Certified Kubernetes Security Specialist on your first attempt

CKS is graded on final cluster state under time pressure. Find your slowest task type.