Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 41

Pod and Container Security Contexts

Recommended resources

Hello! Welcome to the final lesson in our module on Kubernetes Security and Access Control.

In our previous lessons, we focused on securing interactions with the Kubernetes API server. You learned how to use ServiceAccounts to give Pods an identity and Roles and RoleBindings to grant them specific, namespace-scoped permissions. This is about controlling what a Pod can do to the cluster.

Today, we shift our focus from the cluster to the workload itself. We'll answer the question: "What can a process running inside a container do to the underlying host system?" This lesson directly addresses the learning outcome: Configure basic security contexts for Pods and containers.

As a Platform Engineer, this is a critical skill. You are responsible for the stability and security of the entire platform. Enforcing security contexts prevents applications from misbehaving, intentionally or not, and helps ensure that one tenant's compromised application cannot affect the entire node or cluster. This concept is analogous to the principle of least privilege you're familiar with from IAM, but applied at the operating system level for containerized processes.

1. The "Why": Understanding the Risks of Default Privileges

Many container images in public registries are configured to run their main process as the root user (UID 0). By default, Kubernetes will run them as such. A process running as root inside a container, while namespaced, still poses a significant security risk. If an attacker compromises the application, they gain root-level privileges within the container's context, making it much easier to attempt to "escape" the container and gain access to the host node's resources and kernel.

To understand why this is so critical, let's see a practical demonstration of the default, insecure behavior.

Harden Kubernetes cluster with pod and container security contexts

The article 'Harden Kubernetes cluster with pod and container security contexts' from the Earthly blog provides an excellent demonstration of the risks of running containers with their default (often root) privileges.

Read the section titled '1- Let’s Start the Demo by Clarifying the Risks Behind Running Apps with Default Configuration'. Pay attention to how kubectl exec and the id command reveal that the process is running as uid=0(root). The article also touches on the danger of setting privileged: true, which gives the container near-complete access to the host.


2. What is a Security Context?

To mitigate the risks we just discussed, Kubernetes provides the securityContext object. This object allows you to define privilege and access control settings for a Pod or an individual Container. It's your primary tool for hardening your workloads at the process level.

These settings are defined directly in your Pod manifest and can control a wide range of security-related kernel features.

Kubernetes SecurityContext Application
This diagram shows that a `SecurityContext` can be applied at the Pod level (affecting all containers within it) and also at the individual Container level (overriding Pod-level settings where they overlap).

The Kubernetes documentation provides a good summary of the areas a securityContext can influence.

Configure a Security Context for a Pod or Container

Let's turn to the official documentation to see the breadth of controls a security context offers.

Read the introductory section just before 'Before you begin'. This will give you a list of the various security settings you can control, such as User/Group ID, Linux Capabilities, and read-only filesystems. We will focus on the most common and impactful of these.

For a quick reference, the image below highlights some of the most essential settings, several of which we will explore in this lesson.

10 Kubernetes Security Context Settings You Should Understand
This image provides a great overview of some of the most common and important security context settings.

3. Configuring Pod-Level Security Contexts

The most common practice is to set a baseline security policy for all containers in a Pod. You do this by defining a securityContext block at the spec level of your Pod manifest.

Key fields at the Pod level include:

  • runAsUser: Specifies the User ID (UID) that all container processes will run as.
  • runAsGroup: Specifies the primary Group ID (GID) for all container processes.
  • runAsNonRoot: true: A crucial boolean flag. If set to true, the kubelet will validate that the container is not running as root (UID 0) before starting it. If the image tries to run as root, the Pod will fail to start.
  • fsGroup: Specifies a supplemental group ID that will own any volumes attached to the Pod. This is very important for making volumes writable by a non-root user.

Let's see how to apply these settings and verify their effect.

Harden Kubernetes cluster with pod and container security contexts

Now, let's apply a security context at the Pod level to enforce non-root execution and control file permissions. The Earthly article provides a step-by-step guide.

Read the section '2- Applying Security Contexts on Pod Level'. Follow the example where they define runAsUser, runAsGroup, and fsGroup. Pay close attention to the verification steps using id, ps, and creating files to check ownership. This clearly demonstrates how the settings are enforced.


4. Configuring Container-Level Security Contexts

While a Pod-level context is great for a baseline, you sometimes need to grant specific privileges to one container but not others in the same Pod (e.g., a sidecar that needs special permissions). You can do this by adding a securityContext block inside a specific container's definition.

The most important rule to remember is: Container-level settings override Pod-level settings.

In addition to runAsUser, common container-level settings include:

  • allowPrivilegeEscalation: false: Prevents a process from gaining more privileges than its parent. It's a best practice to always set this to false unless you have a very specific need.
  • readOnlyRootFilesystem: true: A powerful security measure that makes the container's root filesystem immutable. If an attacker gains access, they cannot write to the filesystem, install tools, or modify configurations. You would then mount writable emptyDir or PersistentVolumes for any paths that legitimately need to be written to.
  • capabilities: This allows you to use Linux Capabilities to grant a process a small subset of root's powers without giving it full root access. You can add or drop specific capabilities.

First, let's see the override mechanism in action.

Configure a Security Context for a Pod or Container

The official Kubernetes documentation clearly explains how container-level security contexts work and override Pod-level settings.

Read the section 'Set the security context for a Container'. The example clearly shows a Pod with runAsUser: 1000 and a Container with runAsUser: 2000. The verification with ps aux proves that the container-level setting takes precedence.

Now, let's look at how to use Linux Capabilities for fine-grained privilege management.

Configure a Security Context for a Pod or Container

Sometimes, a container needs specific root-level privileges. Linux capabilities allow you to grant these without giving full root access. For example, you might need NET_ADMIN to modify network interfaces, but nothing else.

Read the section 'Set capabilities for a Container'. This example demonstrates adding NET_ADMIN and SYS_TIME capabilities and shows how to verify their effect by inspecting the process status in /proc.

Test your understanding!

You have the following Pod manifest. The nginx image, by default, runs as root (UID 0).

apiVersion: v1
kind: Pod
metadata:
  name: security-test-pod
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1001
  containers:
  - name: nginx-container
    image: nginx:latest
  - name: sidecar-container
    image: busybox:1.28
    command: ["sleep", "3600"]
    securityContext:
      runAsUser: 2002
      allowPrivilegeEscalation: false
  1. What will happen when you try to apply this manifest? Why?
  2. Assuming you fix the issue from question 1, what User ID will the busybox process run as?
  3. What User ID will the nginx process run as?
Show answer
  1. The Pod will fail to start. The kubelet will see the Pod-level runAsNonRoot: true setting. It will then try to start the nginx-container, but since the nginx image wants to run as root (UID 0) and there is no container-level runAsUser to override this, the runAsNonRoot constraint is violated, and the Pod enters an error state.
  2. The busybox process will run as UID 2002. The container-level securityContext.runAsUser: 2002 overrides the Pod-level runAsUser: 1001.
  3. The nginx process will run as UID 1001. It inherits this setting from the Pod-level securityContext because it does not have its own runAsUser setting to override it.

Conclusion

You've now added another critical layer of security to your Kubernetes skill set. By mastering securityContext, you can enforce the principle of least privilege not just at the API level, but at the process and filesystem level, drastically reducing the attack surface of your applications.

Key Takeaways:

  • A securityContext defines privilege and access control settings for Pods and containers.
  • Always aim to run your containers as a non-root user. The easiest way to enforce this is with runAsNonRoot: true at the Pod level.
  • Use readOnlyRootFilesystem: true as a strong defensive measure and mount volumes for paths that require write access.
  • Set allowPrivilegeEscalation: false by default for all containers.
  • Apply general security policies at the Pod level and use Container-level contexts for specific exceptions and fine-tuning.

Next Up:
This lesson concludes our deep dive into core Kubernetes security concepts. You've learned how to manage identities (ServiceAccounts), control API access (RBAC), and harden your workloads (SecurityContexts). In the final lesson of this course, we will zoom out to see how these declarative YAML manifests fit into an automated, scalable workflow by discussing high-level approaches for integrating Kubernetes into CI/CD pipelines.