KubernetesLXII · Pod Security StandardsPod Security Standards
Pod Security Standards — overview of the three profiles
What you'll learn
- Explain the three PSS profiles and what each one allows
- Distinguish PSS from PodSecurityPolicy (deprecated) and from OPA/Kyverno
- Identify the production pattern of enforcing `restricted` cluster-wide
- Recognise the failure modes (too-strict enforcement, too-loose audit)
Prerequisites
Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16
Pod Security Standards (PSS) is the built-in declarative policy for Pods. Three profiles — privileged, baseline, restricted — define what a Pod can do. This lesson covers what each profile allows, the relationship to deprecated alternatives (PodSecurityPolicy, PSP), and the production pattern.
The three profiles
The profiles are cumulative: restricted is a strict
subset of baseline, which is a strict subset of
privileged. A workload that passes restricted passes
baseline and privileged; a workload that fails
restricted may pass baseline.
| Profile | Purpose | Use case |
|---|---|---|
| Privileged | No restrictions | System workloads that need full access |
| Baseline | Prevents known privilege escalations | Untrusted code; multi-tenant clusters |
| Restricted | Minimum-allow | Trusted workloads; production |
flowchart LR
A[Privileged] --> B[Baseline]
B --> C[Restricted]
A -.any workload allowed.-> P[OK]
B -.most workloads allowed.-> P
C -.hardened workloads only.-> P
What each profile forbids
| Field | Privileged | Baseline | Restricted |
|---|---|---|---|
privileged | Allowed | Forbidden | Forbidden |
hostNetwork | Allowed | Forbidden | Forbidden |
hostPID | Allowed | Forbidden | Forbidden |
hostIPC | Allowed | Forbidden | Forbidden |
hostPath volumes | Allowed | Allowed (limited) | Forbidden |
capabilities | All | Limited | Drop ALL, add only NET_BIND_SERVICE |
runAsUser | Any | Any | Must not be 0 |
runAsNonRoot | Any | Any | Required true |
allowPrivilegeEscalation | Any | Any | Required false |
| Volume types | Any | Any | Only configMap, csi, downwardAPI, emptyDir, ephemeral, persistentVolumeClaim, projected, secret |
seccompProfile | Any | Any | RuntimeDefault or Localhost |
appArmorProfile | Any | Any | RuntimeDefault or Localhost |
The restricted profile is the production target; it
forbids every common privilege escalation path.
readOnlyRootFilesystem is deliberately absent from
this table. It is a valuable hardening setting, but it
is not part of baseline or restricted and the Pod
Security admission controller never checks it. If you
want it enforced, that is a job for a policy engine
such as Kyverno or Gatekeeper, not for a namespace
label.
Enforcement modes
PSS is enforced via the PodSecurity admission
controller, which is enabled by default in 1.34. The
controller reads namespace labels:
pod-security.kubernetes.io/enforce: privileged|baseline|restricted— the enforced profile. Pods that violate are rejected.pod-security.kubernetes.io/audit: privileged|baseline|restricted— the audit profile. Violations are logged in the audit log; Pods are not rejected.pod-security.kubernetes.io/warn: privileged|baseline|restricted— the warn profile. Violations produce a warning event; Pods are not rejected.
A namespace can have all three labels. A typical configuration:
metadata:
name: prod
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
All three modes use restricted. Violations are
rejected, logged, and warned.
Relationship to PodSecurityPolicy (PSP)
PSP was the predecessor to PSS, deprecated in 1.21 and removed in 1.25. The differences:
| Aspect | PSP | PSS |
|---|---|---|
| Configuration | Custom CRD | Built-in profiles |
| Order | Mutating | Validating (read-only) |
| Default | Cluster-wide | Per-namespace via labels |
| Expressiveness | Custom rules | Three fixed profiles |
PSS is the simpler, less expressive successor. Custom rules beyond PSS require OPA/Kyverno.
A privileged Pod (privileged profile)
A Pod that would pass privileged but fail restricted:
apiVersion: v1
kind: Pod
metadata:
name: legacy-app
namespace: legacy
spec:
containers:
- name: app
image: legacy:v1.0
securityContext:
privileged: true # privileged profile: OK
runAsUser: 0 # privileged: OK
volumeMounts:
- name: host-vol
mountPath: /host
volumes:
- name: host-vol
hostPath:
path: / # hostPath: privileged OK
The Pod is allowed in legacy (a namespace with
enforce: privileged); rejected in prod (with
enforce: restricted).
A baseline Pod (baseline profile)
A Pod that passes baseline but fails restricted:
apiVersion: v1
kind: Pod
metadata:
name: standard-app
namespace: standard
spec:
containers:
- name: app
image: standard:v1.0
securityContext:
runAsUser: 0 # baseline: allowed (UID 0)
capabilities:
add: ["SYS_ADMIN"] # baseline: limited; SYS_ADMIN may pass
The Pod is allowed in standard (enforce: baseline);
rejected in prod (enforce: restricted).
A restricted Pod (restricted profile)
A Pod that passes restricted:
apiVersion: v1
kind: Pod
metadata:
name: hardened-app
namespace: prod
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: myapp:v1.0
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
The Pod is allowed in prod (enforce: restricted).
Production patterns
restrictedcluster-wide. Every production namespace hasenforce: restricted. Exceptions (privileged,baseline) are explicit and documented.- Audit + warn + enforce. All three modes use
restricted; violations are rejected, logged, and warned. - Migration to
restricted. New namespaces userestrictedfrom creation; existing namespaces usewarnorauditfirst, then switch toenforce.
Production failure modes
privilegedis the default. A namespace was created withenforce: privileged(or no label); the cluster’s workloads run with full access. The fix is to setenforce: restricted.warninstead ofenforce. Violations are warned but allowed; the policy is advisory. The fix is to useenforce.- No
auditmode. Violations are not in the audit log; the SIEM does not see them. The fix is to useauditfor compliance. - Exceptions are not documented. A namespace
uses
privilegedbecause of a legacy workload; the team does not know about it. The fix is to document every exception.
Cross-course references
- The Observability course covers the audit log entries for PSS violations.
- The Linux course covers the kernel features (capabilities, seccomp, namespaces) that PSS enforces.
Quiz
Knowledge check · 4 questions
Q1. Which Pod Security Standards profile should production namespaces enforce by default?
Q2. Pod Security Standards (PSS) is the successor to PodSecurityPolicy (PSP), which was deprecated in 1.21 and removed in 1.25.
Q3. Your cluster has 80 namespaces, all with `pod-security.kubernetes.io/enforce: baseline`. The security team wants to enforce `restricted` cluster-wide. Walk the migration plan.
The cluster has 80 namespaces with `enforce: baseline`. Most workloads run as root (`runAsUser: 0`), use `hostPath` volumes, and have no `seccompProfile`. The team wants `restricted` but cannot break the workloads in one shot.
Q4. Name the three PSS modes (enforce, audit, warn) and what each one does.
Passing score: 75%. Answers are checked in this browser.
Production discipline
A defensible PSS programme enforces restricted in
every production namespace, with audit and warn
also set to restricted. Exceptions (privileged,
baseline) are explicit, documented, and reviewed
quarterly. The audit log records every violation; the
SIEM alerts on the violations. A cluster whose PSS
is restricted everywhere has a workload security
programme that is auditable; a cluster whose PSS is
privileged everywhere has a programme that is not.