Overview
Pod Security Policy (PSP) and Pod Security Admission (PSA) were introduced by the Kubernetes Auth Special Interest Group (SIG) to govern pod security in Kubernetes clusters.
Pod Security Policy (PSP) was deprecated in Kubernetes v1.21 and removed in v1.25. It is replaced by Pod Security Standards (PSS) combined with Pod Security Admission (PSA).
PSS profiles can be used with any PSA mode.
Pod Security Standards (PSS)
PSS defines three security profiles:
| Profile | Restrictiveness | Description |
|---|
| privileged | Unrestricted | Allows all capabilities and does not restrict any security context settings. Allows privilege escalation. Suitable for system-wide programs like logging agents and storage drivers. |
| baseline | Restricted | Restricts certain capabilities (e.g., hostPath, hostNetwork, hostIPC, hostPID) and encourages security context settings like readOnlyRootFilesystem and runAsNonRoot. Prevents known privilege escalations. Suitable for most workloads. |
| restricted | Highly restricted | Enforces strict security measures: disallows privilege escalation, requires runAsNonRoot, restricts host namespace and hostPath volume access. Follows pod hardening best practices. Suitable for high-security workloads. |
Pod Security Admission (PSA)
PSA is a built-in admission controller that enforces Pod Security Standards. It is enabled by default in Kubernetes v1.25 and later.
Verify it is enabled by checking the kube-apiserver arguments for PodSecurity in --enable-admission-plugins:
- kube-apiserver
- --enable-admission-plugins=NodeRestriction,PodSecurity
PSA has three enforcement modes:
| Mode | Description | On violation |
|---|
| enforce | Rejects pods that do not meet the policy | Pod is rejected |
| audit | Records violations in audit logs; pods are allowed to run | Recorded in audit logs |
| warn | Displays a warning to the user; pods are allowed to run | Warning message displayed |
PSA exemptions
You can configure exemptions so that specific users, runtime classes, or namespaces bypass Pod Security Admission enforcement entirely (all modes are skipped for exempted subjects).
| Exemption dimension | Description |
|---|
| Usernames | Requests from specified authenticated (or impersonated) usernames are ignored |
| RuntimeClassNames | Requests for pods with a specified RuntimeClass are ignored |
| Namespaces | Requests for pods in specified namespaces are ignored |
Configure the admission controller
Template
Example with exemptions
/etc/kubernetes/admission-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: PodSecurity
configuration:
apiVersion: pod-security.admission.config.k8s.io/v1
kind: PodSecurityConfiguration
defaults:
enforce: "privileged"
enforce-version: "latest"
audit: "privileged"
audit-version: "latest"
warn: "privileged"
warn-version: "latest"
exemptions:
usernames: []
runtimeClasses: []
namespaces: []
/etc/kubernetes/admission-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: AdmissionConfiguration
plugins:
- name: PodSecurity
configuration:
apiVersion: pod-security.admission.config.k8s.io/v1
kind: PodSecurityConfiguration
defaults:
enforce: "privileged"
enforce-version: "latest"
audit: "privileged"
audit-version: "latest"
warn: "privileged"
warn-version: "latest"
exemptions:
usernames: [admin-user, system:serviceaccount:kube-system:default]
runtimeClasses: [gvisor, kata-containers]
namespaces: [kube-system, monitoring]
Pass the configuration to kube-apiserver
- kube-apiserver
- --enable-admission-plugins=NodeRestriction,PodSecurity
- --admission-control-config-file=/etc/kubernetes/admission-config.yaml
Using PSS and PSA together
Label the namespace with a mode and profile
If no labels are set on a namespace, the default policy is privileged.
Changing namespace labels affects existing pods by re-evaluating them against the new policy and returning violations as warnings. Existing pods that violate an enforce policy will not be terminated, but new pods violating the policy will be rejected.
kubectl label namespace <ns> pod-security.kubernetes.io/<mode>=<profile>
# Examples
kubectl label namespace prod pod-security.kubernetes.io/enforce=restricted
kubectl label namespace dev pod-security.kubernetes.io/warn=baseline
# Apply multiple labels
kubectl label namespace staging \
pod-security.kubernetes.io/audit=baseline \
pod-security.kubernetes.io/warn=baseline
Create pods that comply with the namespace profile
Privileged
Baseline
Restricted
apiVersion: v1
kind: Pod
metadata:
name: privileged-pod
namespace: privileged-namespace
spec:
containers:
- name: privileged-container
image: nginx:latest
securityContext:
privileged: true
allowPrivilegeEscalation: true
capabilities:
add: ["ALL"]
Appropriate for workloads requiring full host access, such as system daemons or monitoring agents.apiVersion: v1
kind: Pod
metadata:
name: baseline-pod
namespace: baseline-namespace
spec:
containers:
- name: baseline-container
image: nginx:latest
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
Appropriate for most workloads such as web servers, application servers, or databases.apiVersion: v1
kind: Pod
metadata:
name: restricted-pod
namespace: restricted-namespace
spec:
containers:
- name: restricted-container
image: nginx:latest
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
runAsNonRoot: true
capabilities:
drop: ["ALL"]
Appropriate for sensitive applications requiring the highest level of security and isolation, such as financial, healthcare, or government applications.