# Security Contexts and Pod Security Standards

> Chapter 11 of the Courseiva CNCF-CKAD curriculum — https://courseiva.com/learn/cncf-ckad/security-contexts-and-pod-security

**Official objective:** 5.2 — Apply security contexts and pod security policies to control access

## Introduction

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.

## The Shared Office Kitchen Analogy

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.

## Core explanation

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.

## Real-world context

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.

## Exam focus

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.

## Step by step

1. **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.
2. **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.
3. **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.
4. **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'.
5. **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.
6. **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.

## Comparisons

### Pod-Level SecurityContext vs Container-Level SecurityContext

**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) vs PodSecurityPolicy (PSP - Deprecated)

**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 vs readOnlyRootFilesystem: false (default)

**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 vs Add Specific Capabilities

**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]'

## Diagram

_This flowchart shows how the Pod Security Admission Controller checks a new Pod's Security Context against the Pod Security Standard label on the namespace before allowing it to run._

```mermaid
flowchart TD
    A[User submits Pod YAML] --> B[Pod Security Admission Controller]
    B --> C{Check namespace label?}
    C -->|No label| D[Pod created without PSS check]
    C -->|Label exists| E[Compare Pod securityContext to policy level]
    E -->|Meets policy| F[Pod created]
    E -->|Violates policy| G[Pod rejected with error]
    subgraph Namespace
        H[pod-security.kubernetes.io/enforce: restricted]
    end
    H --> B
```

## Common misconceptions

- **Misconception:** Setting a Security Context at the Pod level applies to all containers, and no container can override it. **Reality:** 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.)
- **Misconception:** If I set readOnlyRootFilesystem to true, the container cannot write any data anywhere. **Reality:** 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.)
- **Misconception:** Pod Security Standards are applied inside the Pod spec, like a securityContext. **Reality:** 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.)
- **Misconception:** The 'Privileged' Pod Security Standard is the default if I do not add any label. **Reality:** 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.)
- **Misconception:** Dropping all capabilities with 'drop: [ALL]' makes every application break. **Reality:** 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.)

## Key takeaways

- 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.

## FAQ

**What is the difference between a Pod Security Context and a Container Security Context?**

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.

**What does 'readOnlyRootFilesystem: true' actually prevent?**

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.

**Do I need to write YAML for PodSecurityPolicy (PSP) for the CKAD exam?**

No. The CKAD exam no longer tests PodSecurityPolicy. It has been replaced by Pod Security Standards (PSS), which are applied using namespace labels.

**How do I set the Pod Security Standard to 'Restricted' on a namespace?**

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.

**What happens if my Pod's Security Context violates the namespace's Pod Security Standard?**

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.

**Can I add a specific Linux capability back after dropping all of them?**

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.

## Check your understanding

1. **What YAML field would you add to a container to make its filesystem read-only?**

   Answer: You add 'readOnlyRootFilesystem: true' inside the container's 'securityContext' block.

2. **How do you enforce the 'Restricted' Pod Security Standard on a namespace called 'test-ns'?**

   Answer: Edit the namespace and add the label 'pod-security.kubernetes.io/enforce: restricted' to its 'metadata.labels'.

3. **If you set 'runAsUser: 1000' at the Pod level, and 'runAsUser: 2000' at the container level, which UID does the container use?**

   Answer: The container uses UID 2000, because the container-level securityContext overrides the Pod-level setting for that specific container.

4. **What is the purpose of the 'capabilities: drop: [ALL]' setting?**

   Answer: It removes all Linux capabilities from the container, ensuring the process has no extra privileges beyond the basic ones for its user ID.

5. **Name two requirements of the 'Restricted' Pod Security Standard. **

   Answer: Running as a non-root user (runAsUser not 0) and setting a read-only root filesystem (readOnlyRootFilesystem: true) are two requirements of the Restricted standard.

---

Interactive version with quiz and diagrams: https://courseiva.com/learn/cncf-ckad/security-contexts-and-pod-security
