KCSA — Pod Security Admission (PSA)

5 minute read

What Is Pod Security Admission?

Pod Security Admission (PSA) is the built-in Kubernetes admission controller that enforces Pod Security Standards (PSS). While PSS defines the security levels (Privileged, Baseline, Restricted), PSA is the mechanism that actually validates pods against those levels.

Key Point: PSS = the policy definition. PSA = the enforcement engine.

PSA operates at the namespace level — you apply PSA configuration to namespaces using labels, and all pods created in that namespace are evaluated against the configured PSS level.


The Three PSA Modes

PSA supports three modes that determine what happens when a pod violates the configured PSS level:

Mode Behavior Pod Created? Use Case
enforce Rejects non-compliant pods ❌ No Production enforcement
audit Logs violations to the audit log, allows pods ✅ Yes Monitoring compliance
warn Sends a warning to the user, allows pods ✅ Yes Migration and transition

Mode Details

  • enforce — The strictest mode. Non-compliant pods are rejected and will not be created. The user sees an error message explaining why.

  • audit — Violations are recorded in the Kubernetes audit log but the pod is allowed to run. This is useful for tracking how many workloads would break under a given PSS level without actually blocking them.

  • warn — The API server sends a warning header in the response. The user sees a warning message (e.g., in kubectl output) but the pod is allowed to run. This is ideal for educating developers about compliance issues.

Exam Tip: Only enforce mode actually prevents pods from being created. Both audit and warn allow the pod to run.


Namespace Labels for PSA

PSA is configured entirely through namespace labels. No CRDs, no webhook configurations — just labels.

Label Format

pod-security.kubernetes.io/<MODE>: <LEVEL>
pod-security.kubernetes.io/<MODE>-version: <VERSION>

Where:

  • <MODE> is enforce, audit, or warn
  • <LEVEL> is privileged, baseline, or restricted
  • <VERSION> is a Kubernetes minor version (e.g., v1.28) or latest

Full Label Reference

Label Purpose
pod-security.kubernetes.io/enforce PSS level to enforce (reject violations)
pod-security.kubernetes.io/enforce-version Kubernetes version for enforce policy
pod-security.kubernetes.io/audit PSS level to audit (log violations)
pod-security.kubernetes.io/audit-version Kubernetes version for audit policy
pod-security.kubernetes.io/warn PSS level to warn (show warnings)
pod-security.kubernetes.io/warn-version Kubernetes version for warn policy

YAML Examples

Namespace with Restricted Enforcement

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

This namespace will:

  • Reject any pod that does not meet the Restricted level
  • Log all violations to the audit log
  • Warn users about violations in kubectl output

Namespace with Baseline Enforcement

apiVersion: v1
kind: Namespace
metadata:
  name: development
  labels:
    pod-security.kubernetes.io/enforce: baseline
    pod-security.kubernetes.io/enforce-version: latest
    pod-security.kubernetes.io/warn: restricted
    pod-security.kubernetes.io/warn-version: latest

This namespace will:

  • Reject pods that violate the Baseline level
  • Warn users if their pods don’t meet the Restricted level (but still allow them)

This is a common pattern for gradually moving toward Restricted compliance.


Combining Modes — The Migration Strategy

One of the most powerful features of PSA is the ability to combine modes at different levels. This is the recommended approach for migrating to stricter security:

Mode Level Purpose
enforce baseline Block the most dangerous pods now
audit restricted Track what would break under Restricted
warn restricted Show developers what needs to change
apiVersion: v1
kind: Namespace
metadata:
  name: staging
  labels:
    pod-security.kubernetes.io/enforce: baseline
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted

Why this works:

  1. Dangerous pods (privileged, hostNetwork) are immediately blocked (enforce: baseline)
  2. The audit log captures every pod that wouldn’t pass Restricted (audit: restricted)
  3. Developers see warnings telling them exactly what to fix (warn: restricted)
  4. Once all warnings are resolved, you can upgrade enforce to restricted

Migration from PSP to PSA

If you’re migrating from PodSecurityPolicy to PSA, follow this 3-step process:

Step 1: Assess Current State

  • Identify all namespaces and their current PSP bindings
  • Determine which PSS level matches each namespace’s current PSP
  • Use audit and warn modes to test without breaking anything
# Add labels to test without enforcement
labels:
  pod-security.kubernetes.io/audit: baseline
  pod-security.kubernetes.io/warn: baseline

Step 2: Enable Enforcement Gradually

  • Start with enforce: baseline on non-critical namespaces
  • Monitor audit logs for violations
  • Fix workloads that fail Baseline compliance
  • Move to production namespaces
# Enable enforcement after testing
labels:
  pod-security.kubernetes.io/enforce: baseline
  pod-security.kubernetes.io/warn: restricted

Step 3: Tighten to Restricted

  • Once all Baseline violations are resolved, upgrade
  • Use warn: restricted first to identify remaining issues
  • Switch enforce to restricted when ready
# Final state for production
labels:
  pod-security.kubernetes.io/enforce: restricted
  pod-security.kubernetes.io/audit: restricted
  pod-security.kubernetes.io/warn: restricted

Exempt Namespaces

Some namespaces need to run privileged workloads and should be exempted from PSA enforcement.

Common Exemptions

Namespace Why It’s Exempted
kube-system Control plane components need host access
kube-node-lease Node heartbeat pods
kube-public Public cluster information

Configuring Exemptions

PSA exemptions are configured in the admission controller configuration file (typically /etc/kubernetes/psa/config.yaml on the API server):

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"
      enforce-version: "latest"
      audit: "restricted"
      audit-version: "latest"
      warn: "restricted"
      warn-version: "latest"
    exemptions:
      usernames: []
      runtimeClasses: []
      namespaces:
      - kube-system
      - kube-node-lease
      - kube-public

Note: Exemptions can be based on usernames, runtimeClasses, or namespaces. For the KCSA exam, focus on namespace-level exemptions.


PSA Behavior with Workload Controllers

An important nuance: PSA evaluates the pod template inside workload controllers (Deployments, DaemonSets, StatefulSets, etc.), not just standalone pods.

Action enforce Mode audit/warn Modes
Create a non-compliant Pod directly ❌ Rejected ✅ Allowed (with audit/warn)
Create a Deployment with non-compliant pod template ✅ Deployment created ✅ Allowed (with audit/warn)
Deployment tries to create a non-compliant Pod ❌ Pod rejected ✅ Allowed (with audit/warn)

Important: In enforce mode, a non-compliant Deployment is not rejected, but the pods it tries to create are. This means the Deployment will exist but have zero available replicas. The audit and warn modes catch this at Deployment creation time.


Verifying PSA Configuration

To check which PSA labels are set on a namespace:

kubectl get namespace production --show-labels

To see PSA warnings when creating a pod:

kubectl --dry-run=server -n production apply -f pod.yaml

The --dry-run=server flag sends the request to the API server for validation without actually creating the resource. You’ll see any PSA warnings in the output.


Common Misconceptions

Misconception Reality
“PSA requires installing a webhook” No — PSA is a built-in admission controller
“PSA is configured with CRDs” No — PSA uses namespace labels
“enforce mode blocks Deployments” No — it blocks the pods the Deployment tries to create
“You can only use one mode per namespace” No — you can combine all three modes at different levels
“PSA replaces OPA/Gatekeeper” Not necessarily — PSA handles standard policies; OPA handles custom policies

Key Takeaways for the Exam

  1. PSA is the enforcement mechanism for Pod Security Standards. It’s a built-in admission controller.

  2. Three modes: enforce (reject), audit (log), warn (warn). Only enforce blocks pods.

  3. PSA is configured through namespace labels — no CRDs or webhooks needed.

  4. Combine modes for gradual migration: enforce=baseline + warn=restricted is a common pattern.

  5. Exempt namespaces like kube-system that need privileged access.

  6. PSA evaluates pod templates in workload controllers during audit and warn, but only blocks actual pods in enforce mode.

  7. The version label (enforce-version: latest) controls which Kubernetes version’s PSS definition is used for evaluation.


Next: Security Contexts — the pod and container-level fields that implement security controls.

Updated: