Understanding Pod Security Standards

Pod Security Standards Overview

The PSP to Pod Security Standards migration was supposed to be simple. It wasn't. Half our legacy apps broke because they were running as root and nobody documented why. But compared to the YAML hell of Pod Security Policies, which got deprecated in K8s 1.21 and finally killed in 1.25, Pod Security Standards is actually a relief.

Instead of writing custom PSP YAML files that nobody understood (we all copy-pasted from Stack Overflow), you get three options. Done. Pod Security Admission handles everything through namespace labels. Actually stable since 1.25 and built right into K8s, which is nice for once. Still need to configure it properly, but at least it exists without needing another third-party operator.

The Three Security Profiles

Privileged is basically "fuck it, do whatever you want" mode. Everything's allowed - privileged containers, host network access, hostPath volumes. Your kube-system namespace probably needs this because system pods are special snowflakes that need to touch everything.

Baseline blocks the obvious stupid shit while still being practical. No privileged containers, no host namespace sharing, no dangerous Linux capabilities. Most Helm charts from 2019 work with Baseline after you patch a few securityContext settings.

Restricted is where things get real. Non-root execution required, all capabilities dropped except NET_BIND_SERVICE, mandatory seccomp and AppArmor profiles. This breaks more things than you expect - DNS-based service discovery, init containers that write configs, monitoring agents that need special access. We had three apps that took weeks to fix because they assumed they could write to /tmp as root.

Implementation Through Pod Security Admission

Kubernetes API server request flow

Pod Security Admission is built into K8s now (finally stable in 1.25) but of course you still need to configure it. Three modes: enforce (kills pods that don't comply), audit (logs violations), and warn (shows warnings to kubectl users).

Start with audit and warn modes before enabling enforce - seriously, don't skip this step or you'll take down production. EKS, GKE, and AKS all support Pod Security Standards now, but the configuration varies enough to make you swear at your cloud provider.

Namespace-level labels control everything. Your kube-system namespace stays Privileged, production apps get Restricted, everything else gets Baseline. The error messages are useless - "violates PodSecurity restricted" is the most unhelpful error message in K8s. It doesn't tell you WHICH control failed, so you get to play guessing games.

PSA/PSS in a Kubernetes cluster with Namespace integration

Migration from Pod Security Policies

The migration from PSPs is like ripping off a Band-Aid that's been stuck for three years. Google's migration guide makes it sound easy - surprise, it's fucking not.

First, you audit your existing PSPs to see what they actually do. Most organizations discover they have 10 different PSPs that do basically the same thing, plus one snowflake policy for that legacy Java app that needs root access for "historical reasons" (nobody remembers what those reasons were).

The real timeline: Plan 2-3 months for a cluster with 100+ apps if you want to sleep at night. The policy change takes 5 minutes, fixing everything that breaks takes forever. Our first production cluster migration? Disaster. Found like 40-something apps running as root (maybe 47? stopped counting), a bunch that needed privileged containers because "legacy reasons" that nobody could explain, and one critical database backup script that just assumed it owned the entire filesystem. Version pinning seems smart until you're stuck on an old standard during cluster upgrades and can't figure out why your new deployments aren't starting. We learned this the hard way during a K8s 1.27 upgrade when half our apps wouldn't restart.

Security Profile Comparison

Security Control

Privileged

Baseline

Restricted

Privileged Containers

✅ Allowed

❌ Forbidden

❌ Forbidden

Host Namespaces

✅ Allowed

❌ Forbidden

❌ Forbidden

Host Ports

✅ Allowed

❌ Forbidden

❌ Forbidden

HostPath Volumes

✅ Allowed

❌ Forbidden

❌ Forbidden

Linux Capabilities

✅ All allowed

⚠️ Limited set allowed

❌ Must drop ALL, only NET_BIND_SERVICE

Privilege Escalation

✅ Allowed

✅ Allowed

❌ Forbidden

Root User (UID 0)

✅ Allowed

✅ Allowed

❌ Forbidden

Non-root Required

❌ Optional

❌ Optional

✅ Required

Seccomp Profile

✅ Any/None

⚠️ Not Unconfined

✅ RuntimeDefault/Localhost

AppArmor Profile

✅ Any/None

⚠️ RuntimeDefault/Localhost

✅ RuntimeDefault/Localhost

SELinux Options

✅ Any

⚠️ Limited types

✅ Limited types

Volume Types

✅ All allowed

✅ Most allowed

⚠️ Safe types only

Sysctls

✅ All allowed

⚠️ Safe subset only

⚠️ Safe subset only

Windows HostProcess

✅ Allowed

❌ Forbidden

❌ Forbidden

Implementation and Configuration

Pod Security Standards Architecture

Pod Security Standards work through namespace labels that tell the admission controller what to do. Simple concept, fucking annoying in practice when you've got 50 namespaces that all need different settings.

Namespace Configuration

Three namespace labels per profile. Copy this and adjust to taste:

apiVersion: v1
kind: Namespace
metadata:
  name: production-apps
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/audit: restricted  
    pod-security.kubernetes.io/warn: restricted
    pod-security.kubernetes.io/enforce-version: v1.29

Enforce kills pods that don't comply - use this carefully or you'll take down production wondering why nothing fucking starts. Audit logs violations to your audit logs (hope you're actually reading them). Warn shows kubectl users what's wrong - helpful for developers who don't read documentation anyway.

Version Pinning and Compatibility

Version pinning with the -version suffix sounds like a good idea until you realize you're pinned to like v1.24 standards during a K8s 1.29 upgrade and wondering why new security features aren't working. I spent two days debugging why our new seccomp profiles weren't applying before realizing we were still pinned to old standards. Felt pretty dumb about that one.

Without version pinning, you get the latest standards for your K8s version. This usually works fine unless you're upgrading across multiple K8s versions and something breaks. The compatibility matrix exists but reading it requires more coffee than most people have available.

Cluster-Level Configuration

Cluster-wide defaults through AdmissionConfiguration if you want to set policy once instead of labeling 47 namespaces individually:

apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: PodSecurity
  configuration:
    apiVersion: pod-security.admission.config.k8s.io/v1
    kind: PodSecurityConfiguration
    defaults:
      enforce: baseline
      audit: restricted
      warn: restricted
    exemptions:
      usernames: ["system:serviceaccounts:kube-system"]
      namespaces: ["kube-system", "kube-public"]

This sets baseline enforcement with restricted auditing everywhere except exempted namespaces. Your kube-system needs exemptions or system pods won't start and you'll wonder why your cluster is broken. Trust me on this one - I spent half a day debugging why our control plane wouldn't start after enabling Pod Security Standards. Not my finest moment.

Migration Strategies

Start with audit mode - seriously, don't fucking skip this. Enable audit and warn first, then spend a week reading logs to see what breaks. Audit logs are verbose garbage filled with every syscall and capability check, but good luck finding actual violations without grepping for hours. You'll be parsing JSON logs looking for "violates" while wondering why Kubernetes makes everything harder than it needs to be.

Namespace-by-namespace works if your teams don't hate each other. Dev namespaces get restricted first (devs love complaining about security changes), staging gets it next (where you discover what really breaks), production gets it last (after you fix everything twice).

Speaking of managed services - EKS users get the bonus of learning AWS-specific gotchas, like how ALB controller needs special permissions that nobody documents properly. Don't get me started on GKE Autopilot, which quietly enforces its own Pod Security standards that conflict with yours in subtle ways. And Azure? Azure CNI has its own networking quirks that break when seccomp profiles get too restrictive.

Automated checking sounds great until your CI/CD pipeline starts failing because that Helm chart you copied from the internet assumes root access. Polaris and Falco help but they'll find way too many violations you didn't know existed. Our first scan? Jesus, I think it was like 300+ issues spread across 80-something deployments. Most turned out to be false positives but sorting through that mess took over a week. Still have PTSD from that JSON output.

Integration with Security Tools

Pod Security Standards don't replace your existing security tools - they just add another layer to debug when things break. Network Policies still control traffic, RBAC still controls API access. Service meshes like Istio add even more security (and complexity).

Third-party engines like OPA Gatekeeper, Kyverno, and Kubewarden let you write custom policies on top of Pod Security Standards. Great for organizations that need more than three security profiles or love writing Rego policies that nobody can debug when they break. We tried Gatekeeper for six months before giving up - the learning curve is steeper than K8s itself and debugging policies feels like archeology.

When Things Break (They Will)

Troubleshooting and Debugging

Kubernetes Architecture Diagram

"violates PodSecurity restricted" is the most useless error message in K8s. It doesn't tell you which control failed. Use kubectl describe on the pod to see slightly more helpful information, or enable warn mode to get feedback during deployment. Still not great, but better than guessing.

Things that usually break with Restricted:

  • Prometheus node-exporter needs hostNetwork: true - took me like 4 hours to figure this out, docs don't really mention it
  • DNS-based service discovery containers often need NET_ADMIN capability - ours failed silently for days before we caught it
  • Legacy Java apps that write to /tmp as root - our Spring Boot apps all did this, took weeks to patch them all
  • Init containers that configure file permissions - most of ours broke, including cert-manager
  • Older sidecars from before 2020 - istio-proxy was a nightmare, ended up upgrading the entire mesh
  • That one Postgres backup script that assumed root access - broke our nightly backups for over a week
  • Fluent Bit logging agents need to read /var/log/containers as root - discovered this during a production incident, of course
  • NGINX Ingress Controller sidecars break if they can't bind to port 80 - obvious in hindsight, painful in reality
  • MySQL init containers that chown data directories - most Helm charts did this, broke pretty consistently

The nuclear option: kubectl delete namespace && kubectl create namespace clears Pod Security labels if you're desperate. Just remember to back up your configs first. I've had to do this twice when namespaces got into weird states during testing.

Frequently Asked Questions

Q

Why does everything break when I enable Restricted mode?

A

Because every app written before 2020 assumed it could run as root and write to /tmp. Restricted mode forces non-root execution, drops all Linux capabilities, and restricts volume types. Your monitoring agents, DNS tools, and legacy Java apps all hate this. We had like 20-something different apps that broke

  • maybe 25? Lost count after the 3rd day of fixing this crap.
Q

How long does migration actually take?

A

In our experience, plan 2-3 months for a cluster with 100+ apps if you want to sleep at night. The namespace labeling takes 5 minutes. Finding and fixing all the apps that break takes forever. Add another month if you're on a managed service like EKS or GKE because they each have special gotchas that'll make you question your career choices.

Q

What's the actual performance impact?

A

Pod startup adds maybe 50ms while the admission controller checks your pod against the standard. The real cost is developer time

  • expect to spend weeks debugging why pods won't start and fixing security

Context configurations in every deployment. Performance isn't the problem, your sanity is.

Q

Can I just ignore this and keep using Privileged everywhere?

A

Sure, if you enjoy explaining to auditors why your production cluster runs everything as root. Privileged mode is fine for system namespaces like kube-system, but running applications in Privileged defeats the point of having security standards. Your security team will eventually notice and you'll get to have that awkward conversation.

Q

How do I debug "violates PodSecurity restricted" errors?

A

The error message is intentionally useless. Enable warn mode on your namespace to get slightly better feedback. Use kubectl describe pod to see which security controls failed. Common culprits: running as root, missing securityContext, or trying to use hostPath volumes. Still not great, but better than guessing what broke this time.

Q

What breaks most often when migrating to Restricted?

A

Monitoring agents that need host access, init containers that write configs, legacy Java apps that assume root, and anything with privileged: true. DNS-based service discovery containers often need NET_ADMIN capabilities that Restricted blocks. Basically anything written before people cared about security.

Q

Do I need to restart existing pods after changing namespace labels?

A

No, running pods ignore label changes. Pod Security Standards only check new pods and pod updates. This is both a blessing (no downtime) and a curse (you need to restart everything manually to actually enforce the new standards). Kubernetes loves these gotchas.

Q

Why do Helm charts from 2019 break with Restricted mode?

A

Because nobody thought about security back then. Most Helm charts assumed privileged containers and root execution were perfectly fine. "Security? That's someone else's problem!" Modern charts include proper securityContext settings, but you'll be patching a lot of values.yaml files for legacy deployments that assumed the world was sunshine and rainbows.

Q

What's the real-world timeline for enabling Pod Security Standards?

A

Week 1: Enable audit mode, discover way more violations than you expected. Week 2-8: Fix applications one by one while developers complain about everything. Week 9-12: Fix the edge cases that only show up in production, because of course they do. Month 4: Finally enable enforce mode after you think everything works. Spoiler: it doesn't. Month 6: Realize you missed half the edge cases when your monitoring stack breaks during a routine update. Month 7: Discover more apps nobody told you about when they fail to restart after a node reboot. This happens every time.

Q

Are there any gotchas with managed Kubernetes services?

A

EKS has special handling for AWS Load Balancer Controller that nobody tells you about until stuff breaks. GKE Autopilot enforces some Pod Security controls by default (surprise!). AKS requires specific Azure CNI configurations for some security features to work correctly. Each cloud provider has their own special snowflake requirements that'll make you question why managed Kubernetes isn't actually easier.

Essential Resources

Related Tools & Recommendations

tool
Recommended

GKE Security That Actually Stops Attacks

Secure your GKE clusters without the security theater bullshit. Real configs that actually work when attackers hit your production cluster during lunch break.

Google Kubernetes Engine (GKE)
/tool/google-kubernetes-engine/security-best-practices
100%
tool
Recommended

Google Kubernetes Engine (GKE) - Google's Managed Kubernetes (That Actually Works Most of the Time)

Google runs your Kubernetes clusters so you don't wake up to etcd corruption at 3am. Costs way more than DIY but beats losing your weekend to cluster disasters.

Google Kubernetes Engine (GKE)
/tool/google-kubernetes-engine/overview
100%
tool
Recommended

Amazon EKS - Managed Kubernetes That Actually Works

Kubernetes without the 3am etcd debugging nightmares (but you'll pay $73/month for the privilege)

Amazon Elastic Kubernetes Service
/tool/amazon-eks/overview
100%
integration
Recommended

Falco + Prometheus + Grafana: The Only Security Stack That Doesn't Suck

Tired of burning $50k/month on security vendors that miss everything important? This combo actually catches the shit that matters.

Falco
/integration/falco-prometheus-grafana-security-monitoring/security-monitoring-integration
79%
tool
Recommended

Falco - Linux Security Monitoring That Actually Works

The only security monitoring tool that doesn't make you want to quit your job

Falco
/tool/falco/overview
79%
integration
Recommended

Making Pulumi, Kubernetes, Helm, and GitOps Actually Work Together

Stop fighting with YAML hell and infrastructure drift - here's how to manage everything through Git without losing your sanity

Pulumi
/integration/pulumi-kubernetes-helm-gitops/complete-workflow-integration
75%
troubleshoot
Recommended

CrashLoopBackOff Exit Code 1: When Your App Works Locally But Kubernetes Hates It

depends on Kubernetes

Kubernetes
/troubleshoot/kubernetes-crashloopbackoff-exit-code-1/exit-code-1-application-errors
75%
integration
Recommended

Temporal + Kubernetes + Redis: The Only Microservices Stack That Doesn't Hate You

Stop debugging distributed transactions at 3am like some kind of digital masochist

Temporal
/integration/temporal-kubernetes-redis-microservices/microservices-communication-architecture
75%
tool
Recommended

Open Policy Agent (OPA) - Policy Engine That Centralizes Your Authorization Hell

Stop hardcoding "if user.role == admin" across 47 microservices - ask OPA instead

open-policy-agent
/tool/open-policy-agent/overview
63%
tool
Popular choice

Sketch - Fast Mac Design Tool That Your Windows Teammates Will Hate

Fast on Mac, useless everywhere else

Sketch
/tool/sketch/overview
54%
news
Popular choice

Parallels Desktop 26: Actually Supports New macOS Day One

For once, Mac virtualization doesn't leave you hanging when Apple drops new OS

/news/2025-08-27/parallels-desktop-26-launch
52%
tool
Recommended

Red Hat OpenShift Container Platform - Enterprise Kubernetes That Actually Works

More expensive than vanilla K8s but way less painful to operate in production

Red Hat OpenShift Container Platform
/tool/openshift/overview
52%
tool
Popular choice

jQuery - The Library That Won't Die

Explore jQuery's enduring legacy, its impact on web development, and the key changes in jQuery 4.0. Understand its relevance for new projects in 2025.

jQuery
/tool/jquery/overview
50%
news
Popular choice

US Pulls Plug on Samsung and SK Hynix China Operations

Trump Administration Revokes Chip Equipment Waivers

Samsung Galaxy Devices
/news/2025-08-31/chip-war-escalation
47%
tool
Popular choice

Playwright - Fast and Reliable End-to-End Testing

Cross-browser testing with one API that actually works

Playwright
/tool/playwright/overview
45%
tool
Popular choice

Dask - Scale Python Workloads Without Rewriting Your Code

Discover Dask: the powerful library for scaling Python workloads. Learn what Dask is, why it's essential for large datasets, and how to tackle common production

Dask
/tool/dask/overview
43%
tool
Recommended

Shopify Polaris - Stop Building the Same Components Over and Over

similar to Shopify Polaris

Shopify Polaris
/tool/shopify-polaris/overview
42%
news
Popular choice

Microsoft Drops 111 Security Fixes Like It's Normal

BadSuccessor lets attackers own your entire AD domain - because of course it does

Technology News Aggregation
/news/2025-08-26/microsoft-patch-tuesday-august
40%
tool
Popular choice

Fix TaxAct When It Breaks at the Worst Possible Time

The 3am tax deadline debugging guide for login crashes, WebView2 errors, and all the shit that goes wrong when you need it to work

TaxAct
/tool/taxact/troubleshooting-guide
38%
news
Popular choice

Microsoft Windows 11 24H2 Update Causes SSD Failures - 2025-08-25

August 2025 Security Update Breaking Recovery Tools and Damaging Storage Devices

General Technology News
/news/2025-08-25/windows-11-24h2-ssd-issues
38%

Recommendations combine user behavior, content similarity, research intelligence, and SEO optimization