How do you stop an attacker who has already found a way inside your computer system? This is the core problem that node and container security solves for the Certified Kubernetes Security Specialist (CKS) exam. It matters because even if someone breaks into your Kubernetes cluster, you need defences that limit the damage they can do, preventing them from taking over the whole system or stealing everything at once.
Jump to a section
A simple way to picture Cluster Hardening: Node and Container Security
What would it take to stop a thief who has already snuck inside the museum after hours?
Imagine a museum with priceless paintings. The museum has a strong front gate (that is your cloud security) and a security guard checking tickets (that is your authentication). But what happens if a thief manages to get past those measures? This is where every exhibition room needs its own security, and each painting needs its own glass case. This chapter is about making each room and each glass case tough to break into, even if the main entrance has been breached.
The museum's walls are the nodes (the servers). If a wall is made of cardboard, a thief could kick right through it and access the storage room. We have to harden the node walls with concrete (system updates, disabled unused services). The paintings inside the glass cases are the containers (the applications). A glass case not only protects the painting but also has a tamper alarm. If someone tries to break the glass to steal the painting (a container escape), the alarm triggers and security rushes to that room. Hardening nodes means making the building itself impenetrable, and hardening containers means making each glass case a self-contained fortress that can't be cracked open to access the other paintings in the room. We are securing the inside, because the outside might already be compromised.
Node and container security is a set of practices to protect the individual computers (nodes) that run your applications (containers) inside a Kubernetes cluster, and to protect the applications themselves from harming each other or the underlying system. A Kubernetes cluster is a group of computers, called nodes, that work together. Each node can be a physical machine or a virtual machine (a simulated computer running inside another computer). On each node, the container runtime (like Docker or containerd) runs your application inside an isolated environment called a container. A container is a lightweight, standalone, executable package that includes everything needed to run a piece of software.
Let's start with node hardening. A node that is not hardened is like a house with all the doors unlocked. Hardening means making it difficult for an attacker to compromise that specific computer. This begins with the host operating system (OS), the fundamental software that makes the computer run. You must regularly apply security patches (updates that fix known vulnerabilities) to the OS. You should disable any services that are not required. A service is a program that runs in the background, like a file-sharing service or a web server. If you don't need it, turn it off. You should also configure authentication (the process of verifying who you are) and authorisation (the process of deciding what you are allowed to do) for accessing the node itself, typically by using SSH (Secure Shell) keys instead of passwords. A common tool is AppArmor (Application Armor), a Linux kernel security module that restricts what programs can do. You can also use seccomp (Secure Computing Mode), which limits the system calls a container can make. A system call is a request the program makes to the operating system kernel (the core of the OS) to do something, like open a file or connect to a network. By limiting these calls, you make it much harder for a compromised container to attack the host node.
The goal of node hardening is to reduce what security experts call the 'attack surface' — the total number of ways an attacker could potentially try to break into the system.
Now, let's look at container security. A container should be run with only the minimum necessary permissions. This is the 'principle of least privilege'. A container doesn't need root access (administrator power) to run your web application. If a container runs as root and is compromised, the attacker instantly has full control over that container and has an easier path to escaping onto the host node. You should use a dedicated user for the container, defined in the container image (the template used to build the container). You should also make the container's filesystem read-only whenever possible. A filesystem is the structure where files are stored. Making it read-only means the container cannot write new files or modify existing ones, which stops malware from saving itself onto the disk.
Kubernetes provides Pod Security Standards (PSS) to help. A pod is the smallest deployable unit in Kubernetes, which can hold one or more containers. Pod Security Standards define three policies:
Privileged: Unrestricted. The container can do almost anything. This is the least secure and should be avoided.
Baseline: Minimally restrictive. It prevents known privilege escalations but allows the container to run normally.
Restricted: Heavily constrained. It follows the principle of least privilege closely, blocking many things that could be dangerous.
These standards replace older concepts like Pod Security Policies (PSP) which were deprecated (removed from newer versions of Kubernetes). You will apply these standards using Admission Controllers. An Admission Controller is a piece of code that intercepts requests to the Kubernetes API (the main control interface) to create a pod, and either allows or denies the request based on the security rules you have set.
Why does this matter? In older models, you trusted the container and the system. Now, you trust nothing. You build layers of security so that even if one layer fails, another layer catches the attacker. For the CKS exam, the focus is on practical tasks: editing configuration files, checking running containers, and applying security contexts (settings inside a pod's definition file that specify user IDs, filesystem permissions, and other restrictions). You will also need to use tools like kube-bench (a tool that checks your cluster against security best practices) and kube-hunter (a tool that looks for vulnerabilities in your cluster). You might also need to use Falco, a security monitoring tool that watches for suspicious behaviour in your containers and nodes. This is not just theory; you will be expected to type commands into a terminal to harden a cluster in a time-pressured exam environment.
Audit the nodes with kube-bench
Run kube-bench on a controlplane node to discover misconfigurations. The output will list failed tests with specific remediation steps. This step is crucial because it gives you a targeted list of exactly what to fix, rather than guessing. For cluster hardening, this is your starting point.
Fix kubelet configuration
Edit the kubelet config file (usually /var/lib/kubelet/config.yaml) to disable anonymous authentication and enable only HTTPS. Restart the kubelet service afterwards. This step matters because an unauthenticated kubelet can be controlled by anyone on the network, giving them access to all pods on that node.
Apply Pod Security Standards to a namespace
Label the target namespace with 'pod-security.kubernetes.io/enforce: restricted'. This tells the Admission Controller to reject any pod that does not meet the 'restricted' level. This step hardens the pod creation process by preventing insecure pods from ever being deployed.
Configure a security context for a container
Edit the pod's YAML file to add 'securityContext.runAsUser: 1000' and 'securityContext.readOnlyRootFilesystem: true'. This changes the user the container process runs as and prevents it from writing to its own filesystem. This is a direct application of least privilege, limiting damage if the container is compromised.
Enable a seccomp profile
Create a seccomp JSON file on the node that blocks the 'mount' syscall. Then, add an annotation to the pod to reference that profile. This step hardens the container against kernel-level attacks by restricting the system calls it can make.
Install and test Falco
Deploy Falco as a DaemonSet across the cluster. Configure it to log alerts to a file. Then, simulate a suspicious action inside a container (like running 'cat /etc/shadow') and verify that Falco logs the alerts. This step provides runtime monitoring to detect active attacks.
An IT professional working as a Kubernetes administrator at a mid-sized e-commerce company is tasked with hardening the cluster before a major sales event. They know that during high traffic, attempts to exploit vulnerabilities increase. Here is what they actually do, step by step.
First, they audit the nodes. They log into each machine and run kube-bench. This tool automatically checks the node against the CIS (Center for Internet Security) Kubernetes Benchmark, a published set of security recommendations. The report shows that SSH password authentication is still enabled on two nodes, and the kubelet service (the primary agent that runs on each node) is listening on an insecure port. The administrator disables password authentication, forces the use of SSH keys only, and reconfigures the kubelet to use only secure, encrypted ports (port 10250 instead of 10255).
Next, they analyse existing containers. They use the command 'kubectl get pods --all-namespaces' to see every running pod. Then they inspect the security context of a critical payment processing pod. They output the pod's definition file and see that the container is set to 'privileged: true'. This is a major risk. A privileged container has all the same access to the host as the root user. The administrator works with the development team to tweak the container code. They remove the privileged flag, and instead set 'allowPrivilegeEscalation: false' and 'runAsUser: 1000'. They drop all Linux capabilities (specific permissions a container requests, like the ability to change network settings) except those absolutely needed. This means the container runs as a non-root user with minimal permissions.
Then, they implement Pod Security Standards. The administrator creates a namespace for the payment services called 'payments'. They add a label to that namespace: 'pod-security.kubernetes.io/enforce: restricted'. This label tells Kubernetes to reject any pod that does not meet the 'restricted' policy level. The administrator then tries to deploy the old unhardened pod definition. The deployment fails because the container is running as root. The administrator works with the developer to fix the image to run as a non-root user, and after the fix, the pod is created successfully.
Finally, they set up runtime security. They install Falco via a Kubernetes DaemonSet (a controller that ensures a copy of a pod runs on every node). Falco will now monitor system calls and alert the operations team if a container tries to spawn a shell or read sensitive files like '/etc/shadow'. This gives the team real-time visibility into attacks that bypass the initial hardenings. The team also configures Falco to send alerts to a central logging system (like the ELK stack — Elasticsearch, Logstash, Kibana) so they can investigate incidents after the fact.
This real-world workflow ensures that even if a developer accidentally pushes a vulnerable container, the cluster's built-in defences block it. The administrator does not just trust the people using the system; they design the system so that mistakes are caught automatically.
The CKS exam is a performance-based exam. You do not answer multiple-choice questions; you sit in front of a real, but isolated, Kubernetes cluster and must complete a series of tasks within a limited time (usually 2 hours). Node and container hardening is a major focus area. The exam will test your ability to implement security measures using command-line tools rather than just knowing the theory.
The exam loves to test specific concepts in very specific ways. Here are the exact topics and traps:
Pod Security Standards (PSS): You must know how to enable these using labels on namespaces. The trap is that the exam environment might still reference the older Pod Security Policies (PSP). You must remember that PSP is deprecated and PSS is the current standard. You will be asked to apply a 'restricted' policy to an existing namespace and then deploy a pod. If the pod fails, you must edit its definition to comply with the policy, which often means setting 'runAsNonRoot: true' and dropping all capabilities.
Security Context: This is a setting inside a Pod or Container specification. You will be given a YAML file (a human-readable data serialisation language used for Kubernetes configuration) that has no security context. You must add 'securityContext.runAsUser: 1000', 'securityContext.runAsGroup: 3000', and 'securityContext.fsGroup: 2000'. The trap is sometimes you must apply it at the pod level, other times at the container level, and the exam expects you to know the difference in how the YAML is structured.
AppArmor and seccomp: You will be asked to enable these on existing pods. A common trap is that AppArmor profiles are not enabled by default. You must load a profile onto the node (manually, using a command) and then reference that profile in the pod's annotation (a key-value pair in the pod metadata). For seccomp, the exam might ask you to create a custom seccomp profile that blocks a specific system call like 'mount'. The trap is that the seccomp profile path must be correct, and the pod annotation must match exactly (e.g., 'container.seccomp.security.alpha.kubernetes.io/<container-name>: localhost/<path>').
Runtime security with Falco: The exam may ask you to install Falco and verify it is running. A trap here is that Falco must have its configuration file modified to output alerts to a specific file, and you must demonstrate that alerts are being logged by checking the file. You may also be asked to write a custom Falco rule to detect a specific behaviour, like a container reading a sensitive file.
kube-bench: You will run kube-bench on a controlplane node (the main node that manages the cluster) and fix one or two of the issues it reports. The trap is that the issues are often subtle things like 'the kubelet API is not authenticated' or 'etcd (the cluster's key-value store) has no peer authentication'. You must fix these by editing the configuration files (usually under /etc/kubernetes/) and restarting the relevant services.
Container Immutability: The exam tests the idea that containers should be treated as immutable (unchangeable). They will ask you to set a container's filesystem to read-only. The command to know is 'securityContext.readOnlyRootFilesystem: true' in the pod spec.
The exam always presents a scenario. For instance: "A security audit has revealed an abnormal number of containers running as root. Hardening is required. Apply the restricted Pod Security Standard to the 'applications' namespace and ensure all existing pods in that namespace meet the new policy." You must execute the commands without any hints. The correct answer pattern is: (1) Label the namespace, (2) Check existing pods, (3) Edit any non-compliant pod definitions using 'kubectl edit', (4) Redeploy if necessary.
Key definitions to memorise:
Privilege escalation: The act of gaining elevated access to resources that are normally protected from an application or user.
Capabilities: Fine-grained permissions that can be assigned to a container, such as the ability to bind to a privileged port (<1024).
seccomp profile: A JSON file that defines which Linux system calls a container is allowed to make.
AppArmor profile: A text file that defines what a program can access (files, networks, etc.).
Node hardening reduces the attack surface by applying OS patches, disabling unused services, and configuring secure SSH access.
Containers must run with the principle of least privilege: non-root user, dropped capabilities, and a read-only filesystem.
Pod Security Standards (PSS) have replaced Pod Security Policies (PSP) and are enforced via namespace labels in Kubernetes 1.25 and later.
A privileged container has all the same host access as root and should be avoided in production environments.
AppArmor and seccomp restrict what a container can do at the kernel level, adding a critical layer of defence against container escapes.
Tools like kube-bench, kube-hunter, and Falco are used in the CKS exam to audit and monitor cluster security.
Making a container's filesystem read-only prevents malware from writing itself to disk and tampering with application files.
Security context settings (runAsUser, runAsGroup, fsGroup) are configured inside the pod YAML definition file.
These come up on the exam all the time. Here's how to tell them apart.
Privileged Container
Has all root capabilities on the host
Can access host devices directly
Should not be used in production
Unprivileged Container
Runs with dropped capabilities
Has a read-only filesystem where possible
Follows the principle of least privilege
Pod Security Policy (PSP)
Deprecated since Kubernetes 1.21
Removed in Kubernetes 1.25
Was a cluster-level resource
Pod Security Standards (PSS)
Current security standard
Enforced via namespace labels
Has three levels: privileged, baseline, restricted
AppArmor
Controls file access and program capabilities
Uses profiles defined in text format
Works at the path and process level
seccomp
Controls Linux system calls
Uses profiles defined in JSON format
Works at the kernel system call level
readOnlyRootFilesystem: false
Container can write files to its root filesystem
Increases attack surface for malware
Default setting for most images
readOnlyRootFilesystem: true
Container cannot write to its filesystem
Prevents malware from persisting
Requires careful design for apps that need temporary storage
runAsUser: 0 (root)
Container has full root privileges
Simpler to configure initially
High risk if container is compromised
runAsUser: 1000 (non-root)
Container runs with limited user privileges
Requires image built with non-root user
Reduces damage from container breach
Mistake
If I run my container as a non-root user, I don't need to worry about any other security settings.
Correct
Running as a non-root user is a critical step, but it is not sufficient. You still need to drop unnecessary capabilities, set the filesystem to read-only, and restrict system calls with seccomp, or a compromised container could still use other attack vectors.
Beginners often think that 'non-root' equals 'completely safe', because they are used to thinking of root as all-powerful. They do not realise that a container can still perform dangerous actions as a normal user, like making network connections or reading sensitive files, unless those are explicitly blocked.
Mistake
Pod Security Policies (PSP) are the only way to enforce container security in Kubernetes.
Correct
Pod Security Policies were deprecated in Kubernetes version 1.21 and removed in version 1.25. The current standard is Pod Security Standards (PSS), implemented via namespace labels and Admission Controllers.
Many older blog posts and tutorials still reference PSP, and because the exam environment might be somewhat older, beginners assume PSP is still the primary method. They haven't read the Kubernetes changelog that documents the deprecation.
Mistake
Hardening a node means installing an antivirus and a firewall on the host operating system.
Correct
While firewalls are part of node security, the core of node hardening in a Kubernetes context is about configuring the host OS securely, disabling unnecessary services, applying patches, and using tools like AppArmor and seccomp. Antivirus is not typically considered a Kubernetes-specific hardening measure.
This misconception comes from a general IT security background. Beginners transfer their knowledge from personal computer security to server security without understanding that Kubernetes nodes have unique attack surfaces related to the container runtime and the kubelet.
Mistake
If I use a Docker image from the official registry, I don't need to worry about container hardening.
Correct
Even official images can have vulnerabilities or be run with insecure defaults. You must always audit the security context of the container and apply the principle of least privilege, regardless of the image source.
Beginners trust official repositories implicitly. They don't realise that an official image might run as root by default, or include unnecessary tools like 'curl' or 'bash' that increase the attack surface. They assume that 'official' means 'automatically secure'.
Mistake
If I set 'securityContext.runAsUser: 1000', the container will never be able to read files owned by root.
Correct
The kernel applies user ID mapping. A container running as user 1000 may still be able to read world-readable files owned by root (like /etc/passwd). runAsUser only controls the primary user ID, not file permissions entirely.
This is a nuanced Unix permissions concept. Beginners think that changing the user ID changes all access rules, but they forget about file permission bits (owner/group/other) and capabilities. They need to learn that a non-root user can still access many system files.
Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.
Pod Security Policies (PSP) were an older Kubernetes resource that allowed fine-grained control over pod security. Pod Security Standards (PSS) are the replacement, which use namespace labels and require an Admission Controller. PSS has three levels: privileged, baseline, and restricted.
Set 'securityContext.runAsUser: 1000' in the pod or container specification in the YAML file. Also ensure the container image itself is built to run as a non-root user, by using a USER directive in the Dockerfile.
It makes the container's filesystem read-only. The container cannot write new files or modify existing ones, which prevents malware from saving itself and protects against configuration file tampering.
A container escape is when a process inside a container breaks out of its isolation and gains access to the host node. Hardening prevents this by using non-root users, dropping capabilities, and restricting system calls with seccomp and AppArmor.
Yes. Every node, including controlplane nodes and worker nodes, should be hardened. An attacker only needs to compromise one weak node to potentially pivot to the rest of the cluster.
kube-bench is an open-source tool that checks your Kubernetes cluster against the CIS Kubernetes Benchmark, which is a set of security configuration recommendations. It runs on nodes and reports which checks pass and fail.
Falco is a runtime security tool that monitors container and host behaviour by observing system calls. It alerts on suspicious activity, such as a container spawning a shell or reading sensitive files like /etc/shadow.
You've finished Cluster Hardening: Node and Container Security. Continue through the CKS study guide to build a complete picture of the exam.
Done with this chapter?