KubernetesLXII · Pod Security StandardsPod Security Standards
PSA labels and modes — enforcing PSS at admission
What you'll learn
- Configure the PSA labels on a namespace (enforce, audit, warn, version)
- Choose the right mode for each phase of a migration
- Use the version label to opt out of newer PSS rules
- Diagnose why a Pod is rejected and remediate
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 Admission (PSA) is the controller that enforces PSS at admission. It reads namespace labels and applies the corresponding profile. This lesson covers the labels, the three modes (enforce, audit, warn), the version label for opt-out, and the operational patterns.
The four labels
A namespace can carry four labels that control PSA:
| Label | Effect |
|---|---|
pod-security.kubernetes.io/enforce | Reject Pods that violate the profile |
pod-security.kubernetes.io/audit | Log violations to the audit log |
pod-security.kubernetes.io/warn | Produce a warning event |
pod-security.kubernetes.io/enforce-version | Version of the enforce profile |
The first three accept the same profile values:
privileged, baseline, restricted. The fourth
accepts a Kubernetes version (latest, 1.34).
apiVersion: v1
kind: Namespace
metadata:
name: prod
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: latest
The version label is the opt-out mechanism: a
namespace that cannot meet the latest restricted
profile pins to an older version.
The three modes
flowchart LR
A[Pod admission] --> B{Pod violates?}
B -->|yes| C{enforce mode}
B -->|no| D[Allow]
C -->|matches| E[Reject]
C -->|no match| F{audit mode}
F -->|matches| G[Log to audit]
G --> H{warn mode}
H -->|matches| I[Warning event]
I --> D
E --> J[Pod rejected]
Each mode is independent:
- Enforce: rejects the Pod with a 403 error. The error message lists the violations.
- Audit: logs the violation to the audit log at
ResponseCompletestage. The Pod is admitted. - Warn: produces a Kubernetes warning event. The Pod is admitted.
The three modes are cumulative: a Pod that violates
the audit profile but not the warn profile is
logged but not warned. A Pod that violates the
enforce profile is rejected.
The version label
The enforce-version label pins the enforce profile
to a specific Kubernetes version:
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: "1.32"
A namespace pinned to 1.32 uses the restricted
profile as defined in 1.32, even on a 1.34 cluster.
This is the opt-out for workloads that cannot meet
the latest restricted (because a new rule was
added).
flowchart LR
A[Newer rule] --> B{version pinned?}
B -->|yes| C[Use pinned profile]
B -->|no| D[Use latest profile]
C --> E[Existing workload passes]
D --> F[Existing workload fails]
The migration pattern
The migration from baseline (or no PSS) to
restricted:
warn: restricted. Surface violations as warnings. No Pods are rejected.audit: restricted. Capture violations in the audit log. SIEM rules can alert on the violations.- Fix the violations. Address each violation:
add
runAsNonRoot, switch toemptyDir, addseccompProfile, etc. enforce: restricted. Once violations are fixed, switch toenforce. Future violations are rejected.
# 1. Set warn
kubectl label ns prod pod-security.kubernetes.io/warn=restricted --overwrite
# 2. Set audit
kubectl label ns prod pod-security.kubernetes.io/audit=restricted --overwrite
# 3. Identify violations
kubectl get events -n prod --field-selector reason=FailedCreate
# 4. Fix the violations in the manifests
# 5. Set enforce
kubectl label ns prod pod-security.kubernetes.io/enforce=restricted --overwrite
Common failure modes
- A workload is rejected. The error message lists the violated fields. The fix is to update the manifest to meet the profile.
- A namespace is implicitly
privileged. The namespace has no PSA labels. The fix is to addenforce: restrictedat creation. - The version label is wrong. A namespace pinned
to
1.32on a1.34cluster does not enforce the new rules. The fix is to update the version (after fixing the violations) or to remove the label. - The namespace label is changed. A misclick
changes
enforce: restrictedtoenforce: privileged. The fix is RBAC to restrict namespace updates to cluster-admin.
Diagnosing rejections
When a Pod is rejected, the API server returns a 403 with the violated fields:
Error from server (Forbidden): error when creating "pod.yaml":
pods "api" is forbidden: violates PodSecurity "restricted:latest":
allowPrivilegeEscalation != false (container "api" must set
securityContext.allowPrivilegeEscalation to false),
unrestricted capabilities (container "api" must set
securityContext.capabilities.drop to ["ALL"]),
seccompProfile (pod or container "api" must set
securityContext.seccompProfile.type to "RuntimeDefault" or "Localhost")
The error message lists every violation. The fix is to address each one in the manifest.
Production patterns
restrictedfrom creation. Every new namespace is created withenforce: restricted,audit: restricted,warn: restricted.- Migration per-namespace. Existing namespaces
migrate via
warn → audit → enforce. - Version pinning for exceptions. A namespace
that genuinely cannot meet the latest
restrictedpins to an older version with a documented deadline. - Quarterly audit. Review every namespace’s PSA
labels; verify no namespace is implicitly
privileged.
Cross-course references
- The Observability course covers the audit log entries for PSS violations.
- The Linux course covers the kernel features that PSS enforces.
Quiz
Knowledge check · 4 questions
Q1. What is the difference between the `audit`, `warn`, and `enforce` modes?
Q2. The `enforce-version` label can be used to opt a namespace out of newer PSS rules without removing the `enforce` label.
Q3. Your team is migrating the `prod` namespace from `enforce: baseline` to `enforce: restricted`. Walk the migration steps.
The `prod` namespace has been on `baseline` for a year. The workloads run as root and use `hostPath` for cache mounts. The migration to `restricted` requires removing root and replacing `hostPath`.
Q4. Describe the three-step migration from no PSS to `enforce: restricted`.
Passing score: 75%. Answers are checked in this browser.
Production discipline
PSA labels are the operational control surface for
PSS. A defensible PSS programme sets
enforce: restricted on every production namespace,
uses audit: restricted and warn: restricted for
visibility, migrates per-namespace via
warn → audit → enforce, and pins
enforce-version only for documented exceptions.
The audit log records every violation; the SIEM
alerts on the violations. A cluster whose namespaces
are mostly restricted with documented exceptions
has a PSS programme that is auditable.