CKS — Exam Setup & Speed Tips

10 minute read

First 2 Minutes: Terminal Setup

The moment the exam starts, before reading any question, run this setup in your terminal. It will save you 10+ minutes over the 2-hour exam.

Essential Aliases and Exports

Run these commands immediately:

alias k=kubectl
alias kn='kubectl config set-context --current --namespace'
export do="--dry-run=client -o yaml"
export now="--force --grace-period=0"

What Each One Does

Alias/Export Purpose Example
k Short for kubectl k get pods instead of kubectl get pods
kn Switch namespace quickly kn secure instead of kubectl config set-context --current --namespace secure
$do Generate YAML without creating k run nginx --image=nginx $do > pod.yaml
$now Force-delete pods instantly k delete pod nginx $now

kubectl Autocomplete

Enable tab completion for kubectl and the k alias:

source <(kubectl completion bash)
complete -o default -F __start_kubectl k

After this, you can type k get pod<TAB> and it auto-completes to k get pods. You can also tab-complete resource names: k describe pod ng<TAB> completes to k describe pod nginx.

Important: If you switch to a new terminal or SSH into a node, you must re-run all aliases and completion commands. They do not persist across sessions in the exam environment.


Vim Configuration

Create your ~/.vimrc at the start of the exam:

cat << 'EOF' > ~/.vimrc
set tabstop=2
set shiftwidth=2
set expandtab
set number
EOF

What Each Setting Does

Setting Purpose
tabstop=2 Tab key displays as 2 spaces (YAML standard)
shiftwidth=2 Indentation uses 2 spaces (for >> and << commands)
expandtab Converts tabs to spaces (YAML does not allow literal tabs)
number Shows line numbers (helps when debugging YAML errors)

Essential Vim Commands for the Exam

Command Action
i Enter insert mode
Esc Exit insert mode
dd Delete current line
5dd Delete 5 lines
yy Copy (yank) current line
5yy Copy 5 lines
p Paste below current line
u Undo last change
Ctrl+r Redo
:set paste Enable paste mode (preserves indentation when pasting)
:set nopaste Disable paste mode
/searchterm Search forward for “searchterm”
n Jump to next search match
N Jump to previous search match
:%s/old/new/g Replace all occurrences of “old” with “new”
:wq Save and quit
:q! Quit without saving
gg Go to first line
G Go to last line
:42 Go to line 42
v Enter visual mode (for selecting text)
V Enter visual line mode (select entire lines)
> Indent selected text (in visual mode)
< Unindent selected text (in visual mode)

Pro tip: When pasting YAML from the docs, always enter :set paste mode first. Otherwise, vim auto-indentation will corrupt your YAML structure. After pasting, run :set nopaste.


Must-Know Security Aliases

Beyond the basic aliases, these security-specific shortcuts save significant time on CKS questions:

# Quick context check (run before EVERY question)
alias kctx='kubectl config get-contexts'
alias kns='kubectl config view --minify --output jsonpath="{..namespace}"'

# Security-focused shortcuts
alias kgp='kubectl get pods'
alias kgpa='kubectl get pods --all-namespaces'
alias kgsa='kubectl get serviceaccounts'
alias kgnp='kubectl get networkpolicies'
alias kgsec='kubectl get secrets'
alias kdp='kubectl describe pod'
alias kaf='kubectl apply -f'

# Quick Pod creation with security context
alias krun='kubectl run --image=nginx --dry-run=client -o yaml'

Security Shortcuts Reference Table

Task Fast Command
Check current context k config current-context
Switch context k config use-context <name>
Check current namespace k config view --minify -o jsonpath='{..namespace}'
Switch namespace kn <namespace>
Generate Pod YAML k run test --image=nginx $do > pod.yaml
Generate Role YAML k create role myrole --verb=get,list --resource=pods $do
Generate RoleBinding YAML k create rolebinding mybinding --role=myrole --serviceaccount=ns:sa $do
Generate ClusterRole YAML k create clusterrole myrole --verb=get,list --resource=pods $do
Generate NetworkPolicy Copy from kubernetes.io docs — no imperative command exists
Force delete a pod k delete pod <name> $now
Check API server flags cat /etc/kubernetes/manifests/kube-apiserver.yaml
Check kubelet config cat /var/lib/kubelet/config.yaml
SSH to a node ssh <node-name>
Check AppArmor profiles aa-status (on the node)
Check Seccomp profiles ls /var/lib/kubelet/seccomp/

Key Bookmarks to Prepare

Before exam day, familiarize yourself with these documentation pages. During the exam, you can navigate to them from the allowed sites. Knowing exactly where to find each resource saves 2–3 minutes per question.

Kubernetes Official Docs

Topic URL Path
NetworkPolicy kubernetes.io/docs/concepts/services-networking/network-policies/
Audit Policy kubernetes.io/docs/tasks/debug/debug-cluster/audit/
AppArmor kubernetes.io/docs/tutorials/security/apparmor/
Seccomp kubernetes.io/docs/tutorials/security/seccomp/
Pod Security Admission kubernetes.io/docs/concepts/security/pod-security-admission/
Pod Security Standards kubernetes.io/docs/concepts/security/pod-security-standards/
RBAC kubernetes.io/docs/reference/access-authn-authz/rbac/
Encryption at Rest kubernetes.io/docs/tasks/administer-cluster/encrypt-data/
Service Accounts kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/
Security Context kubernetes.io/docs/tasks/configure-pod-container/security-context/
Admission Controllers kubernetes.io/docs/reference/access-authn-authz/admission-controllers/

External Tool Docs (Allowed in Exam)

Tool URL
Falco falco.org/docs/rules/
Trivy aquasecurity.github.io/trivy/
AppArmor (upstream) gitlab.com/apparmor/apparmor/-/wikis/

Practice this: Before the exam, navigate to each of these pages at least 3 times. Know the page layout so you can find the relevant YAML example in under 30 seconds.


kubectl Cheat Sheet for Security Tasks

This table covers the most common kubectl operations you will need during the CKS exam:

Cluster & Context

Command Purpose
k config get-contexts List all available contexts
k config use-context <ctx> Switch to a specific context
k config current-context Show current context
k config set-context --current --namespace=<ns> Set default namespace
k cluster-info Show cluster endpoint info
k get nodes List all nodes
k get nodes -o wide List nodes with IPs and OS info

RBAC

Command Purpose
k create role <name> --verb=get,list --resource=pods -n <ns> Create a Role
k create rolebinding <name> --role=<role> --user=<user> -n <ns> Create a RoleBinding
k create clusterrole <name> --verb=get,list --resource=pods Create a ClusterRole
k create clusterrolebinding <name> --clusterrole=<role> --user=<user> Create a ClusterRoleBinding
k auth can-i get pods --as=<user> -n <ns> Test permissions
k auth can-i --list --as=<user> -n <ns> List all permissions for a user

Pods & Security

Command Purpose
k run test --image=nginx $do > pod.yaml Generate Pod YAML
k exec -it <pod> -- /bin/sh Exec into a pod
k exec <pod> -- cat /run/secrets/kubernetes.io/serviceaccount/token Check SA token mount
k get pod <pod> -o jsonpath='{.spec.securityContext}' Check Pod security context
k get pod <pod> -o jsonpath='{.spec.containers[0].securityContext}' Check container security context
k label ns <ns> pod-security.kubernetes.io/enforce=restricted Apply PSA label

Secrets & Encryption

Command Purpose
k create secret generic <name> --from-literal=key=value -n <ns> Create a Secret
k get secret <name> -o jsonpath='{.data.key}' \| base64 -d Decode a Secret value
ETCDCTL_API=3 etcdctl get /registry/secrets/<ns>/<name> --cert ... --key ... --cacert ... Read Secret directly from etcd

Network & Policies

Command Purpose
k get networkpolicies -n <ns> List NetworkPolicies
k describe networkpolicy <name> -n <ns> Describe a NetworkPolicy
k exec <pod> -- wget -qO- --timeout=2 <target> Test network connectivity
k exec <pod> -- nslookup <service> Test DNS resolution

API Server & Static Pods

Command Purpose
cat /etc/kubernetes/manifests/kube-apiserver.yaml View API server config
cat /etc/kubernetes/manifests/etcd.yaml View etcd config
cat /var/lib/kubelet/config.yaml View kubelet config
systemctl restart kubelet Restart kubelet
crictl ps List running containers (containerd)
crictl logs <container-id> View container logs

Speed Techniques for YAML Editing

Technique 1: Generate, Don’t Write From Scratch

Never write YAML from memory. Always generate a base and modify it:

# Generate a Pod spec
k run secure-pod --image=nginx $do > pod.yaml

# Generate a Role
k create role pod-reader --verb=get,list --resource=pods $do > role.yaml

# Generate a RoleBinding
k create rolebinding pod-reader-binding --role=pod-reader \
  --serviceaccount=default:mysa $do > rb.yaml

Technique 2: Copy From Docs, Modify in vim

For resources without imperative generation (like NetworkPolicy):

  1. Open the Kubernetes docs page for NetworkPolicy
  2. Find the closest example to what you need
  3. Copy the YAML
  4. In terminal: vi np.yaml
  5. Type :set paste, press i, paste, press Esc, type :set nopaste
  6. Modify the fields you need (namespace, labels, ports)
  7. Save with :wq and apply with k apply -f np.yaml

Technique 3: Use kubectl edit for Quick Fixes

If a resource already exists and needs a small change:

k edit pod <pod-name>
# or
k edit deployment <deploy-name>

This opens the live resource in vim. Make your change, save, and it is applied immediately.

Technique 4: Redirect and Append

# Create a base file
k run pod1 --image=nginx $do > pod.yaml

# View the API server manifest and search for a flag
grep -i "enable-admission" /etc/kubernetes/manifests/kube-apiserver.yaml

# Append to an existing file
echo "---" >> combined.yaml
k create role viewer --verb=get --resource=pods $do >> combined.yaml

Technique 5: Use grep to Find Things Fast

# Find which node has an AppArmor profile loaded
ssh node01 'aa-status | grep my-profile'

# Find a specific flag in API server config
grep -i "audit" /etc/kubernetes/manifests/kube-apiserver.yaml

# Find Falco rules mentioning a specific syscall
grep -r "spawned_process" /etc/falco/

Exam Environment Gotchas

You Lose Aliases When You SSH

When you ssh node01 to work on a node (for AppArmor, Seccomp, etc.), your aliases are gone. Re-set them if needed:

ssh node01
alias k=kubectl  # if you need kubectl on the node

Static Pod Changes Need Kubelet Restart (Sometimes)

After modifying /etc/kubernetes/manifests/kube-apiserver.yaml, the kubelet watches this directory and automatically restarts the API server. However:

  • It can take 30–60 seconds for the restart
  • If you made a YAML error, the API server will crash-loop
  • Monitor with: crictl ps | grep apiserver or watch crictl ps
  • If the API server does not come back, check your YAML: cat /etc/kubernetes/manifests/kube-apiserver.yaml | python3 -c "import sys,yaml;yaml.safe_load(sys.stdin.read())" (validates YAML syntax)

Copy-Paste Behavior

  • Copy: select text in terminal, it auto-copies (or use Ctrl+Shift+C)
  • Paste: Ctrl+Shift+V in terminal
  • In vim: :set paste before pasting, :set nopaste after

Practice Questions

Question 1: Write the exact commands you would run in the first 2 minutes of the CKS exam to set up your environment.
# Aliases
alias k=kubectl
alias kn='kubectl config set-context --current --namespace'
export do="--dry-run=client -o yaml"
export now="--force --grace-period=0"

# Autocomplete
source <(kubectl completion bash)
complete -o default -F __start_kubectl k

# Vim config
cat << 'EOF' > ~/.vimrc
set tabstop=2
set shiftwidth=2
set expandtab
set number
EOF

This should take under 60 seconds if you have it memorized. Practice typing this from memory until it becomes muscle memory.

Question 2: During the exam, you need to create a NetworkPolicy. No imperative `kubectl create networkpolicy` command exists. What is the fastest approach?
  1. Open the allowed documentation: kubernetes.io/docs/concepts/services-networking/network-policies/
  2. Find the example closest to what you need
  3. Copy the YAML example
  4. In the terminal:
    vi np.yaml
    
  5. In vim:
    • Type :set paste and press Enter
    • Press i to enter insert mode
    • Paste with Ctrl+Shift+V
    • Press Esc
    • Type :set nopaste and press Enter
    • Modify the namespace, labels, ports as needed
    • Type :wq to save and quit
  6. Apply: k apply -f np.yaml
  7. Verify: k get networkpolicy -n <namespace>

This should take 2–3 minutes total with practice.

Question 3: You SSH into a worker node to load an AppArmor profile. After loading it, you try to run `k get pods` but get "command not found". Why? How do you fix it?

Your aliases (alias k=kubectl) are set in the control plane terminal session. When you SSH into a worker node, you start a new shell session where those aliases do not exist.

Fix:

# Option 1: Use the full command
kubectl get pods

# Option 2: Re-set the alias on the node
alias k=kubectl

# Option 3: Exit back to the control plane
exit
k get pods

In most cases, you do not need kubectl on the worker node. You SSH to the node only to:

  • Load AppArmor profiles (apparmor_parser -r /etc/apparmor.d/profile)
  • Place Seccomp profiles (copy JSON to /var/lib/kubelet/seccomp/)
  • Check node-level configuration
  • Harden SSH or other services

After completing node-level tasks, exit back to the control plane to create/modify Kubernetes resources.

Question 4: You modify `/etc/kubernetes/manifests/kube-apiserver.yaml` to add an audit policy flag, but the API server does not come back. How do you debug this?

Step-by-step debugging:

# 1. Check if the API server container is running
crictl ps | grep apiserver

# 2. If it shows restarting/crash-looping, check the logs
crictl logs $(crictl ps -a | grep apiserver | head -1 | awk '{print $1}')

# 3. Validate your YAML syntax
python3 -c "import yaml; yaml.safe_load(open('/etc/kubernetes/manifests/kube-apiserver.yaml'))"

# 4. Common mistakes to check:
# - Did you mount the audit policy file as a volume?
# - Is the volume mount path correct?
# - Does the audit policy file exist at the mounted host path?
# - Did you introduce a YAML indentation error?

# 5. If you cannot fix it, restore the original
# (Hopefully you made a backup before editing)
cp /etc/kubernetes/manifests/kube-apiserver.yaml.bak \
   /etc/kubernetes/manifests/kube-apiserver.yaml

Pro tip: Always back up the API server manifest before editing:

cp /etc/kubernetes/manifests/kube-apiserver.yaml \
   /etc/kubernetes/manifests/kube-apiserver.yaml.bak
Question 5: You need to verify the integrity of the kubectl binary on a node. Write the exact commands.
# 1. Check the current kubectl version
kubectl version --client --short

# 2. Download the checksum for that version from kubernetes.io
# Example for v1.29.0:
curl -LO "https://dl.k8s.io/v1.29.0/bin/linux/amd64/kubectl.sha256"

# 3. Generate the sha256sum of the installed binary
sha256sum $(which kubectl)

# 4. Compare the checksums
echo "$(cat kubectl.sha256)  $(which kubectl)" | sha256sum --check

# If the output says "OK", the binary is verified.
# If it says "FAILED", the binary has been tampered with.

On the exam, the question may provide the expected hash or ask you to download it from a specific URL. Always check which version is installed first.

Alternative using sha512:

sha512sum $(which kubectl)
# Compare with the expected sha512 hash provided in the question

Updated: