Implementing Pod Security Standards in Kubernetes: A Practical Guide

Introduction

Securing Kubernetes workloads is critical to prevent security breaches and container escapes. Kubernetes Pod Security Standards (PSS) provide a framework for defining and enforcing security settings for Pods at different levels—Privileged, Baseline, and Restricted.

In this guide, you’ll learn how to implement Pod Security Standards in a Kubernetes cluster while ensuring your applications run smoothly.Understanding Pod Security Standards (PSS)

Kubernetes defines three security levels for Pods:

  1. Privileged – No restrictions; full host access (Not recommended).
  2. Baseline – Reasonable defaults for running common applications.
  3. Restricted – Strictest policies for maximum security.

Goal: Implement Restricted policies where possible while ensuring apps run without breaking.

Step 1: Enabling Pod Security Admission (PSA)

Starting from Kubernetes v1.23, Pod Security Admission (PSA) replaces PodSecurityPolicies (PSP) to enforce PSS.

Check if PSA is Enabled

kubectl get ns --show-labels

If namespaces are not labeled with PSS, you must label them manually.

Step 2: Apply Pod Security Labels to Namespaces

Namespaces must be labeled to enforce a Pod Security Standard.

Baseline Policy (For Standard Applications)

kubectl label namespace default pod-security.kubernetes.io/enforce=baseline

Restricted Policy (For Maximum Security)

kubectl label namespace secure-apps pod-security.kubernetes.io/enforce=restricted

Verify Labels

kubectl get ns --show-labels

Step 3: Deploy Applications with Pod Security Standards

Example 1: Non-Root Container (Restricted Mode)

A properly secured Pod must not run as root. Here’s a compliant example:

apiVersion: v1
kind: Pod
metadata:
  name: secure-app
  namespace: secure-apps
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1001
    fsGroup: 1001
  containers:
    - name: app
      image: nginx:latest
      securityContext:
        allowPrivilegeEscalation: false
        capabilities:
          drop:
            - ALL
        readOnlyRootFilesystem: true
      volumeMounts:
        - mountPath: /data
          name: app-storage
  volumes:
    - name: app-storage
      emptyDir: {}
Click Here to Copy YAML

Why This Pod Is Secure?

  • Runs as a non-root user (runAsNonRoot: true)
  • No privilege escalation (allowPrivilegeEscalation: false)
  • All unnecessary Linux capabilities are dropped (capabilities.drop: ALL)
  • Uses a read-only root filesystem (readOnlyRootFilesystem: true)

Step 4: Prevent Non-Compliant Pods from Running

Test deploying a privileged Pod in the secure-apps namespace:

apiVersion: v1
kind: Pod
metadata:
  name: privileged-app
  namespace: secure-apps
spec:
  containers:
    - name: app
      image: nginx:latest
      securityContext:
        privileged: true
Click Here to Copy YAML

Expected Output

Error: pods "privileged-app" is forbidden: violates PodSecurity "restricted:latest"

Kubernetes blocks the Pod due to the privileged: true setting.Step 5: Audit and Warn Non-Compliant Pods (Optional)

Instead of enforcing policies immediately, you can audit violations first.

Audit Only:

kubectl label namespace dev-team pod-security.kubernetes.io/audit=restricted

Warn Before Deployment:

kubectl label namespace dev-team pod-security.kubernetes.io/warn=restricted

Now, users get warnings instead of immediate rejections.Step 6: Verify Security Policies

Check PSA Enforcement Logs

kubectl describe pod secure-app -n secure-apps

Test Pod Security Admission

kubectl run test-pod --image=nginx --namespace=secure-apps

If the Pod violates security rules, Kubernetes will block it.

Conclusion

✅ You implemented Kubernetes Pod Security Standards
✅ Pods now run with minimal privileges
✅ Security policies are enforced while maintaining functionality

How do you implement PSS? Let’s discuss best practices in the comments!👇

Leave a comment