Certified Kubernetes Security Specialist (CKS) #19: Exam tips, time management, and patterns people get wrong

From #1 through #18 we covered all six domains. This post is a condensed read to go through one more time right before you walk into the hands-on exam. There’s no new domain here — it gathers only how to run the 2-hour hands-on exam and the traps where security tasks most often leak points across the whole series. Because this isn’t multiple choice but an exam that makes a real cluster safer from an empty terminal, the same knowledge still comes down to execution being the deciding factor between passing and failing.

Strategy for running the 2 hours #

Running it task by task #

CKS asks you to solve roughly 15–20 tasks within 2 hours. Rather than splitting time evenly per question like a multiple-choice test, each task’s point value is shown on screen, and that value is your priority. CKS’s distinctive trait is that each task requires a different tool. One task is about AppArmor, the next about Trivy, the one after that about Falco rules — so the moment you hit a tool your hands aren’t used to, it’s easy to get stuck on a single task entirely.

PhaseTimeAction
First passAbout 90 minStart with high-value tasks using tools your hands know. If stuck, flag it and move on immediately
Second passAbout 20 minRevisit only flagged tasks. Secure partial credit at least
VerificationAbout 10 minConfirm results with k get, re-check context, namespace, node, and loaded profiles

The first rule of time management #

Don’t over-invest in a single task. If a task is taking long relative to its point value, build it out as far as you can, flag it, and move on. The passing line is 67%, so you can give up one or two hard tasks. Clinging to one task with an unfamiliar tool while missing two or three NetworkPolicy or RBAC tasks your hands know well is the most common failure.

Start with the tools your hands know #

CKS is a tool-by-tool exam, so difficulty varies widely from task to task. Skim the task list start to finish once, mentally marking difficulty against point value. Handle tasks with a fixed procedure your hands know — NetworkPolicy default deny, RBAC least privilege, PSA labels — first to pile up points quickly. Placing the labor-heavy or node-internal tasks — loading an AppArmor profile on a node, specifying a seccomp path, writing Falco rules — in the middle is the way to clear the passing line.

Re-running the setup #

Finish the setup you established in #1 within one minute right after the exam starts. CKS too has plenty of tasks solved with kubectl, so the same speed setup as CKA/CKAD turns directly into points.

# kubectl to k
alias k=kubectl

# dry-run + YAML output to do
export do="--dry-run=client -o yaml"

# immediate deletion to now (to quickly delete and recreate a Pod)
export now="--force --grace-period=0"

# completion (extends to k as well)
source <(kubectl completion bash)
complete -o default -F __start_kubectl k

In ~/.vimrc, add the settings that prevent YAML indentation mishaps. It matters even more in CKS, where you frequently edit manifests like seccomp/AppArmor paths or securityContext fields that won’t apply if even one space is off.

set expandtab
set tabstop=2
set shiftwidth=2
set number

To indent a whole YAML block, select the lines in visual mode (V), indent one level with >, and repeat with .. When you copy and paste a securityContext or PSA label snippet from the docs, auto-indent interferes, so turn on :set paste right before pasting.

Switch context first of all #

Like CKA, CKS also has multiple clusters, and each task is graded only if solved on the designated cluster. If you don’t run first the use-context command given at the top of the task description, you’ll work on the wrong cluster and score zero even if you built the profile correctly or applied the policy right.

# the very first thing for each task
k config use-context <the context specified in the task>

# check which cluster you're on right now
k config current-context

CKS has a larger share of tasks that take you inside the nodes than CKA. Tasks like loading an AppArmor profile, placing a seccomp profile file, tuning kernel parameters, and installing Falco or modifying its rules must be solved after you SSH into the designated node. If you do a control-plane-node task on a worker node, there are no points.

# connect to the hostname given in the task
ssh node01

# when the task is done, always leave to return to the original environment
exit

A common mistake is starting the next task while still SSH’d into a node. Making it one motion to leave with exit once the node task is done prevents wrong answers. If you start a kubectl task while inside a node, things get created in the wrong environment.

Make fast use of the official docs #

During CKS, you’re allowed to browse not only kubernetes.io/docs but also the official docs of designated tools like Falco, Trivy, AppArmor, and gVisor. Security tools have long syntax and options that are hard to memorize, so doc usage is even more decisive than in CKA. There are two principles for running it, though.

  • Learn where the docs live in advance. Figuring out the doc structure for the first time at the testing center loses you whole chunks of time. Get it into your hands beforehand: which page on kubernetes.io has the seccomp profile example, where the Falco rule syntax is in the falco.org docs, and where the Trivy severity options and AppArmor profile syntax live in their respective docs.
  • Doc time is exam time too. The timer runs while you dig through docs. For tasks you can build instantly with a generator or a memorized pattern, like NetworkPolicy or RBAC, don’t open the docs; use the docs only to check hard-to-memorize parts like profile syntax or tool options.

When you copy a YAML snippet from the docs, the indentation comes along, so it’s safer to turn off auto-indent interference with :set paste right after pasting.

Patterns people get wrong #

These are the recurring patterns that leak points on a security hands-on exam. More points are lost to execution mistakes and missing tool-specific steps than to lack of knowledge.

1) Not switching context and namespace #

Each task is graded only if solved on the designated cluster and namespace. If you don’t run the use-context command given in the task description first, you’ll work on the wrong cluster and score zero even with a correct answer. With CKS having multiple clusters, this mistake is especially frequent.

k config use-context <the context specified in the task>
k config set-context --current --namespace=<the task's namespace>

2) Forgetting to load the AppArmor profile on the node #

This is the most common point loss on AppArmor tasks. If you only reference the profile in the manifest but don’t load the profile on that node, the Pod won’t come up or enforcement won’t apply. A task is only complete once you place the profile file on the node, load it into the kernel with apparmor_parser, and reference that profile in the Pod’s securityContext.

# on the designated node: load the profile into the kernel
ssh node01
sudo apparmor_parser -q /etc/apparmor.d/custom-profile
# check the loaded state
sudo aa-status | grep custom-profile
exit
# reference the loaded profile in the Pod securityContext
securityContext:
  appArmorProfile:
    type: Localhost
    localhostProfile: custom-profile

3) Confusing the seccomp profile path #

A seccomp profile is specified as a path relative to the kubelet’s seccomp root directory. The default root is /var/lib/kubelet/seccomp; place the profile file under this directory and write only the path relative to that root in localhostProfile. Writing an absolute path or placing the file in the wrong location keeps the Pod from coming up.

# place the profile under the kubelet seccomp root
sudo mkdir -p /var/lib/kubelet/seccomp/profiles
sudo cp audit.json /var/lib/kubelet/seccomp/profiles/audit.json
# write only the path relative to the root (/var/lib/kubelet/seccomp)
securityContext:
  seccompProfile:
    type: Localhost
    localhostProfile: profiles/audit.json

4) Typos in PSA labels and confusing the mode #

Pod Security Admission is controlled by namespace labels. You must write the label key prefix (pod-security.kubernetes.io/), the mode (enforce, audit, warn), and the level (privileged, baseline, restricted) exactly. If the key is off by even one character, admission won’t act, and if you set only warn where you should use enforce, dangerous Pods pass straight through and there are no points.

k label ns prod \
  pod-security.kubernetes.io/enforce=restricted \
  pod-security.kubernetes.io/enforce-version=latest

5) Forgetting to re-encrypt after enabling etcd encryption #

Encrypting data at rest in etcd doesn’t end with creating an EncryptionConfiguration and wiring it to the apiserver with --encryption-provider-config. Applying the config only encrypts Secrets written after that point, so existing Secrets already stored in plaintext must be rewritten once to be encrypted. Skipping this re-encryption step leaves existing Secrets in plaintext and docks your score.

# after applying the config, rewrite all existing Secrets to re-encrypt them
k get secrets --all-namespaces -o json | k replace -f -

6) Missing Trivy severity and exit-code options #

On image scan tasks, the type “find and delete images with HIGH and CRITICAL vulnerabilities” comes up often. Without limiting severity with --severity HIGH,CRITICAL, results are too many to judge, and when automatic determination is needed, use the exit code with --exit-code 1. Write the severity values joined with a comma and no spaces.

# only the specified severities, with concise output
trivy image --severity HIGH,CRITICAL --quiet nginx:1.19

# exit code 1 if there are vulnerabilities
trivy image --exit-code 1 --severity CRITICAL nginx:1.19

7) Confusing the namespace a policy applies to #

For OPA/Gatekeeper or Kyverno policies and NetworkPolicy, which namespace it applies to is a key condition. A NetworkPolicy applies only to the namespace it’s created in, and a Kyverno policy’s scope differs depending on whether it’s a ClusterPolicy or a namespace-scoped Policy. If the target scope the task specifies and the policy’s scope of application diverge, the intended blocking won’t happen.

# a NetworkPolicy only works within the namespace it's created in
k get networkpolicy -n target-ns

8) Forgetting to return after SSH’ing into a node #

The System Hardening domain has many tasks solved by going directly into a node. If you finish loading AppArmor, placing seccomp files, and adjusting kernel parameters (sysctl) on the node but don’t leave with exit, the next task’s kubectl command runs in the node environment and gets created in the wrong place. Run node tasks as one bundle of ssh → task → exit.

9) Forgetting to apply and restart after a change #

To add the apiserver’s --encryption-provider-config or an admission plugin, you have to edit /etc/kubernetes/manifests/kube-apiserver.yaml, and after editing you must wait until the kubelet brings the static Pod back up for it to take effect. After changing a Falco rule, you have to restart the service for the new rule to apply. Bundle a config change together with applying and restarting as one motion.

# check whether the apiserver static Pod came back up
k get pods -n kube-system | grep apiserver
# apply the Falco rule
sudo systemctl restart falco

Partial credit and verification #

CKS is graded per task, and some tasks have partial credit. For tool tasks, you must confirm not “I built it” but “it’s actually applied and the blocking/detection works.” Run a short verification each time you finish a task.

# whether the policy/resource you built actually came up
k get networkpolicy,pod -n <namespace>

# whether PSA actually rejects a dangerous Pod (rejection means it's working)
k run test --image=nginx --privileged -n prod

# whether the AppArmor profile is loaded on the node
ssh node01 'sudo aa-status | grep custom-profile'

# whether the apiserver came back up with the new config
k get pods -n kube-system | grep apiserver

Verification takes under 30 seconds but prevents the most common point loss — “the task you thought you finished wasn’t actually applied.” Especially after editing the apiserver manifest, it takes the kubelet a few seconds to bring the new Pod up, so check k get pods -n kube-system one more time.

Easily confused concept pairs #

Here are security concept pairs that are easy to confuse in the moment during a task, condensed into a one-line difference.

PairOne-line difference
AppArmor vs seccompRestrict file/capability access with a profile vs filter system calls themselves
OPA/Gatekeeper vs KyvernoWrite policy in the Rego language vs write policy in YAML (Kubernetes-native)
PSS privileged vs baseline vs restrictedNo restriction vs block known privilege escalation vs enforce strong best practices
PSA enforce vs audit vs warnReject violating Pods vs audit log only vs warning only (the latter two still allow creation)
NetworkPolicy vs mTLSAllow/block communication at L3/L4 vs encrypt and verify identity for Pod-to-Pod traffic
gVisor vs AppArmor/seccompKernel isolation with a user-space kernel vs restricting calls on top of the host kernel

AppArmor and seccomp often appear together in one task, but what they block is different. seccomp narrows the set of system calls a container can make, while AppArmor restricts resource access like file paths, networking, and capabilities with a profile. Both operate on top of the host kernel, whereas gVisor puts a separate user-space kernel in place to peel the container one more layer off the host kernel.

Per-domain pre-exam checklist #

These are the core commands and procedures your hands should produce immediately in each domain.

Domain 1: Cluster Setup (10%) #

  • NetworkPolicy: default deny, then only the necessary ingress/egress, podSelector/namespaceSelector
  • Check the CIS benchmark with kube-bench, fix flagged items
  • Ingress TLS: wire up the tls block and a Secret (kubernetes.io/tls)
  • Binary verification: check checksums/signatures

Domain 2: Cluster Hardening (15%) #

  • RBAC least privilege: Role/ClusterRole, only the necessary verbs/resources, k auth can-i
  • ServiceAccount tokens: automountServiceAccountToken: false
  • Restricting API access: anonymous-auth, NodeRestriction admission
  • Patch known vulnerabilities by upgrading the cluster

Domain 3: System Hardening (15%) #

  • AppArmor: load on the node with apparmor_parser, securityContext.appArmorProfile
  • seccomp: place under /var/lib/kubelet/seccomp, path relative to the root
  • Minimize capabilities (drop: ["ALL"]), protect /proc
  • Run a node ssh task as one bundle, returning with exit

Domain 4: Minimize Microservice Vulnerabilities (20%) #

  • PSA: pod-security.kubernetes.io/enforce label, level and mode exact
  • Secrets: EncryptionConfiguration, re-encrypt existing Secrets
  • gVisor: specify the runsc handler with a RuntimeClass
  • Pod-to-Pod mTLS: encrypt and verify identity with a Cilium policy

Domain 5: Supply Chain Security (20%) #

  • Minimal images: distroless/scratch, remove unnecessary packages
  • Trivy scan: --severity HIGH,CRITICAL, --exit-code
  • Sign and verify with cosign, generate an SBOM
  • Reject unsigned/vulnerable images with admission

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

  • Enforce policy with OPA/Gatekeeper or Kyverno, check the scope of application
  • Write and trigger Falco rules, check logs, restart after changing rules
  • Write an audit policy, wire up apiserver --audit-policy-file/--audit-log-path
  • Container immutability (readOnlyRootFilesystem), forensics procedure

Pre-exam checks for the online-proctored exam #

CKS is an online-proctored exam where you connect to a PSI remote terminal to work. Confirm the following before the exam starts.

ID #

  • An ID with English Romanization (passport recommended), name matching your registration info exactly
  • Present both sides of the ID to the camera as the proctor’s chat guides you

Testing environment #

  • Clear everything off the desk, remove notes and posters from the walls
  • Use only one screen with dual monitors, disconnect the secondary
  • Block family and roommates from entering, secure a quiet, solo space

System #

  • Check in 30 minutes before the exam and pass the system check
  • Close background apps, notifications, and VPNs; a stable wired network is recommended
  • Right after the exam starts, set up alias k/do/completion/.vimrc first, then check context before the first task

Wrap-up #

What this post locked in:

  • Running the 2 hours. A task’s point value is your priority. Start with the tools your hands know, flag and move on if you get stuck on an unfamiliar tool, no over-investing
  • Tool-by-tool tasks. CKS uses a different tool per task, so it’s easy to get stuck on one. Pile up points starting with what your hands know
  • Setup. alias k, do, now, completion, and vim indentation within the first minute
  • Context first. CKS has multiple clusters and frequent node tasks. use-context first for each task, exit after a node task
  • Doc usage. Learn where the kubernetes.io and Falco/Trivy/AppArmor/gVisor docs live in advance; doc time is exam time too
  • Recurring mistakes. Context/namespace, AppArmor node load, seccomp path, PSA label typos, etcd re-encryption, Trivy severity options, the policy’s namespace, returning from a node, forgetting to apply/restart
  • Partial credit and verification. Build as far as you can and confirm the blocking/detection actually works
  • Easily confused concept pairs, the core procedures for each of the six domains, and online-proctored checks

Next — full-scale hands-on mock exam #

This is the last post.

In #20 Full-scale hands-on mock exam (all-domain integrated scenario + explanations), we solve an integrated scenario with a domain distribution close to the real exam and attach detailed explanations. It’s the final step — solving it on the clock like the exam environment and firming up the three heavily weighted back-half domains (microservices, supply chain, runtime) one more time.

X