Back to Blog

Kubernetes Runtime Security for the CKS Exam: Falco, Audit Logs & Threat Detection (2026)

A hands-on guide to the Monitoring, Logging & Runtime Security domain of the CKS exam — detecting threats with Falco, writing custom rules, enforcing container immutability, and using Kubernetes audit logs, with practical commands and YAML.

By Sailor Team , June 11, 2026

Supply chain and admission control stop bad things from entering your cluster. Runtime security is about everything that happens after a pod is already running — and on the Certified Kubernetes Security Specialist (CKS) exam, that’s one of the heaviest domains. Monitoring, Logging and Runtime Security carries roughly 20% of the exam weight, tied with Cluster Hardening and Supply Chain Security as one of the big three.

This guide walks the entire domain from a practitioner’s point of view: detecting suspicious behavior with Falco, writing and tuning custom rules, enforcing immutability on running containers, and wiring up Kubernetes API audit logging. You’ll get the concepts, the exact commands, and the exam-day reflexes that let you finish these tasks before the two-hour clock runs out.

If you still need the big picture of the exam first, start with the CKS Exam Guide 2026 and the CKS Exam Topics breakdown, then come back here to go deep on runtime security.

What “Runtime Security” Actually Covers

Runtime is the live attack surface. A pod that passed every admission check can still be compromised by a vulnerable dependency, a leaked credential, or a misconfiguration that lets an attacker get a shell. Runtime security answers two questions: Is something malicious happening right now? and Can I prove what happened after the fact?

For the CKS exam, this domain breaks down into four practical skills:

SkillWhat you’ll do on the exam
Behavioral analytics & threat detectionDeploy Falco, write rules, find triggered alerts
Container immutabilityLock down securityContext so containers can’t be modified
Kubernetes audit loggingConfigure an audit policy on the API server
Investigate attacksRead Falco output and audit logs to trace activity

Each maps to a tool or a Kubernetes mechanism. Let’s take them in order.

Detecting Threats with Falco

Falco is the CNCF runtime security project and the tool the CKS exam expects you to know. It watches the kernel’s system call stream — open, execve, connect, setuid, and so on — and raises an alert whenever activity matches one of its rules. Because it operates at the syscall layer (via an eBPF probe or a kernel module), it sees what a container is actually doing, not just what its manifest claims.

How Falco is structured

Falco’s configuration lives in a few files you should be able to find instantly:

/etc/falco/falco.yaml          # main config: outputs, drivers, log level
/etc/falco/falco_rules.yaml    # default shipped rules (don't edit these)
/etc/falco/falco_rules.local.yaml  # your custom & override rules
/etc/falco/rules.d/            # additional rule files

The golden rule on the exam: never edit falco_rules.yaml directly. Put custom rules and overrides in falco_rules.local.yaml, which is loaded last and wins.

Rules, macros, and lists

A Falco ruleset has three building blocks:

  • Lists — reusable collections of values (e.g. a set of binaries).
  • Macros — named, reusable condition snippets.
  • Rules — the actual detections, each with a condition, output, and priority.

Here’s a minimal custom rule that fires whenever a shell is spawned inside a container — a classic indicator of an interactive intrusion:

# /etc/falco/falco_rules.local.yaml
- rule: Terminal shell in container
  desc: A shell was spawned inside a container
  condition: >
    spawned_process and container
    and shell_procs and proc.tty != 0
  output: >
    Shell opened in container
    (user=%user.name container=%container.name
    image=%container.image.repository proc=%proc.cmdline)
  priority: WARNING
  tags: [container, shell, runtime]

The condition is a filter expression over syscall fields. output is the human-readable alert, with %-prefixed fields interpolated at fire time. priority is one of EMERGENCY, ALERT, CRITICAL, ERROR, WARNING, NOTICE, INFORMATIONAL, DEBUG — and you’ll often be asked to filter alerts by priority, so know the order.

Running Falco and reading its output

On a node where Falco is installed as a service:

# Check Falco is running and see its alerts
systemctl status falco
journalctl -u falco -f

# Validate a rules file before relying on it
falco -V -r /etc/falco/falco_rules.local.yaml

# Run Falco with a specific rule file and human output
falco -r /etc/falco/falco_rules.local.yaml -o json_output=false

A very common exam task: “Falco is running on the node. A rule has detected a process. Find the alert and write the container name / time / details to a file.” The fastest path is journalctl -u falco (or reading the configured log file) and grepping for the rule name or priority:

# Find every CRITICAL-or-higher Falco alert and save it
journalctl -u falco --no-pager | grep -i "critical" > /opt/falco-incident.log

Falco is frequently deployed in-cluster as a DaemonSet so every node is covered:

kubectl get pods -n falco -o wide
kubectl logs -n falco ds/falco | grep "Terminal shell"

Tuning a noisy rule

You’ll sometimes be asked to change an existing rule rather than write a new one — for example, raise its priority or narrow its condition. Override by redefining the rule with the same name in falco_rules.local.yaml:

# Override the default to only alert for non-allowed images
- rule: Terminal shell in container
  condition: >
    spawned_process and container and shell_procs
    and proc.tty != 0
    and not container.image.repository in (allowed_images)
  priority: CRITICAL
  override:
    condition: replace
    priority: replace

After any rules change, restart Falco and confirm it loaded cleanly:

systemctl restart falco
journalctl -u falco -n 20 --no-pager   # look for "Loading rules" with no errors

Enforcing Container Immutability

The second pillar of this domain is making sure a running container cannot be tampered with. An immutable container has no writable filesystem, runs as a non-root user, and carries only the Linux capabilities it truly needs. If an attacker lands inside it, there’s nothing to write, no package manager to abuse, and no privilege to escalate.

This is all done in the pod’s securityContext:

apiVersion: v1
kind: Pod
metadata:
  name: hardened-app
spec:
  containers:
    - name: app
      image: myapp:v1
      securityContext:
        readOnlyRootFilesystem: true      # filesystem can't be modified
        runAsNonRoot: true                # refuse to run as root
        runAsUser: 1000
        allowPrivilegeEscalation: false   # no setuid escalation
        privileged: false
        capabilities:
          drop: ["ALL"]                   # start from zero capabilities
          add: ["NET_BIND_SERVICE"]       # add back only what's needed
      volumeMounts:
        - name: tmp
          mountPath: /tmp                 # writable scratch space if required
  volumes:
    - name: tmp
      emptyDir: {}

The exam mindset here is to take an insecure pod and harden it in place. A useful checklist you should be able to apply from memory:

SettingWhy it matters
readOnlyRootFilesystem: trueStops malware/dropper writing to disk
runAsNonRoot + runAsUserRemoves root inside the container
allowPrivilegeEscalation: falseBlocks setuid privilege gain
capabilities.drop: ["ALL"]Least privilege at the kernel level
privileged: falseNo host-level access

To enforce these org-wide rather than per pod, you use Pod Security Admission (the built-in restricted profile covers most of the above) or a policy engine — concepts that overlap with the Kubernetes security best practices for CKS and the admission-control work covered in the CKS supply chain security guide.

seccomp and AppArmor at runtime

Two more runtime controls the exam loves:

  • seccomp filters which syscalls a container may make. The safest practical setting is the runtime default profile:

    securityContext:
      seccompProfile:
        type: RuntimeDefault

    Custom profiles live under /var/lib/kubelet/seccomp/profiles/ and are referenced with type: Localhost and localhostProfile: profiles/audit.json.

  • AppArmor confines what files and capabilities a process can touch. In current Kubernetes you set it via the security context (older versions used an annotation):

    securityContext:
      appArmorProfile:
        type: Localhost
        localhostProfile: k8s-apparmor-restrictive

Know how to confirm a profile is active — kubectl exec into the pod and try a denied action (e.g. write to a read-only path) and watch it fail.

Kubernetes Audit Logging

Falco watches the kernel; audit logging watches the API. Every request to kube-apiserver — who did what, to which resource, and whether it was allowed — can be recorded. On the exam you’re typically asked to create or modify an audit policy and wire it into the API server.

Audit levels and stages

An audit policy decides how much detail to record for each request:

LevelWhat it records
NoneNothing — used to drop noisy requests
MetadataWho, what, when (no request/response bodies)
RequestMetadata + request body
RequestResponseMetadata + request and response bodies

A minimal policy that captures secret access in detail but ignores noise:

# /etc/kubernetes/audit/policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
  # Log secret access at the most detailed level
  - level: RequestResponse
    resources:
      - group: ""
        resources: ["secrets"]
  # Log everything else at metadata level
  - level: Metadata
    omitStages:
      - "RequestReceived"

Wiring it into the API server

The API server is a static pod, so you edit its manifest and add the audit flags plus the volume mounts for the policy and log file:

# /etc/kubernetes/manifests/kube-apiserver.yaml (excerpt)
spec:
  containers:
    - command:
        - kube-apiserver
        - --audit-policy-file=/etc/kubernetes/audit/policy.yaml
        - --audit-log-path=/var/log/kubernetes/audit/audit.log
        - --audit-log-maxage=30
        - --audit-log-maxbackup=5
        - --audit-log-maxsize=100
      volumeMounts:
        - name: audit-policy
          mountPath: /etc/kubernetes/audit/policy.yaml
          readOnly: true
        - name: audit-logs
          mountPath: /var/log/kubernetes/audit/
  volumes:
    - name: audit-policy
      hostPath:
        path: /etc/kubernetes/audit/policy.yaml
        type: File
    - name: audit-logs
      hostPath:
        path: /var/log/kubernetes/audit/
        type: DirectoryOrCreate

Because the API server is a static pod, saving the manifest makes the kubelet restart it automatically. Watch it come back:

# The apiserver container will restart; wait for it
watch crictl ps | grep kube-apiserver

# Then confirm audit events are landing
tail -f /var/log/kubernetes/audit/audit.log

A frequent exam trap: an invalid audit policy crashes the API server and kubectl stops responding. Always kubectl apply --dry-run=client your policy logic mentally, double-check the YAML indentation, and keep a backup of the original manifest before editing.

Investigating an Attack

The final skill ties the others together: given Falco alerts and audit logs, reconstruct what happened. A practical investigation flow:

  1. Triage the Falco alert — which rule, which container, which process, what time?
  2. Pivot to the audit log — search for the same timeframe and the service account or user involved.
  3. Identify the phase — was this reconnaissance (listing secrets), execution (a shell), or persistence (a new pod/role)?
  4. Contain — cordon the node, delete the pod, revoke the credential or RBAC binding.
# Correlate: find what a suspicious service account did
grep "system:serviceaccount:prod:deployer" /var/log/kubernetes/audit/audit.log \
  | grep '"verb":"create"'

Speed here comes from having read these logs before — the formats are dense, and exam time is short.

A 7-Day Runtime Security Study Plan

DayFocusHands-on goal
1Falco install & architectureLocate all config files, read the default rules
2Write custom Falco rulesDetect a shell, a write to /etc, an outbound connection
3Tune & override rulesRaise a priority, add an exception, reload cleanly
4Container immutabilityHarden 3 insecure pods from memory under 5 min each
5seccomp & AppArmorApply RuntimeDefault + a Localhost profile, prove a deny
6Audit policyConfigure API server audit end-to-end, recover from a bad policy
7Investigation drillCorrelate a Falco alert to an audit entry against the clock

The thing that separates a pass from a fail in this domain is fluency, not theory. Reading about Falco rules is not the same as having written five of them and knowing exactly which file they go in.

Practice in a Real Exam-Like Environment

Runtime security tasks are muscle memory. You want to have already triggered a Falco rule and recovered a crashed API server before exam day — not be doing it for the first time under the two-hour clock.

Sailor.sh’s Certified Kubernetes Security Specialist (CKS) Mock Exam Bundle gives you a browser-based, exam-style terminal wired to a live Kubernetes cluster, with realistic runtime scenarios: writing Falco rules, hardening running pods, and configuring audit policies against a real API server. It mirrors the exam’s format and time pressure so the reflexes are there when it counts. If you want to try a free, open-source practice terminal first, the CKS practice environment guide walks through getting started, and how to practice CKS for free lists more options.

Pair the hands-on work with structured study using the CKS Study Plan, and make sure you’ve cleared the CKS prerequisites — you need a current CKA to even sit the exam.

Frequently Asked Questions

How much of the CKS exam is runtime security?

Monitoring, Logging and Runtime Security accounts for roughly 20% of the CKS exam — one of the three largest domains alongside Cluster Hardening and Supply Chain Security.

Do I need to memorize Falco rule syntax?

You should be fluent writing a rule with condition, output, and priority, and you must know where custom rules go (falco_rules.local.yaml). The exam gives documentation access, but fumbling for syntax costs time you don’t have. Write a dozen rules in practice until it’s automatic.

What’s the difference between Falco and audit logs?

Falco watches kernel system calls to detect what a container is doing (a shell, a file write, an outbound connection). Kubernetes audit logs record API server requests — who called the API and what they asked for. You need both: one sees workload behavior, the other sees control-plane activity.

What’s the single highest-impact runtime change I can make?

Setting readOnlyRootFilesystem: true together with runAsNonRoot and dropping all capabilities. It removes the writable disk, the root user, and the kernel privileges that most container attacks depend on — usually just a few lines of securityContext.

How do I avoid breaking the API server when adding an audit policy?

Back up /etc/kubernetes/manifests/kube-apiserver.yaml first, validate your policy YAML indentation, and make sure the host paths for the policy file and log directory actually exist. A malformed policy or missing mount will crash the API server and lock you out of kubectl.

Can I pass the CKS without a strong CKA foundation?

Unlikely. CKS assumes you already move fast in a cluster — editing static pod manifests, reading logs, fixing RBAC. If those feel slow, shore them up first. See CKA vs CKAD vs CKS: which certification first.

Conclusion

The runtime security domain rewards practitioners who actually do the work: deploy Falco and read its alerts, lock a container down so there’s nothing to exploit, and turn on audit logging so every API call leaves a trail. None of it is conceptually hard — but all of it is timed, and the gap between knowing it and doing it fast is hours in a real terminal.

Get Falco rules into your fingers, make securityContext hardening boring, and configure API server auditing until you can recover from a bad policy without panicking. The same skills that earn the certification are the ones that genuinely detect and contain attacks in production — which is the entire point of CKS.

Limited Time Offer: Get 80% off all Mock Exam Bundles | Sale ends in 7 days. Start learning today.

Claim Now