CKS — Exam Tips & Strategies
The 3-Pass Time Management Strategy
Time management is even more critical in CKS than CKA. CKS tasks often involve multiple steps (create profile → load → apply → verify) and security-specific tools.
Pass 1 — Quick Wins (First 10–15 Minutes)
- Scan all questions and identify easy tasks you can solve in under 2 minutes
- Complete every quick win first: set SecurityContext fields, apply a Seccomp
RuntimeDefaultprofile, switch Secrets to mounted volumes - Skip anything involving Falco rule writing, complex NetworkPolicies, or multi-step audit configurations
- Target: Complete 3–5 fast questions
Pass 2 — Medium Tasks (Next 60–70 Minutes)
- Return to medium-complexity questions: create AppArmor profiles, write basic Falco rules, configure Pod Security Admission on namespaces
- Allocate 5–8 minutes per task — if stuck after 8 minutes, flag and move on
- Use documentation for YAML structure references (NetworkPolicy spec, audit policy levels)
- Target: Complete 7–10 medium questions
Pass 3 — Hard Tasks (Remaining Time)
- Tackle remaining complex questions: multi-step Gatekeeper policies, custom Seccomp profiles, elaborate Falco rule chains, multi-namespace NetworkPolicy scenarios
- Even partial answers earn partial credit — always write something
- Use the last 5 minutes to review flagged questions and verify context switches
- Target: Attempt all remaining questions, even partially
Time Budget Summary
| Pass | Time | Task Type | Expected Questions |
|---|---|---|---|
| Pass 1 | 10–15 min | Quick wins | 3–5 |
| Pass 2 | 60–70 min | Medium tasks | 7–10 |
| Pass 3 | 25–35 min | Hard tasks + review | Remaining |
| Total | 120 min | 15–20 |
Average time per question: ~6–8 minutes. Some questions take 2 minutes, others take 15. The 3-pass approach ensures you capture all easy points first.
vi/vim Editor Shortcuts
You’ll use vi extensively in CKS — editing YAML manifests, Falco rules, AppArmor profiles, and audit policies. These shortcuts save significant time:
Essential Shortcuts
| Shortcut | Action |
|---|---|
i |
Enter insert mode (type text) |
Esc |
Exit insert mode |
:wq |
Save and quit |
:q! |
Quit without saving |
dd |
Delete current line |
5dd |
Delete 5 lines |
yy |
Copy (yank) current line |
5yy |
Copy 5 lines |
p |
Paste below current line |
P |
Paste above current line |
u |
Undo last change |
Ctrl+r |
Redo |
/search |
Search forward for “search” |
n |
Next search result |
N |
Previous search result |
:%s/old/new/g |
Replace all “old” with “new” |
G |
Go to end of file |
gg |
Go to beginning of file |
:set number |
Show line numbers |
:set paste |
Enable paste mode (preserves indentation) |
:set nopaste |
Disable paste mode |
CKS-Specific vi Tips
| Task | vi Workflow |
|---|---|
| Edit Falco rules | Open /etc/falco/falco_rules.local.yaml, use /rule: to search for rules |
| Edit AppArmor profiles | Open /etc/apparmor.d/<profile>, add deny/allow lines |
| Edit audit policy | Navigate to /etc/kubernetes/audit-policy.yaml, add rules at correct indentation |
| Edit API server manifest | Open /etc/kubernetes/manifests/kube-apiserver.yaml, careful with indentation |
| Paste YAML from docs | :set paste first, then Ctrl+Shift+V, then :set nopaste |
Always use :set paste before pasting multi-line content. Without it, vim auto-indents each line, destroying YAML structure.
First-Thing Setup
Run this at the start of your exam to optimize your shell:
# Set kubectl alias and exports
alias k=kubectl
export do="--dry-run=client -o yaml"
export now="--force --grace-period=0"
# Set vim defaults
echo 'set tabstop=2 shiftwidth=2 expandtab number' >> ~/.vimrc
YAML Best Practices for Security Resources
CKS tasks involve writing YAML for security-specific resources. Follow these patterns:
SecurityContext Template
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
spec:
securityContext:
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: nginx:1.27
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
NetworkPolicy Template (Default Deny All)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: target-namespace
spec:
podSelector: {} # Selects ALL pods in namespace
policyTypes:
- Ingress
- Egress
Audit Policy Template
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: RequestResponse
resources:
- group: ""
resources: ["secrets"]
- level: Metadata
resources:
- group: ""
resources: ["configmaps"]
- level: None
resources:
- group: ""
resources: ["events"]
Pod Security Admission Labels
apiVersion: v1
kind: Namespace
metadata:
name: secure-namespace
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
Common Exam Traps
These are mistakes that cost points in the CKS exam. Learn them before exam day:
Trap 1: Forgetting to Switch Context
Every question tells you which cluster to use. If you skip the kubectl config use-context command and work on the wrong cluster, you get zero points — even if your answer is technically correct.
Prevention: Make it a physical habit — read the context line, type the switch command, verify.
# ALWAYS start with this
kubectl config use-context <context-name>
# Verify
kubectl config current-context
Trap 2: Forgetting the Namespace
Many CKS tasks specify a namespace. If you create resources in the default namespace instead:
# WRONG — creates in default namespace
kubectl apply -f networkpolicy.yaml
# RIGHT — specify namespace
kubectl apply -f networkpolicy.yaml -n production
Or set the namespace in your context:
kubectl config set-context --current --namespace=production
Trap 3: NetworkPolicy Direction Confusion
| Direction | Meaning |
|---|---|
| Ingress | Traffic coming INTO the selected Pods |
| Egress | Traffic going OUT FROM the selected Pods |
Common mistake: Creating an ingress rule when the question asks to restrict outbound traffic (egress), or vice versa.
Prevention: Always ask yourself: “From whose perspective? Which Pod is sending, which is receiving?”
Trap 4: Wrong Seccomp Profile Path
Seccomp Localhost profiles must be relative to the kubelet’s seccomp directory:
# WRONG — absolute path
seccompProfile:
type: Localhost
localhostProfile: /var/lib/kubelet/seccomp/profiles/my-profile.json
# RIGHT — relative to seccomp root
seccompProfile:
type: Localhost
localhostProfile: profiles/my-profile.json
The kubelet automatically prepends /var/lib/kubelet/seccomp/ to the path.
Trap 5: Not Loading AppArmor Profile Before Creating Pod
# WRONG order — Pod fails because profile doesn't exist on node
kubectl apply -f pod-with-apparmor.yaml
apparmor_parser -q /etc/apparmor.d/my-profile # Too late!
# RIGHT order
apparmor_parser -q /etc/apparmor.d/my-profile # Load first
kubectl apply -f pod-with-apparmor.yaml # Then create Pod
If the profile isn’t loaded, the Pod stays in Blocked or Error state.
Trap 6: Editing Default Falco Rules
# WRONG — never edit this file (overwritten on upgrade)
vi /etc/falco/falco_rules.yaml
# RIGHT — put custom rules here
vi /etc/falco/falco_rules.local.yaml
Trap 7: Not Restarting Services After Config Changes
After editing Falco config, API server manifests, or kubelet config, you must restart the relevant service:
# After editing Falco rules
systemctl restart falco
# After editing kubelet config
systemctl restart kubelet
# After editing API server static Pod manifest
# (automatic restart — but verify it comes back)
crictl ps | grep kube-apiserver
For static Pods (API server, etcd, scheduler, controller-manager): Editing the manifest in /etc/kubernetes/manifests/ triggers automatic restart. But if the YAML is invalid, the Pod won’t come back — always validate before saving.
Trap 8: Forgetting to Verify
After applying any security configuration, verify it works:
# Verify NetworkPolicy blocks traffic
kubectl exec test-pod -- wget -qO- --timeout=2 http://target-service
# Verify AppArmor profile is enforced
kubectl get pod secure-pod -o jsonpath='{.metadata.annotations}'
# Verify Seccomp is applied
kubectl get pod secure-pod -o jsonpath='{.spec.securityContext.seccompProfile}'
# Verify Falco detects events
kubectl exec test-pod -- cat /etc/shadow
journalctl -u falco | tail -5
Exam Day Checklist
1 Hour Before
- Close all unnecessary applications
- Clear your desk completely
- Test webcam and microphone
- Have your ID ready
- Water in a clear container (if needed)
- Use the bathroom
- Disable all notifications (system, phone, messaging)
5 Minutes Before
- Log into the PSI exam portal
- Complete proctor check-in (ID, room scan)
- Verify browser is Google Chrome / Chromium
- Deep breath — you’ve prepared for this
First 60 Seconds of Exam
# Set up your environment immediately
alias k=kubectl
export do="--dry-run=client -o yaml"
export now="--force --grace-period=0"
# Quick scan of all questions (note easy ones)
# Switch to the first question's context
kubectl config use-context <context-name>
Key Bookmarks to Prepare
Prepare browser bookmarks for these specific pages before exam day:
| Bookmark | URL Path | Why |
|---|---|---|
| NetworkPolicy spec | kubernetes.io/docs → NetworkPolicy | Copy YAML structure for ingress/egress rules |
| Pod SecurityContext | kubernetes.io/docs → Security Context | Reference all security fields |
| Audit Policy | kubernetes.io/docs → Auditing | Audit levels and policy YAML |
| Pod Security Standards | kubernetes.io/docs → Pod Security Standards | Three levels reference |
| PSA labels | kubernetes.io/docs → Pod Security Admission | Namespace label syntax |
| Encryption at rest | kubernetes.io/docs → Encrypting Secret Data | EncryptionConfiguration YAML |
| Falco rules | falco.org/docs → Rules | Rule syntax and macros |
| AppArmor with K8s | kubernetes.io/docs → AppArmor | Profile annotation/securityContext syntax |
| Trivy CLI | aquasecurity.github.io/trivy → CLI | Command-line flags and options |
| Seccomp | kubernetes.io/docs → Seccomp | Profile types and Pod spec syntax |
Pro tip: Organize bookmarks in a “CKS Exam” folder in your browser. During the exam, you’ll need to find specific YAML snippets quickly — 10 seconds of bookmark navigation vs 2 minutes of searching the docs.
Practice Questions
Q1: You have 120 minutes for 18 CKS questions. Using the 3-pass strategy, how would you allocate time?
Show Answer
| Pass | Time | Target |
|---|---|---|
| Pass 1 (Quick wins) | 10–15 min | 3–5 easy questions (<2 min each) |
| Pass 2 (Medium tasks) | 60–70 min | 7–10 medium questions (5–8 min each) |
| Pass 3 (Hard tasks) | 25–35 min | Remaining 3–5 hard questions + review |
Average ~6.7 min per question. Quick wins in Pass 1 build confidence and secure easy points before tackling complex tasks.
Q2: What is the correct order of operations when applying an AppArmor profile to a Pod?
Show Answer
- Write the AppArmor profile (e.g.,
/etc/apparmor.d/my-profile) - Load the profile on the target node:
apparmor_parser -q /etc/apparmor.d/my-profile - Verify the profile is loaded:
aa-status | grep my-profile - Create the Pod with the AppArmor reference in the spec
- Verify the Pod is running and the profile is enforced
Loading the profile before creating the Pod is critical. If the profile isn’t loaded, the Pod will fail to start.
Q3: Why should you run :set paste in vim before pasting YAML from the browser?
Show Answer
Without :set paste, vim auto-indents each pasted line based on the previous line’s indentation. For multi-line YAML, this causes cascading indentation errors — each line gets indented further than the last, destroying the YAML structure.
:set paste disables auto-indentation temporarily, preserving the exact formatting of the pasted content. After pasting, run :set nopaste to re-enable normal vim behavior.
Q4: A question asks you to “restrict egress traffic from Pods in namespace backend to only allow DNS and connections to namespace database.” Which NetworkPolicy direction do you configure?
Show Answer
Egress. The question says “restrict egress traffic from Pods” — this means controlling traffic leaving the backend Pods.
You would create a NetworkPolicy with:
podSelector: {}(selects all Pods inbackend)policyTypes: [Egress]egressrules allowing:- DNS: port 53 (TCP and UDP) to kube-dns
- Database: namespaceSelector matching
databasenamespace
A common trap is confusing this with ingress. Egress = traffic from the selected Pods. Ingress = traffic to the selected Pods.
Q5: After editing /etc/kubernetes/manifests/kube-apiserver.yaml, what should you do next?
Show Answer
Wait for the static Pod to restart automatically and verify it comes back. The kubelet monitors /etc/kubernetes/manifests/ and automatically restarts static Pods when their manifests change.
Verification steps:
# Watch for the API server to come back
crictl ps | grep kube-apiserver
# Or check with kubectl (may take 30-60 seconds)
kubectl get pods -n kube-system | grep apiserver
# If it doesn't come back, check the YAML for errors
cat /etc/kubernetes/manifests/kube-apiserver.yaml | python3 -c "import yaml,sys; yaml.safe_load(sys.stdin)"
If the YAML is invalid, the API server won’t start and kubectl will stop working. Always validate YAML before saving.
Next: Test your knowledge with Practice Questions →