Article

Understanding Kubernetes Security Context: A Practical Guide

4 min read
Originally published on Medium. Read, clap or comment on Medium ↗

Kubernetes has become the de facto standard for container orchestration, but with great power comes great responsibility — especially when it comes to security. One of the most underutilized yet powerful security features in Kubernetes is Security Context. If you’ve ever felt uncertain about how to properly lock down your containers, you’re not alone. Today, we’re diving into this essential security mechanism that can transform your Kubernetes deployments from vulnerable to hardened.

What Is a Security Context, Anyway?

At its core, a security context defines privilege and access control settings for a Pod or Container. Think of it as the security rulebook that tells Kubernetes: “Here’s how this container should behave, and here are the restrictions I want to enforce.”

Security contexts allow you to control things like:

The beauty of security context is that it bridges the gap between “this container kind of works” and “this container is properly secured.” You’re not just making your deployment more secure — you’re making it more predictable and resilient.

Pod-Level vs Container-Level Security Context

Here’s where things get interesting: you can define security contexts at two levels.

Pod-level security contexts apply to all containers in a Pod. They’re the baseline rules that every container must follow. If you set runAsUser: 1000 at the Pod level, every container in that Pod will run as user 1000—unless overridden.

Container-level security contexts are more granular. They override Pod-level settings and allow you to fine-tune security for specific containers. This is particularly useful when you have init containers that might need different permissions than your main application container.

In practice, this means you can establish reasonable security defaults at the Pod level while still maintaining flexibility where you need it.

A Practical Example: From Unrestricted to Hardened

Let’s say you have a simple web application. Here’s what it might look like without security context:

apiVersion: v1
kind: Pod
metadata:
name: vulnerable-app
spec:
containers:
- name: app
image: my-app:latest
ports:
- containerPort: 8080

This container runs as root, has all Linux capabilities, can write to the filesystem, and could escalate privileges. Not ideal.

Now, let’s apply security hardening:

apiVersion: v1
kind: Pod
metadata:
name: hardened-app
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 3000
containers:
- name: app
image: my-app:latest
ports:
- containerPort: 8080
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {}

What changed? Suddenly, our container:

This single YAML change transforms your security posture dramatically.

The Essential Security Context Fields

runAsUser / runAsGroup — Specify which user/group runs the container process. Never run as root (0) unless absolutely necessary.

runAsNonRoot — A boolean that prevents the container from running as root. It’s a safeguard that fails fast if your image defaults to root.

fsGroup — Sets the group ID for volume ownership. Useful for ensuring containers can read/write to shared volumes.

allowPrivilegeEscalation — Prevents containers from gaining more privileges than their parent process. Set to false for most workloads.

readOnlyRootFilesystem — Makes the root filesystem read-only. Forces applications to be explicit about where they write data.

capabilities — Fine-grained control over Linux kernel capabilities. Usually, you want to drop ALL and selectively add back what you need.

seccompProfile — Confines syscalls available to the container. Works in tandem with other security measures.

Common Pitfalls to Avoid

Pitfall #1: Assuming your image works with non-root — Many containerized applications assume they’re running as root. Before enforcing runAsNonRoot: true, actually test your image with a non-root user.

Pitfall #2: Using privileged: true as the default - Privileged containers bypass most security measures. Use them only for infrastructure components that absolutely need it (like CNI plugins).

Pitfall #3: Forgetting about temporary directories — If you enable readOnlyRootFilesystem: true, applications that need to write to /tmp will fail unless you mount an emptyDir volume there.

Pitfall #4: Ignoring container registry scanning — Security context protects against runtime attacks, but it doesn’t scan for vulnerable dependencies in your image. Combine security context with image scanning.

Security Context in Your Organization

Rolling out security context across your organization doesn’t happen overnight. Here’s a realistic approach:

Start with auditing. Use tools like kubesec or kubectl-who-can to understand your current security posture. Then, implement security policies gradually through Pod Security Policies or Pod Security Standards.

Many teams use a policy-as-code approach with tools like Kyverno or OPA/Gatekeeper to enforce reasonable security context defaults across all deployments. Instead of relying on individual developers to remember security best practices, automation ensures compliance.

The Bottom Line

Security context is one of the few Kubernetes features where the cost of implementation is low, but the security benefit is enormous. You’re not adding complex infrastructure; you’re just being explicit about the constraints your container should operate within.

Start small. Pick one deployment. Add reasonable security context constraints. Test it. Roll it out to others. Before you know it, your entire cluster runs with hardened containers that fail safely when something tries to exploit them.

Security in Kubernetes isn’t about perfect defense — it’s about making attacks progressively harder and less worthwhile. Security context is your first, best step in that direction.

Now go forth and harden those containers.

← All articles Discuss on Medium ↗