Security contexts and pod security standards solve the problem of controlling what a running application can do inside its container, preventing it from taking over the host operating system. For the CKAD exam, you need to know how to set these permissions and how to enforce company-wide security rules on your Pods. This chapter teaches you how to lock down your containers like you would lock the doors and windows of your house.
Jump to a section
A simple way to picture Security Contexts and Pod Security Standards
A shared office kitchen is a place where employees from different teams can prepare food and store their lunches. The kitchen itself is a resource, like a Kubernetes Pod, that multiple containers (your lunch containers) share. Security Contexts are the individual rules you put on your own lunch bag. You might write your name on it, ensure it's sealed, and add a note that it needs to be kept cold. These are settings you, as the container, ask for. Pod Security Standards (PSS) are the overarching rules for the entire kitchen. The office manager might declare a 'Restricted' policy that bans all nut-based products, requires all containers to be clearly labelled, and forbids anyone from using the microwave after 2 PM. A 'Privileged' policy would be anything goes. Security Contexts are the fine-grained, per-container adjustments you make, while Pod Security Standards are the building-wide policies that apply to everyone, enforced by a security guard (the Pod Security Admission controller). If your lunch bag's rules (Security Context) violate the kitchen's policy (PSS), you will be told to leave the kitchen until you comply.
This maps precisely to how a Pod is the shared environment, each container has its own Security Context, and Pod Security Standards are admission control policies that check if the Pod's requested context is allowed before it can start running.
In Kubernetes, a container is a lightweight, standalone, executable package that includes everything needed to run a piece of software, including the code, runtime, system tools, and libraries. By default, a container might have more permissions than it needs to function. This is a security risk. If someone breaches the application, they could use those permissions to attack the underlying host (the server), or other containers on the same server. The principle of least privilege says you should give a process only the bare minimum permissions it needs to do its job.
A Security Context is a configuration object inside a Pod definition (a YAML file) that defines privilege and access control settings for a Pod or its containers. It is a set of constraints that you apply to the Pod, telling it exactly how it should run. You can set a Security Context at the Pod level, which then applies to all containers in that Pod, or you can set a Security Context for a specific container, which overrides the Pod-level settings for that container.
Key settings within a Security Context include:
runAsUser: This specifies the User ID (UID) that the container's process runs as. Instead of running as the powerful root user (UID 0), you specify a high-numbered, unprivileged user ID (e.g., 1000). Running as a non-root user is a fundamental security best practice.
runAsGroup: This specifies the primary Group ID (GID) for the process, similar to runAsUser.
readOnlyRootFilesystem: This is a critical setting. When set to 'true', the container's filesystem is made read-only. The application cannot write new files or modify existing ones on the container's own disk. This prevents an attacker from planting malicious scripts or altering configuration files. If the application needs to write temporary data, it must mount a separate writable volume.
allowPrivilegeEscalation: This controls whether a process can gain more privileges than its parent process. You should always set this to 'false' unless the application specifically needs it (e.g., a container that manages network interfaces). When false, it prevents techniques where a child process tries to become root.
capabilities: Linux capabilities are specific privileges that are normally associated with root, broken down into small, individual units. For example, the 'NET_BIND_SERVICE' capability allows a non-root user to bind to a port under 1024 (like port 80). Instead of giving a container full root access, you add only the specific capabilities it needs and drop all the rest using 'drop: [ALL]'.
Pod Security Standards (PSS) are a set of pre-defined security policies that Kubernetes offers to control what Security Contexts are allowed on a namespace (a logical cluster of resources). There are three levels:
Privileged: This is the most permissive policy. It places no restrictions. It is only used for system-level Pods that require full access (e.g., network plugins).
Baseline: This is a moderately restrictive policy that prevents known privilege escalations. It is designed to be easy to adopt for most common applications. It enforces rules like forbidding host networking, running as root, or using host paths for volumes.
Restricted: This is the most restrictive policy. It follows the current best practices for hardening Pods. It forces settings like running as a non-root user, using a read-only root filesystem, and dropping all Linux capabilities.
PSS is implemented by a component called the Pod Security Admission Controller. This is a piece of built-in software that intercepts requests to create or update Pods. When you try to create a Pod, the controller checks the Pod's Security Context against the PSS level you have configured on the namespace. If the Pod violates the policy, the controller can either warn you (audit mode) or reject the creation entirely (enforce mode).
You apply these standards to a namespace by adding a label to the namespace definition, such as 'pod-security.kubernetes.io/enforce: restricted'. This label tells the controller what level of security to enforce.
These mechanisms replace the older, now-deprecated PodSecurityPolicy (PSP), which was complex and hard to manage. PSS is much simpler and is the current standard for the CKAD exam.
Identify the Required Security Level
First, read the exam scenario. Determine if it asks for a specific user ID, a read-only filesystem, or a Pod Security Standard level (e.g., 'Restricted'). This tells you what constraints to place on the Pod.
Set the Pod-Level Security Context (Optional)
If the scenario does not specify different settings for each container, add a 'spec.securityContext' block. Set 'runAsUser' and 'runAsGroup' to the desired IDs. This sets a default for all containers in the Pod.
Set the Container-Level Security Context
Inside each container definition in the YAML, add a 'securityContext' field. This overrides the Pod-level for that container. Set 'readOnlyRootFilesystem: true' if required. Set 'capabilities.drop: [ALL]' to remove all privileges.
Add a Writable Volume for Temporary Data
Because the container's own filesystem is now read-only, you must add a volume mount. Declare an 'emptyDir' volume in the 'spec.volumes' array, and mount it inside the container at a path like '/tmp' using 'volumeMounts'.
Apply the Pod Security Standard to the Namespace
Edit the target namespace's YAML definition. Add a label in the format 'pod-security.kubernetes.io/enforce: restricted' (or 'baseline'). This tells the admission controller to check all new Pods in that namespace against that standard.
Deploy and Verify the Pod
Use 'kubectl apply -f <file>.yaml' to deploy. If the Pod is rejected, read the error message to see which security context field failed the policy check. Fix the YAML and reapply until the Pod is created successfully.
Imagine you work for a financial technology company called 'PayFlow'. The company has a Kubernetes cluster to run its payment processing service. Your boss gives you a task: deploy a new microservice that handles user profile data. The company has a strict security policy that all non-essential Pods must run under the 'Restricted' Pod Security Standard.
You know you cannot just use any old Pod definition. You must first check if the namespace you are deploying to has the correct label. You open a terminal and run 'kubectl get ns production -o yaml'. In the output, you see the label 'pod-security.kubernetes.io/enforce: restricted'. This confirms the namespace will reject any Pod that does not meet the 'Restricted' standard.
Now you write your Deployment YAML file (a specification for running a set of identical Pods). You know the Pod must not run as root. You set 'spec.securityContext.runAsUser: 1000' and 'spec.securityContext.runAsGroup: 3000'. You also make the filesystem read-only by setting 'spec.containers[0].securityContext.readOnlyRootFilesystem: true'.
Next, the application needs to write temporary session files. Since the filesystem is read-only, you add an 'emptyDir' volume (a temporary, writable directory) and mount it at '/tmp'. You also know the 'Restricted' policy requires you to drop all Linux capabilities. You add 'capabilities: drop: [ALL]'. You confirm the app doesn't need any specific capabilities; if it did, you would add them individually.
But the application is a web server that needs to listen on port 443 (HTTPS). Normally, binding to a port below 1024 requires root privileges. To avoid running as root, you add the single capability 'NET_BIND_SERVICE' to the container's Security Context, and you run the application as a non-root user. This is allowed under the 'Restricted' policy because you are not escalating privileges; you are giving the user a specific permission.
You also check if the application needs to access the host's network. It does not, so you set 'spec.hostNetwork: false' (which is the default but you make it explicit). The Pod attempts to communicate with a legacy database running on the host. You know the 'Restricted' policy forbids 'hostPort' and 'hostNetwork', so you configure a Kubernetes Service to route traffic to the database instead.
Finally, you run 'kubectl apply -f deployment.yaml'. The Pod Security Admission Controller intercepts the request. It checks your Pod's security context against the 'Restricted' profile. It sees the container runs as a non-root user, has a read-only filesystem, drops all capabilities, and does not use host networking. The controller accepts the request, and your Pod starts running. If you had accidentally omitted the 'readOnlyRootFilesystem' setting, the controller would have rejected the Pod, and you would see an error message explaining which policy was violated.
The CKAD exam tests your ability to apply Security Contexts and understand Pod Security Standards. You will not be asked to write YAML for PodSecurityPolicies (PSP) because they are deprecated. The exam focuses on defining security contexts inside a Pod spec and using namespace labels to enforce PSS.
Specific exam topics you must master:
Writing a container-level 'securityContext' block. You must know how to indent it correctly inside the 'containers' array. The exam often gives you a YAML file with missing fields and asks you to add the correct security context.
Setting 'runAsUser' and 'runAsGroup'. You will be given a scenario where a container runs as root and you must change it to a non-root user specified in the question.
Setting 'readOnlyRootFilesystem' to 'true'. You must then know to add a writable volume mount (like 'emptyDir') so the container can still write temporary files.
Dropping and adding Linux capabilities using 'capabilities: drop: [ALL]' and 'capabilities: add: [NET_BIND_SERVICE]'.
Applying a Pod Security Standard to a namespace. You will need to edit a namespace YAML file and add the correct label to enforce a specific level (e.g., 'pod-security.kubernetes.io/enforce: baseline').
Common traps:
Forgetting that a container-level securityContext overrides a Pod-level securityContext. The exam will set a value at the Pod level (e.g., runAsUser: 2000) and then ask you to set a different value for one of the containers. You must know exactly where to put the override.
Mixing up the securityContext field for the whole Pod (spec.securityContext) with the one for a container (spec.containers[].securityContext). They are different YAML locations.
Adding 'hostNetwork' or 'hostPID' settings, which are blocked by Baseline and Restricted policies. The exam expects you to leave these out or set them to 'false'.
Not realising that 'readOnlyRootFilesystem' prevents the container from writing to its own filesystem. If you set this and the application needs to write logs, you must provide a volume.
Key definitions to memorise:
Security Context: A set of permission and privilege settings for a Pod or container.
Pod Security Standard (PSS): A built-in collection of policies (Privileged, Baseline, Restricted) to control Pod security.
Pod Security Admission Controller: The component that enforces PSS by checking Pod creation requests.
runAsUser: The UID the container's process uses.
readOnlyRootFilesystem: A setting that makes the container's disk read-only.
capabilities: Fine-grained Linux permissions, such as the ability to bind to a low port.
A Security Context is a per-Pod or per-container YAML block that defines the user ID, group ID, filesystem permissions, and Linux capabilities for the running process.
The 'runAsUser' field inside a securityContext specifies the numerical ID of the user the container's process will run as, which should almost always be a non-root ID.
Setting 'readOnlyRootFilesystem: true' forces the container to only read from its own disk, requiring you to mount a writable volume (like emptyDir) for any temporary file storage.
Pod Security Standards (PSS) are pre-defined policies (Privileged, Baseline, Restricted) enforced on a namespace using labels, not inside the Pod specification itself.
The 'Restricted' PSS level is the most secure and is the one the CKAD exam most commonly tests, requiring non-root users, read-only filesystems, and dropped capabilities.
You must drop all Linux capabilities with 'capabilities: drop: [ALL]' and then explicitly add back only the ones you need, following the principle of least privilege.
These come up on the exam all the time. Here's how to tell them apart.
Pod-Level SecurityContext
Applies as a default to all containers in the Pod
Defined at 'spec.securityContext' in the Pod YAML
Overridden by any container-level securityContext for that container
Container-Level SecurityContext
Applies only to the specific container it is defined in
Defined at 'spec.containers[].securityContext' in the container's YAML block
Overrides the Pod-level setting for that single container
Pod Security Standard (PSS)
Configured via simple namespace labels
Has only three levels: Privileged, Baseline, Restricted
Enforced by the built-in Pod Security Admission controller
PodSecurityPolicy (PSP - Deprecated)
Configured via a complex, separate CRD (Custom Resource Definition) YAML file
Had many customisable fields and was prone to misconfiguration
Removed in Kubernetes 1.25 and no longer tested on CKAD
readOnlyRootFilesystem: true
Container's own disk cannot be written to
Forces use of a volume (e.g., emptyDir) for temporary writes
Significantly reduces attack surface from malware writing files
readOnlyRootFilesystem: false (default)
Container can write to its own disk freely
No extra volume mount required for temporary data
Higher risk if an attacker gains access and modifies files
Drop ALL Capabilities
Removes all Linux capabilities from the container
Is the default secure starting point for most containers
Written as 'capabilities: drop: [ALL]'
Add Specific Capabilities
Adds back only one or two specific capabilities
Used after dropping all, e.g., 'capabilities: add: [NET_BIND_SERVICE]'
Written as 'capabilities: add: [CAP_NAME]'
Mistake
Setting a Security Context at the Pod level applies to all containers, and no container can override it.
Correct
A container-level securityContext will override the Pod-level securityContext for that specific container. The Pod-level acts as a default, but containers can make their own stricter or different choices.
Beginners think of Pod-level as a hard lock, but it is actually a default set of permissions that containers can further restrict or customise.
Mistake
If I set readOnlyRootFilesystem to true, the container cannot write any data anywhere.
Correct
It means the container's own filesystem is read-only. The container can still write to mounted volumes, such as an emptyDir or a persistent volume claim. You must mount a writable volume for temporary files.
People confuse the container's ephemeral storage with all storage. They do not yet understand that volumes are separate from the container's root filesystem.
Mistake
Pod Security Standards are applied inside the Pod spec, like a securityContext.
Correct
Pod Security Standards are applied as labels on the namespace, not on the Pod itself. The Pod's securityContext is the request; the namespace label is the rule that checks that request.
Learners see the word 'Pod' in the name and assume the configuration goes in the Pod YAML, but it actually goes on the namespace object.
Mistake
The 'Privileged' Pod Security Standard is the default if I do not add any label.
Correct
There is no default policy. If you do not add a label to the namespace, the Pod Security Admission Controller does not enforce any standard. It is not a default to Privileged; it is simply not enforced.
People expect a 'default deny' or 'default allow' system, but Kubernetes leaves it unconfigured, requiring explicit action.
Mistake
Dropping all capabilities with 'drop: [ALL]' makes every application break.
Correct
Most applications do not need any special Linux capabilities to function. Dropping all is the recommended secure default. You only add back specific capabilities like NET_BIND_SERVICE if the application genuinely needs them.
There is a common fear that Linux capabilities are essential for all software, but typical web applications, APIs, and databases run fine without them.
Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.
A Pod Security Context sets defaults for all containers in the Pod (e.g., a common user ID). A Container Security Context applies only to that specific container and overrides any Pod-level setting for that container.
It prevents the container's own filesystem from being written to. The container cannot create, modify, or delete files on its own disk. It can still write to any volumes that are mounted into the container.
No. The CKAD exam no longer tests PodSecurityPolicy. It has been replaced by Pod Security Standards (PSS), which are applied using namespace labels.
You add a label to the namespace metadata: 'pod-security.kubernetes.io/enforce: restricted'. You can also set 'audit' and 'warn' modes using similar labels.
If the 'enforce' mode is set, the Pod Security Admission Controller rejects the creation of the Pod and returns an error explaining the violation. If only 'warn' mode is set, the Pod is created but a warning is logged.
Yes. You first drop all with 'capabilities: drop: [ALL]' and then add specific ones like 'capabilities: add: [NET_BIND_SERVICE]'. This is the correct pattern for granting only the needed permissions.
You've finished Security Contexts and Pod Security Standards. Continue through the CKAD study guide to build a complete picture of the exam.
Done with this chapter?