CNCF / Kubernetes Security

Certified Kubernetes Security Specialist (CKS)

The CKS is the most advanced Kubernetes certification from CNCF — it requires a valid CKA to attempt and tests your ability to secure Kubernetes clusters in depth. This course covers all six CKS exam domains: cluster setup and hardening, system-level Linux security controls, minimizing microservice vulnerabilities, securing the software supply chain, and implementing runtime threat detection with Falco and Kubernetes audit logging.

Advanced 7 modules ~40 hours 60 practice questions Requires CKA

Jump straight into practice questions

60 scenario-based CKS questions covering every exam domain — free, no signup required.

CKS Exam Snapshot

FormatPerformance-based
Duration2 hours
Questions15–20 tasks
Passing score67%
PrerequisiteActive CKA
Validity2 years

Exam Domain Weights

Cluster Setup10%
Cluster Hardening15%
System Hardening15%
Minimize Microservice Vulnerabilities20%
Supply Chain Security20%
Monitoring, Logging & Runtime Security20%

Key Concept: Defense in Depth

The CKS is organized around layered security: cluster-level controls (NetworkPolicy, RBAC, API server flags) + node-level controls (AppArmor, seccomp, kernel modules) + workload-level controls (SecurityContext, Pod Security Admission) + runtime detection (Falco, audit logs). No single layer is sufficient — the exam tests whether you can apply all layers together.

🎧

Learn Kubernetes security on the go

Tune in to Falco deep dives, supply chain security walkthroughs, and CKS exam strategy discussions. New episodes every week — perfect for commutes and gym sessions.

Listen on Spotify

Course Modules

01
CKS Overview & Kubernetes Security Architecture
2 lessons · ~4 hours
The CKS Exam: What You Need to Know

CKS vs CKA vs CKAD

  • CKA — cluster administration, must pass before attempting CKS
  • CKAD — application development and deployment on Kubernetes
  • CKS — security specialist, builds directly on CKA knowledge, hardest of the three
  • CKS is performance-based: you work in a live cluster via browser terminal, no multiple choice
  • You can use official Kubernetes docs (kubernetes.io) and some tool docs during the exam

Kubernetes Security Model Overview

  • Authentication — who are you? (certificates, tokens, OIDC)
  • Authorization — what can you do? (RBAC, Node authorization)
  • Admission Control — is this request valid? (PodSecurity, OPA Gatekeeper, webhooks)
  • Network Policies — what can this Pod communicate with?
  • SecurityContext — how is this container isolated from the host?
  • Runtime Security — what is happening at runtime? (Falco, audit logs)
The CKS exam is 2 hours for ~15–20 hands-on tasks. Speed matters. Practice all kubectl commands until they are muscle memory. The killer CKS tasks are Falco rules, audit policy, NetworkPolicy, and RBAC — expect at least one of each.
The CKS performance-based exam tests your ability to apply controls under time pressure, not just know them. Every concept in this course should be practiced hands-on in a cluster before exam day. Use killer.sh (included with your CKS voucher) for realistic mock exams.
Kubernetes Attack Surface & Threat Model

Common Attack Vectors in Kubernetes

  • Compromised container — exploit an app vulnerability, then escape to the host via privileged container, hostPath mount, or container runtime CVE
  • Stolen service account token — use the default SA token to call the Kubernetes API and enumerate/exfiltrate resources
  • SSRF to metadata endpoint — use server-side request forgery in an app to reach 169.254.169.254 and steal cloud credentials
  • Malicious container image — supply chain attack via compromised public image or CI pipeline
  • Overly permissive RBAC — SA with cluster-admin access lets an attacker control the whole cluster

CKS Security Controls mapped to Threats

  • Container escape → SecurityContext, AppArmor, seccomp, non-root, readOnlyRootFilesystem
  • SA token abuse → disable automount, time-limited tokens, RBAC minimum privilege
  • Metadata SSRF → NetworkPolicy egress to 169.254.169.254
  • Supply chain → Trivy scanning, Cosign signing, OPA registry policy, distroless images
  • Runtime threats → Falco, audit logs, immutable infrastructure
The CKS exam doesn't present abstract questions — it gives you a scenario ("Pod X is running privileged, fix it with minimum change") and you apply the correct control. Always ask: what is the specific attack vector and what is the least-privilege control to address it?
02
Cluster Setup: Network Policies, TLS & API Hardening
3 lessons · ~6 hours
NetworkPolicy Deep Dive

NetworkPolicy Fundamentals

  • NetworkPolicy is namespaced — it only affects Pods in its own namespace
  • Default behavior: all ingress and egress is allowed if no NetworkPolicy selects the Pod
  • Once a NetworkPolicy selects a Pod, only explicitly allowed traffic is permitted
  • Requires a CNI plugin that enforces NetworkPolicy (Calico, Cilium, Weave) — kubectl apply of the policy has no effect with a non-enforcing CNI (e.g., Flannel)

Common NetworkPolicy Patterns

  • Default deny all ingress: spec: podSelector: {} policyTypes: [Ingress] — empty ingress rules = deny all
  • Restrict ingress to same namespace: use namespaceSelector: {matchLabels: {kubernetes.io/metadata.name: <ns>}}
  • Restrict egress to DNS + specific IPs: allow port 53 UDP/TCP + allow specific CIDRs
  • Block access to cloud metadata: egress deny ipBlock: cidr: 169.254.169.254/32

Example: Full Isolation Policy

  • policyTypes: [Ingress, Egress] with both sections empty → complete isolation
  • Allows adding targeted exceptions without global deny rules conflicting
  • For DNS access, always add: egress to port 53 UDP/TCP or pods will lose name resolution
On the CKS exam, NetworkPolicy tasks often involve fixing an existing policy that allows too much. Read the existing policy carefully before modifying — do not accidentally block DNS (port 53) or other required traffic. Test with kubectl exec <pod> -- curl <target> after applying.
CIS Kubernetes Benchmark & kube-bench

What the CIS Benchmark Covers

  • 1.x — kube-apiserver flags: authorization mode, admission plugins, TLS settings, audit logging
  • 2.x — etcd: certificate authentication, data encryption at rest
  • 3.x — Control Plane Configuration: controller manager, scheduler flags
  • 4.x — Worker Node: kubelet config, anonymous auth, read-only port
  • 5.x — Kubernetes Policies: RBAC, pod security, secrets, network policies

kube-bench Usage

  • Run all checks: kube-bench run --targets master,node,etcd
  • Run specific check: kube-bench run --check 1.2.6
  • Output JSON: kube-bench run --json > results.json
  • Most CKS exam remediations involve editing /etc/kubernetes/manifests/kube-apiserver.yaml

Key API Server Security Flags

  • --anonymous-auth=false — reject unauthenticated requests
  • --authorization-mode=Node,RBAC — remove AlwaysAllow
  • --enable-admission-plugins=NodeRestriction,PodSecurity
  • --audit-log-path=/var/log/audit.log
  • --audit-policy-file=/etc/kubernetes/audit-policy.yaml
After editing /etc/kubernetes/manifests/kube-apiserver.yaml, the kubelet automatically restarts the API server as a static Pod. Wait 30–60 seconds and verify with kubectl get pods -n kube-system. If the API server doesn't restart, check crictl ps -a and crictl logs <id> for errors in the manifest.
kube-bench reports PASS/FAIL/WARN. CKS tasks often say "fix CIS check 1.2.X". Know that most apiserver fixes are in /etc/kubernetes/manifests/kube-apiserver.yaml, kubelet fixes are in /var/lib/kubelet/config.yaml or /etc/kubernetes/kubelet.conf.
Ingress TLS & API Server Certificate Configuration

Ingress TLS Termination

  • Create a TLS Secret: kubectl create secret tls myapp-tls --cert=tls.crt --key=tls.key -n myapp
  • Reference in Ingress: add spec.tls[].secretName: myapp-tls with hosts matching the cert SAN
  • Secret type must be kubernetes.io/tls with keys tls.crt and tls.key

Adding SANs to the API Server Certificate (kubeadm)

  • Edit kubeadm config: add apiServer.certSANs with the new hostname or IP
  • Delete existing certs: rm /etc/kubernetes/pki/apiserver.{crt,key}
  • Regenerate: kubeadm init phase certs apiserver --config kubeadm.yaml
  • Restart API server: delete the static Pod or wait for kubelet to pick up the cert change
CKS exam TLS tasks often involve verifying a certificate's SAN with openssl x509 -in /etc/kubernetes/pki/apiserver.crt -text -noout | grep -A1 "Subject Alternative". Know how to read openssl output.
03
Cluster Hardening: RBAC, Service Accounts & Upgrades
3 lessons · ~6 hours
RBAC Minimum Privilege

Role vs ClusterRole, RoleBinding vs ClusterRoleBinding

  • Role — namespaced; grants permissions on resources in one namespace
  • ClusterRole — cluster-scoped; can be bound namespace-specifically via RoleBinding or globally via ClusterRoleBinding
  • RoleBinding — grants a Role or ClusterRole within a single namespace
  • ClusterRoleBinding — grants a ClusterRole across all namespaces

Least Privilege Pattern

  • Always use the most namespace-restricted binding possible
  • Only grant the minimum verbs needed: avoid * verbs or * resources
  • Avoid granting secrets read access unless strictly required
  • Dangerous verbs: escalate, bind, impersonate, create on ClusterRoleBindings
  • The cluster-admin ClusterRole has * on * — should never be used for service accounts

Useful RBAC Commands

  • Check what a SA can do: kubectl auth can-i list pods --as=system:serviceaccount:<ns>:<sa>
  • See all permissions: kubectl auth can-i --list --as=system:serviceaccount:<ns>:<sa>
  • Create a Role quickly: kubectl create role pod-reader --verb=get,list --resource=pods -n dev
  • Bind it: kubectl create rolebinding pod-reader-binding --role=pod-reader --serviceaccount=dev:myapp -n dev
CKS RBAC tasks often involve auditing an existing role for excessive permissions and restricting it. Use kubectl auth can-i --list to see what permissions an identity currently has before and after your fix.
Service Account Security

Disable Automatic Token Mounting

  • Default: every Pod gets a projected SA token at /var/run/secrets/kubernetes.io/serviceaccount/token
  • For Pods that don't need API access, disable: automountServiceAccountToken: false in the Pod spec
  • Or disable on the ServiceAccount object to apply to all Pods using it
  • Pod-level setting overrides SA-level setting — use Pod-level for surgical targeting

TokenRequest API & Projected Tokens

  • Legacy SA tokens (stored in Secrets): never expire, single audience, exist indefinitely
  • Projected tokens (TokenRequest API): bounded expiry (expirationSeconds), specific audience, tied to Pod lifetime
  • Default projected token expiry: 1 hour (kubelet refreshes before expiry)
  • Verify: kubectl exec <pod> -- cat /run/secrets/kubernetes.io/serviceaccount/token | cut -d. -f2 | base64 -d | jq .exp

NodeRestriction Admission Controller

  • Enabled by default in kubeadm clusters
  • Limits kubelet to: (1) only modify its own Node object, (2) only modify Pods assigned to it
  • Prevents a compromised node from modifying other nodes or other nodes' pods
  • Does NOT limit what a container can do — that's SecurityContext/AppArmor/seccomp
The most impactful SA hardening is disabling automount for Pods that don't need API access. In a real cluster, the vast majority of application Pods don't call the Kubernetes API — they just process business logic. Disabling the token eliminates the risk of SA token theft via container exploit.
Kubernetes Upgrade Security

Why Upgrades Are a Security Practice

  • Kubernetes releases patch CVEs in minor version updates — staying current is a security requirement
  • CVE examples patched by upgrades: kubelet privilege escalation, etcd information disclosure, API server SSRF
  • CKS exam expects you to know the correct upgrade order: control plane → worker nodes

Upgrade Process Review (kubeadm)

  • Check available versions: apt-cache madison kubeadm
  • Upgrade kubeadm: apt-mark unhold kubeadm && apt-get install -y kubeadm=1.30.0-00 && apt-mark hold kubeadm
  • Apply upgrade: kubeadm upgrade apply v1.30.0
  • Drain node: kubectl drain <node> --ignore-daemonsets --delete-emptydir-data
  • Upgrade kubelet/kubectl: apt-get install -y kubelet=1.30.0-00 kubectl=1.30.0-00
  • Restart: systemctl daemon-reload && systemctl restart kubelet
  • Uncordon: kubectl uncordon <node>
One minor version at a time — never skip a version (1.28 → 1.29, not 1.28 → 1.30). Worker node versions must be ≤ control plane version. The exam may present a cluster that needs a specific patch-level upgrade for a security fix.
04
System Hardening: AppArmor, Seccomp & Linux Capabilities
3 lessons · ~6 hours
AppArmor for Containers

AppArmor Concepts

  • AppArmor (Application Armor) — Linux security module that restricts what a process can do using profiles
  • Profile modes: enforce (block violations), complain (log violations only), disabled
  • Profiles are loaded on the node, not stored in Kubernetes objects (except referenced by name)
  • Check loaded profiles: cat /sys/kernel/security/apparmor/profiles
  • Load a profile: apparmor_parser -q /etc/apparmor.d/my-profile

Applying AppArmor to a Container (Kubernetes 1.30+)

  • In the container securityContext: appArmorProfile.type: Localhost and appArmorProfile.localhostProfile: <profile-name>
  • Legacy (pre-1.30): annotation container.apparmor.security.beta.kubernetes.io/<container-name>: localhost/<profile-name>
  • Types: RuntimeDefault (container runtime's default), Localhost (specific loaded profile), Unconfined (disabled)
AppArmor profiles must be loaded on EVERY node where the Pod might schedule. If a profile is missing on a node, the Pod will fail to start with "failed to create containerd container: apply apparmor profile". Use a DaemonSet or node provisioning tool to distribute profiles in production.
Seccomp Profiles

Seccomp Concepts

  • Seccomp (Secure Computing Mode) — Linux kernel feature that filters which syscalls a process can make
  • Restricts the attack surface: even if an attacker has code execution, blocked syscalls can't be used
  • RuntimeDefault — the container runtime's default seccomp profile (recommended for most workloads)
  • Localhost — a custom profile file on the node at the seccomp profile path
  • Unconfined — no seccomp filtering (default before Kubernetes 1.27 if not set)

Configuring Seccomp in Kubernetes

  • Pod level: spec.securityContext.seccompProfile.type: RuntimeDefault
  • Container level: spec.containers[].securityContext.seccompProfile.type: RuntimeDefault
  • Custom profile: place JSON file on node, reference with type: Localhost and localhostProfile: profiles/my-profile.json
  • Default seccomp profile path: /var/lib/kubelet/seccomp/

CIS Benchmark Seccomp Requirement

  • CIS 5.7.2: Ensure that the seccomp profile is set to docker/default or runtime/default
  • In Kubernetes 1.27+, the default profile is Unconfined unless set — always explicitly configure
  • Setting RuntimeDefault at the Pod level applies to all containers in the Pod
The CKS exam often presents a Pod with no seccomp profile set and asks you to add the RuntimeDefault. Know the exact YAML path: spec.securityContext.seccompProfile.type: RuntimeDefault — this is a common one-line fix task.
Linux Capabilities & Node OS Hardening

Linux Capabilities Minimum Set

  • Default container capabilities: a subset of the full Linux capability set (about 14 capabilities)
  • capabilities.drop: ["ALL"] — remove every capability from the container
  • capabilities.add: ["NET_BIND_SERVICE"] — add back only what is needed
  • Common capabilities to be aware of: NET_ADMIN (network config), SYS_PTRACE (process tracing), SYS_ADMIN (broad host access — almost as dangerous as privileged)
  • CIS Benchmark: do not add SYS_ADMIN, NET_ADMIN, or SYS_PTRACE unless absolutely required

Other SecurityContext Hardening Settings

  • allowPrivilegeEscalation: false — sets no_new_privs bit; prevents setuid/setgid escalation
  • readOnlyRootFilesystem: true — makes the root filesystem immutable
  • runAsNonRoot: true — prevents running as UID 0
  • runAsUser: 1000 — explicit UID for the container process
  • privileged: false (always) — never set privileged: true in production

OS-Level Node Hardening

  • Blacklist unused kernel modules: echo "blacklist dccp" >> /etc/modprobe.d/kubernetes.conf
  • Modules to consider blacklisting: dccp, sctp, rds, tipc — rarely needed, exploit potential
  • User namespaces: spec.hostUsers: false maps container UIDs to unprivileged host UIDs
  • Verify with: cat /proc/sys/kernel/unprivileged_userns_clone
The CKS exam often has a combined SecurityContext task: add seccomp RuntimeDefault + drop ALL capabilities + set allowPrivilegeEscalation=false + runAsNonRoot=true all at once. Know how to write these in a single clean securityContext block without looking up the syntax.
05
Minimize Microservice Vulnerabilities: SecurityContext, OPA & Secrets
3 lessons · ~6 hours
Pod Security Admission & Standards

The Three Pod Security Standards

  • Privileged — unrestricted (for cluster infrastructure, system components)
  • Baseline — prevents known privilege escalation: no privileged, no hostPath, no hostPID/hostNetwork, limited capabilities
  • Restricted — heavily hardened: all of Baseline + must drop ALL caps, must run as non-root, must have allowPrivilegeEscalation=false, seccomp required

Applying Pod Security Admission

  • Label namespace: kubectl label ns production pod-security.kubernetes.io/enforce=restricted
  • Three modes: enforce (reject), warn (allow + warn), audit (allow + log)
  • Version pin: pod-security.kubernetes.io/enforce-version: v1.30
  • Safe rollout order: audit first → check logs → warn → fix workloads → enforce

OPA Gatekeeper for Custom Policies

  • Pod Security Admission is built-in but covers only pod security — OPA handles custom org policies
  • Two CRDs: ConstraintTemplate (defines Rego logic) + Constraint (activates it)
  • Example policies: block non-approved registries, require specific labels, enforce naming conventions
  • Rego violation pattern: violation[{"msg": msg}] { ... }

PSA enforce vs warn vs audit

enforce rejects the API request — Pod is never created. warn allows the Pod but returns a warning header that CLIs display (useful for operator awareness). audit logs the violation to the audit log without user-visible feedback. Use all three simultaneously during migration: audit: restricted + warn: restricted + enforce: baseline.

Secrets Security: At Rest, In Transit & Access Patterns

Why Default Secrets Are Not Secure

  • Default: Secrets are stored as base64 in etcd — trivially decodable by anyone with etcd access
  • Environment variable exposure: visible in kubectl describe pod and /proc/<pid>/environ
  • Fix 1: volume-mount Secrets instead of env vars
  • Fix 2: enable encryption at rest with EncryptionConfiguration
  • Fix 3: use an external secrets manager (Vault Agent Injector, AWS Secrets Manager CSI)

Enabling Encryption at Rest

  • Create /etc/kubernetes/enc/encryption.yaml with provider aescbc or secretbox
  • Add flag to kube-apiserver: --encryption-provider-config=/etc/kubernetes/enc/encryption.yaml
  • Re-encrypt existing Secrets: kubectl get secrets -A -o json | kubectl replace -f -
  • Verify: check etcd directly — the stored value should start with k8s:enc:aescbc:v1:

RuntimeClass for Strong Isolation

  • gVisor (runsc): replaces the Linux kernel syscall interface with a Go-implemented sandbox
  • Kata Containers: runs each Pod in a lightweight VM with its own kernel
  • Create: kubectl create -f runtimeclass-gvisor.yaml with handler: runsc
  • Use: spec.runtimeClassName: gvisor in Pod spec
  • Verify: kubectl exec <pod> -- dmesg — gVisor shows different kernel info than host
For the CKS exam, know both the encryption-at-rest setup (EncryptionConfiguration YAML + apiserver flag) and the volume-mount-vs-env pattern. These are direct application tasks — no googling, just write the YAML.
Container Isolation: gVisor, Kata & Pod Security

Container Runtime Isolation Layers

  • Default runtime (containerd + runc): uses Linux namespaces and cgroups — shares the host kernel
  • gVisor (runsc): intercepts syscalls and handles them in userspace — kernel not directly exposed
  • Kata Containers: each Pod gets a micro-VM with a separate kernel — strongest isolation
  • RuntimeClass bridges the K8s scheduler to the correct low-level runtime handler on the node

Practical RuntimeClass Task

  • kubectl apply -f - <<'EOF' ... EOF to create the RuntimeClass quickly
  • Test: create a Pod with runtimeClassName: gvisor, exec in and run uname -r — shows gVisor kernel string
  • Admission webhook (OPA or Kyverno mutation) can auto-inject runtimeClassName for a namespace
On the CKS exam, you won't be asked to install gVisor — just to create the RuntimeClass and reference it. The runtime handler is already configured on the exam nodes. Your job is the Kubernetes configuration layer only.
06
Supply Chain Security: Scanning, Signing & Admission Control
3 lessons · ~6 hours
Image Scanning with Trivy

Trivy Core Commands

  • Scan a local image: trivy image nginx:1.25
  • Filter by severity: trivy image --severity HIGH,CRITICAL nginx:1.25
  • Fail on findings: trivy image --severity CRITICAL --exit-code 1 nginx:1.25
  • Scan cluster: trivy k8s --severity HIGH,CRITICAL --report all cluster
  • Generate SBOM: trivy image --format cyclonedx nginx:1.25
  • Scan IaC config: trivy config ./k8s-manifests/

Static Analysis with kubesec

  • Scan a manifest: kubesec scan pod.yaml
  • Returns a score and advisories for security risk settings in the YAML
  • Checks: privileged, hostPath, capabilities, runAsRoot, missing securityContext settings

Integrating in CI/CD

  • Best practice: scan before push (fail the build → image never enters registry)
  • Second layer: admission webhook to scan during pod admission
  • Third layer: periodic cluster scan with trivy k8s or Starboard operator
For CKS, know the Trivy command syntax cold — especially --exit-code 1 and --severity. You may be asked to scan a specific image and identify which CVE to report, or to run Trivy and interpret the output.
Image Signing with Cosign & Secure Images

Cosign Workflow

  • Generate a key pair: cosign generate-key-pair → produces cosign.key and cosign.pub
  • Sign an image: cosign sign --key cosign.key registry.example.com/myapp:v1.0
  • Verify signature: cosign verify --key cosign.pub registry.example.com/myapp:v1.0
  • Signatures are stored as OCI artifacts in the registry alongside the image

Distroless and Minimal Images

  • Use FROM scratch for fully static Go/Rust binaries — zero OS, zero attack surface
  • Use gcr.io/distroless/static or distroless/base for apps needing minimal OS support
  • No shell → attacker can't run bash -i even with code execution
  • No package manager → can't install tools post-compromise

Multi-Stage Dockerfile Best Practice

  • Stage 1 (builder): FROM golang:1.22 AS builder — compile the binary
  • Stage 2 (final): FROM gcr.io/distroless/static — copy only the binary
  • Final image contains: binary + minimal OS libraries — nothing else
Sigstore's Cosign is becoming the industry standard for image signing. In the CKS exam context, know how to run cosign verify and understand what --key you need (the public key to verify a signature). Signing uses the private key; verification uses the public key.
Admission Control for Supply Chain

ImagePolicyWebhook

  • A Kubernetes-built-in admission webhook type specifically for image policy
  • Enable with: --enable-admission-plugins=ImagePolicyWebhook on the API server
  • defaultAllow: false → fail-closed (safe default — deny when webhook is down)
  • defaultAllow: true → fail-open (unsafe — allows all images if webhook unreachable)

OPA Gatekeeper for Registry Policy

  • Create a ConstraintTemplate with Rego that checks image registry prefix
  • Create a Constraint object applying it to Pod kinds across all or specific namespaces
  • Test with: kubectl apply -f test-pod.yaml — should be rejected with your Gatekeeper message

Validating vs Mutating Webhooks

  • Validating: can reject a request (no modification)
  • Mutating: can modify the request (inject sidecars, add labels, set runtimeClassName)
  • Execution order: mutating webhooks run first, then validating webhooks
  • failurePolicy: Fail → webhook outage = request denied. Ignore → request proceeds
CKS supply chain tasks often ask you to create or modify an OPA ConstraintTemplate Rego policy. Know the Gatekeeper violation pattern: violation[{"msg": msg}] { ... } and the input path: input.review.object.spec.containers[_].image.
07
Runtime Security: Falco, Audit Logs & Behavioral Analysis
3 lessons · ~6 hours
Falco: Runtime Threat Detection

Falco Architecture

  • Falco — CNCF graduated project for runtime security; monitors kernel syscalls using eBPF or kernel module
  • Components: driver (eBPF probe or kernel module), rule engine (evaluates rules), output (stdout, file, gRPC, HTTP)
  • Falco reads syscall events: file opens, process spawns, network connections, privilege changes
  • Configuration files: /etc/falco/falco.yaml (config), /etc/falco/falco_rules.yaml (built-in rules), /etc/falco/falco_rules.local.yaml (custom rules)

Falco Rule Structure

  • rule: rule name
  • desc: description
  • condition: the matching expression (Falco macros + fields)
  • output: alert message (interpolates fields like %user.name, %container.name)
  • priority: EMERGENCY, ALERT, CRITICAL, ERROR, WARNING, NOTICE, INFORMATIONAL, DEBUG

Essential Falco Fields & Macros

  • container — macro: event occurred in a container
  • spawned_process — macro: new process was exec'd
  • open_read — macro: file opened for reading
  • fd.name — file descriptor full path (e.g., /etc/shadow)
  • proc.name — process name (e.g., sh, bash)
  • user.name — user running the process
  • container.name — container name
  • k8s.pod.name — Kubernetes Pod name

Common CKS Falco Rules

  • Shell in container: spawned_process and container and proc.name in (sh, bash, zsh, dash)
  • Read sensitive file: open_read and container and fd.name in (/etc/shadow, /etc/passwd)
  • Read env variables: open_read and container and fd.name=/proc/1/environ
  • Write to /etc: open_write and container and fd.directory=/etc
Falco uses its own condition language — not Prometheus PromQL, not OPA Rego. Know the specific Falco macros and field names. The most common exam mistake is using syscall.type or file.path (don't exist) instead of evt.type and fd.name.
For the CKS exam, you'll likely need to write or edit a Falco custom rule and verify it fires. Practice: edit /etc/falco/falco_rules.local.yaml, restart Falco (systemctl restart falco), trigger the condition, check journalctl -u falco -n 20. The entire workflow in under 5 minutes.
Kubernetes Audit Logging

Audit Policy Levels

  • None — do not log at all
  • Metadata — log request metadata only (user, timestamp, resource, verb) — no body
  • Request — log metadata + request body (captures write payloads)
  • RequestResponse — log metadata + request + response body (most verbose, captures secret values in reads)

Audit Policy Rule Ordering

  • Rules are evaluated top-to-bottom, first match wins
  • Put suppressions (level: None) BEFORE broad rules or they will never fire
  • Put the most specific rules (e.g., Secrets at RequestResponse) before broad fallback rules

Sample Audit Policy

  • Suppress read-only requests to configmaps: level: None, verbs: [get,list,watch], resources: [{resources: [configmaps]}]
  • Log all Secret operations with full body: level: RequestResponse, resources: [{resources: [secrets]}]
  • Catch-all: level: Metadata (last rule)

Configuring Audit on the API Server

  • Add to /etc/kubernetes/manifests/kube-apiserver.yaml:
  • --audit-policy-file=/etc/kubernetes/audit-policy.yaml
  • --audit-log-path=/var/log/kubernetes/audit.log
  • --audit-log-maxage=30 — retain logs for 30 days
  • Mount the audit policy file into the static Pod as a hostPath volume
CKS audit tasks typically give you a policy requirement (e.g., "log all secrets read with RequestResponse level, suppress configmap reads") and ask you to write the audit policy YAML, configure it on the apiserver, and verify the log is written. Watch the rule order — this is the most common mistake.
Immutable Infrastructure & Incident Response

Immutable Containers in Practice

  • readOnlyRootFilesystem: true — the root filesystem is read-only
  • Apps needing writes: use emptyDir volumes for /tmp, log directories, cache
  • Security advantage: any filesystem change = unambiguous attacker activity
  • Verify: kubectl exec <pod> -- touch /test.txt should fail with "Read-only file system"

Container Forensics on a Running Cluster

  • Never run commands inside a compromised container — you're executing attacker-controlled code
  • Use crictl on the node to inspect container state without entering it
  • Inspect filesystem: crictl inspect <container-id> → find overlay filesystem paths
  • Capture state: mount overlay layers on a forensic volume
  • Preserve evidence: take a node snapshot before any remediation

Behavioral Analysis & Anomaly Detection

  • Falco alerts provide runtime behavioral signals — forward to SIEM with falcosidekick
  • Kubernetes audit logs provide API-level signals — who changed what, when
  • Combine both: Falco catches runtime syscall anomalies, audit logs catch control-plane changes
  • Key forensic audit log fields: user.username, verb, objectRef.resource, objectRef.name, sourceIPs
The CKS is the only CNCF certification that directly tests your response to a simulated attack scenario. You may be given a cluster with a "compromised" pod and asked to identify indicators using audit logs and Falco, then apply the appropriate containment controls. Practice your forensic instincts, not just the configuration tasks.
Know how to query audit logs quickly: cat /var/log/kubernetes/audit.log | jq 'select(.verb=="delete" and .objectRef.resource=="secrets") | {user: .user.username, name: .objectRef.name, time: .requestReceivedTimestamp}'. Parsing JSON audit logs with jq is a core CKS exam skill.

Key Concept: Falco vs Audit Logs

Falco watches kernel syscalls in real time — it fires the moment a container opens a sensitive file or spawns a shell. Kubernetes Audit Logs capture Kubernetes API operations — who called the API, what resource was accessed, what was the response. Use Falco for runtime container behavior; use audit logs for Kubernetes control plane activity. The CKS tests both independently — they complement each other.

6-Week CKS Study Plan

Week 1
Prerequisites & Setup: Confirm your CKA is valid. Set up a Kubernetes cluster (kubeadm on VMs or kind + Calico). Review NetworkPolicy and RBAC fundamentals. Install Falco, kube-bench, and Trivy on your lab cluster.
Week 2
Cluster Setup & Hardening: Run kube-bench against your cluster and fix all FAIL items. Practice writing NetworkPolicy YAML for namespace isolation and metadata endpoint blocking. Configure the API server with all security flags. Practice RBAC tasks with kubectl auth can-i.
Week 3
System Hardening: Load AppArmor profiles, reference them in Pods. Configure seccomp RuntimeDefault and custom profiles. Write Pod specs with full SecurityContext hardening (drop ALL caps, readOnlyRootFilesystem, runAsNonRoot, allowPrivilegeEscalation=false). Create RuntimeClasses for gVisor scenarios.
Week 4
Microservice Vulnerabilities & Secrets: Apply Pod Security Admission to namespaces. Write OPA Gatekeeper ConstraintTemplates. Configure Secrets encryption at rest. Practice the Vault Agent Injector pattern. Apply all three layers (PSA + Gatekeeper + SecurityContext) together.
Week 5
Supply Chain Security: Scan images with Trivy in CI simulation. Sign images with Cosign and verify. Build multi-stage distroless Dockerfiles. Configure ImagePolicyWebhook (fail-closed). Write OPA policies for registry enforcement. Run trivy k8s cluster and fix findings.
Week 6
Runtime Security & Mock Exams: Write custom Falco rules and verify them. Configure Kubernetes audit logging with a tiered policy. Practice parsing audit logs with jq. Use killer.sh for 2 full mock exam sessions. Focus on speed — the real exam is 2 hours for 15–20 hands-on tasks.

Top 4 CKS Exam Mistakes

CKS vs CKA — What's Different?

CKA — Administration

  • Cluster installation (kubeadm)
  • etcd backup & restore
  • Node maintenance and upgrades
  • Workload management (Deployments, rolling updates)
  • Storage: PV, PVC, StorageClass
  • Troubleshooting broken clusters

CKS — Security (requires CKA)

  • CIS benchmark hardening
  • RBAC least privilege + SA token management
  • AppArmor, seccomp, Linux capabilities
  • OPA Gatekeeper, Pod Security Admission
  • Falco runtime threat detection
  • Audit logging + supply chain security

Test your CKS knowledge

60 scenario-based questions covering all 6 CKS domains — Falco rules, RBAC, audit policy, NetworkPolicy, OPA and more.

← Back to all courses