Skip to main content
< All Topics

Kubernetes Pod Security Contexts

The Gatekeeper of Your Cluster’s Safety

Kubernetes Security Context is simply that list of rules. It tells the container: “You can run, but only with these permissions, as this user, and don’t touch those system files.” It is the bridge between Kubernetes orchestration and the underlying Linux operating system security. Without this, your containers might default to having “Root” access, which is a major security risk!

Easy Remember Cheat Sheet
  1. “Container rules beat Pod rules.” (If a container says ‘I am root’, the Pod setting doesn’t matter).
  2. “Root is bad, User 1000 is good.” (Always try to run as a non-root user).
  3. “Drop ALL, Add what’s needed.” (Remove all Linux capabilities first, then add back only the essentials).
  4. “Read-only is safer.” (If hackers can’t write to your file system, they can’t hide malware there).
  5. “fsGroup handles the storage permission.” (It makes sure your shared volumes are readable by your user).
  • Granularity: Can be set for the whole Pod or just one Container.
  • Inheritance: Pod settings apply to all containers unless overridden.
  • Kernel Level: These settings talk directly to the Linux Kernel capabilities.
  • Enforcement: Helps pass security audits and standards like NSA/CISA hardening.
FeaturePod Level?Container Level?What it does
runAsUser✅ Yes✅ Yes (Overrides Pod)Decides which User ID runs the process.
fsGroup✅ Yes❌ NoOwns the shared storage volumes so you can read/write.
seccomp✅ Yes✅ YesRestricts which system calls (kernel requests) are allowed.
capabilities❌ No✅ YesGrants specific superpowers (like changing system time).
readOnlyRootFilesystem❌ No✅ YesLocks the file system so no one can edit files.

LevelYAML PathScope
Podspec.securityContextApplies to all containers in the Pod (and some volume settings).
Containerspec.containers[].securityContextApplies only to that specific container. Overrides Pod-level settings if they conflict.

The “Non-Root” Duo

By default, containers often run as root. If a hacker escapes the container, they have root access to your Node.

  • runAsUser: Forces the process to run with a specific UID (e.g., 1000).
  • runAsNonRoot: true: The Kubelet will validate the image at runtime; if it tries to run as UID 0 (root), the Pod will fail to start.
  • If you are running Windows nodes, runAsUserName is used instead, and the logic is quite different.

Privilege Escalation

  • allowPrivilegeEscalation: false: This prevents a process from gaining more privileges than its parent process (e.g., via setuid binaries). This is a “must-have” for any secure production environment.

File System Hardening

  • readOnlyRootFilesystem: true: This turns the container’s root filesystem into a read-only “brick.” If an attacker gains access, they can’t install tools or modify system files.
    • Set this to true. This makes the container’s disk “Read Only.”
    • Why? If a hacker gets into your container, they usually want to download a script or modify a binary. If the disk is read-only, they fail.
    • Practical Issue: Apps need to write logs or temp files.
    • Fix: Mount an emptyDir volume to /tmp or /var/log. This gives them a small scratchpad to write on without exposing the whole system.
  • fsGroup: (Pod level only) Defines a special group ID. Kubernetes will change the ownership of all volumes to this ID, allowing your non-root user to read/write to mounts without needing root.
    • When you mount a volume (like an AWS EBS or PVC), it might belong to root by default. Your poor application (running as User 1000) cannot write to it.
    • Solution: Set fsGroup: 2000 (or your group ID). Kubernetes will magically change the ownership of the files so your app can use them.
    • Performance Tip: If you have millions of small files, this “magical ownership change” takes time. Use fsGroupChangePolicy: "OnRootMismatch" to tell K8s: “Only fix permissions if they are actually wrong, otherwise don’t waste time checking every single file.”

Start small. Don’t try to implement everything at once or your app will crash.

  • Step 1: Just stop running as root. Use runAsUser: 1000.
  • Step 2: Use tools to scan your YAML files before you even deploy.
    • Tools:
      • Kubesec (Scans your YAML for security risks).
      • Trivy (Scans images and config files).

At the Architect level, you are not just setting rules; you are enforcing them across the whole cluster automatically.

  • Linux Capabilities: Defaults are too open.
    • Strategy: drop: ["ALL"]. Then add back only what is needed (e.g., NET_BIND_SERVICE if you need port 80).
  • Seccomp (Secure Computing Mode): This limits the “System Calls” (phone calls to the kernel).
    • Standard: Use RuntimeDefault. It blocks weird, dangerous calls that normal apps never use.
  • Privilege Escalation:
    • Set allowPrivilegeEscalation: false. This stops a process from using tools like sudo to gain more power than it started with.
  • Enforcement Tools:
Key Characteristics
  1. Discretionary Access Control (DAC): Based on User IDs (UID/GID).
  2. Mandatory Access Control (MAC): Hooks into SELinux or AppArmor for deeper locking.
  3. Kernel Isolation: Uses Linux Namespaces and Cgroups to keep processes apart.
Use Case
  • Banking Apps: Must ensure no data can be written to the root file system to comply with PCI-DSS.
  • Multi-tenant Clusters: Prevents one team’s “bad code” from accessing another team’s data or the host node.
Benefits
  • Reduced Attack Surface: Less “superpowers” means less damage if hacked.
  • Compliance: Meets standards like SOC2, ISO 27001, and HIPAA.
  • Stability: Prevents “noisy neighbor” containers from changing host settings that crash the node.
Limitations
  • Complexity: It is hard to know exactly which “Capability” an app needs. You might drop CHOWN and suddenly the app crashes on startup.
  • Legacy Apps: Old applications often assume they are running as root. Refactoring them to run as User 1000 can be a headache for developers.
Common Issues, Problems and Solutions
ProblemSymptomSolution
Permission DeniedApp crashes saying cannot open /var/log/app.logMount an emptyDir volume to that path or change runAsGroup/fsGroup.
CrashLoopBackOffApp starts and immediately dies with no logs.Check capabilities. You likely dropped a capability the app needs to start.
Root Mismatchcontainer has runAsNonRoot and image has non-numeric userChange your YAML to use runAsUser: 1000 (numbers) instead of a name.
Slow StartupPod takes 5 minutes to start “ContainerCreating”.You have a huge volume. Enable fsGroupChangePolicy: "OnRootMismatch".

https://kubernetes.io/docs/tasks/configure-pod-container/security-context/

https://kubernetes.io/docs/concepts/security/pod-security-standards/

Contents
Scroll to Top