Implementing Pod Security Admission
1. Understanding Pod Security Standards
| Standard | Description | Enforcement Level | Key Controls |
|---|---|---|---|
| Privileged | Allows pods to run with full root privileges and access to host resources. | enforce |
Blocks privileged pods; requires securityContext.privileged: false |
| Baseline | Minimum level of security for all pods; prevents most common vulnerabilities. | enforce |
Requires allowPrivilegeEscalation: false, no host namespaces, and read-only root filesystems |
| Restricted | Most secure standard; restricts pod capabilities and configurations. | enforce |
Requires runAsNonRoot: true, no host namespaces, and strict resource limits |
Example: Applying Pod Security Standard
apiVersion: v1
kind: Pod
metadata:
name: example-pod
labels:
pod-security.kubernetes.io/enforce: restricted
spec:
containers:
- name: example-container
image: nginx
securityContext:
runAsNonRoot: true
allowPrivilegeEscalation: false
Note: Pod Security Admission is available in Kubernetes v1.23+ and requires the
PodSecurity admission controller to be enabled.
2. Using Pod Security Admission
| Policy | Description | Enforcement Level | Example |
|---|---|---|---|
| enforce | Denies pods that do not meet the policy requirements | NEW | |
| audit | Logs violations but allows pods to run | DEPRECATED | |
| warn | Logs violations and shows warnings but allows pods to run | NEW | |
Example: Enforcing Pod Security Admission
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: privileged
Note: The
pod-security.kubernetes.io/enforce label must be set on the namespace to enforce a policy.
Warning: Ensure that all pods in the namespace comply with the selected policy to avoid runtime issues.
3. Configuring Namespace Labels
| Label Key | Value | Description |
|---|---|---|
| pod-security.kubernetes.io/enforce | enforce |
Enforces the specified policy level for all pods in the namespace. |
| pod-security.kubernetes.io/enforce-version | v1.28 |
Specifies the version of the policy to enforce (default is latest stable). |
| pod-security.kubernetes.io/audit | audit |
Logs violations but does not block pods from being created. |
| pod-security.kubernetes.io/audit-version | v1.28 |
Specifies the version of the policy to audit (default is latest stable). |
| pod-security.kubernetes.io/warn | warn |
Generates warnings for policy violations but allows pods to be created. |
| pod-security.kubernetes.io/warn-version | v1.28 |
Specifies the version of the policy to warn about (default is latest stable). |
Example: Applying Pod Security Labels to a Namespace
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: enforce
pod-security.kubernetes.io/enforce-version: v1.28
pod-security.kubernetes.io/audit: audit
pod-security.kubernetes.io/audit-version: v1.28
pod-security.kubernetes.io/warn: warn
pod-security.kubernetes.io/warn-version: v1.28
Note: The
pod-security.kubernetes.io/enforce label must be set to enforce for the policy to take effect.
Warning: Ensure that all pods in the namespace comply with the selected policy level to avoid admission rejections.
4. Setting Enforce Level
| Level | Description | Enforcement Behavior | Example Configuration |
|---|---|---|---|
| enforce | Enforces the policy and rejects pods that violate it. | NEW Blocks pod creation if policy is violated. | |
| audit | Logs policy violations but does not block pod creation. | Allows pods to be created but logs violations for review. | |
| warn | Warns about policy violations without blocking or logging. | Does not enforce or log; only displays warnings in logs. | |
Example: Enforce Level Configuration
apiVersion: v1
kind: Pod
metadata:
name: example-pod
annotations:
pod-security.kubernetes.io/enforce: "restricted"
spec:
containers:
- name: example-container
image: nginx
Note: The
enforce level is the most strict and should be used in production environments to ensure compliance with security policies.
5. Setting Audit Level
| Level | Description | Usage |
|---|---|---|
| None | No events are logged. | For environments where audit logging is not required. |
| Metadata | Logs the request metadata, such as user, group, and timestamp. | For basic compliance or debugging without sensitive data. |
| Request | Logs the request metadata and the request body (excluding sensitive fields). | For detailed tracking of API requests without full payload exposure. |
| RequestResponse | Logs the request metadata and both the request and response bodies (excluding sensitive fields). | For full audit trail including responses, useful for compliance and debugging. |
Example: Setting Audit Level in Kubernetes
apiVersion: audit.k8s.io/v1
kind: Policy
metadata:
name: example-policy
rules:
- level: RequestResponse
users: ["admin"]
resources:
- group: ""
resources: ["pods"]
6. Setting Warn Level
| Configuration | Value | Description |
|---|---|---|
| admission.config.k8s.io/warn | true |
Enables warning mode for Pod Security Admission |
| admission.config.k8s.io/enforce | false |
Disables enforcement mode for Pod Security Admission |
Example: Setting Warn Level in a Namespace
apiVersion: v1
kind: Namespace
metadata:
name: example-namespace
labels:
pod-security.kubernetes.io/enforce: "warn"
pod-security.kubernetes.io/warn: "warn"
Note: In warn mode, Pod Security Admission logs violations but does not reject pods.
7. Controlling Host Namespaces
| Field | Description | Values | Notes |
|---|---|---|---|
| hostPID | Controls whether pods can share the host PID namespace | true / false |
Defaults to false. Setting to true allows pods to see processes from the host |
| hostIPC | Controls whether pods can share the host IPC namespace | true / false |
Defaults to false. Setting to true allows pods to access host inter-process communication resources |
| hostNetwork | Controls whether pods can use the host network namespace | true / false |
Defaults to false. Setting to true allows pods to bind to host network interfaces |
Example: Setting hostNetwork to true in a Pod
apiVersion: v1
kind: Pod
metadata:
name: host-network-pod
spec:
hostNetwork: true
containers:
- name: nginx
image: nginx
Note: Enabling host namespaces increases security risks and should be avoided unless necessary for specific use cases like system-level monitoring or network services.
8. Restricting Volume Types
| Volume Type | Description | Security Considerations | Configuration |
|---|---|---|---|
| awsElasticBlockStore | Represents an EBS volume attached to the kubelet node. | Potential for data leakage if not properly secured or restricted. | volumeMounts: - name: ebs-volume mountPath: /data |
| azureDisk | Represents an Azure Disk volume. | Requires proper RBAC and access control to prevent unauthorized access. | volumes: - name: azure-disk azureDisk: diskName: my-disk |
| gcePersistentDisk | Represents a GCE PD mounted to the kubelet node. | Access control must be enforced via IAM roles and policies. | volumes: - name: gce-pd gcePersistentDisk: pdName: my-pd |
| nfs | Represents an NFS mount. | Requires secure network configuration and authentication to prevent data exposure. | volumes: - name: nfs-volume nfs: server: nfs-server |
| hostPath | Represents a directory on the host node's filesystem. | DEPRECATED - Can lead to privilege escalation and host filesystem exposure. | volumes: - name: host-path hostPath: path: /etc |
| emptyDir | Represents a temporary directory mounted to the pod. | Safe for use but should not be used for persistent storage or sensitive data. | volumes: - name: temp-dir emptyDir: {} |
Example: Restricting Volume Types in Pod Security Admission
apiVersion: v1
kind: Pod
metadata:
name: restricted-pod
spec:
containers:
- name: app-container
image: nginx
volumeMounts:
- name: temp-dir
mountPath: /app-data
volumes:
- name: temp-dir
emptyDir: {}
Note: The
hostPath volume type is often restricted due to its potential for privilege escalation and host filesystem access.
9. Configuring Allowed Capabilities
| Capability | Description | Allowed in PSP | Notes |
|---|---|---|---|
| NET_ADMIN | Modify network configuration | DEPRECATED | Replaced by NET_BIND_SERVICE in newer versions |
| NET_BIND_SERVICE | Bind to privileged ports (e.g., < 1024) | NEW | Used for binding to low ports in containers |
| SYS_ADMIN | Perform administrative operations | DEPRECATED | Can be replaced with more granular capabilities |
| SYS_CHROOT | Use chroot() system call | NEW | Allows changing root directory in container |
Example: Pod with Allowed Capabilities
apiVersion: v1
kind: Pod
metadata:
name: example-pod
spec:
containers:
- name: example-container
image: nginx
securityContext:
capabilities:
allow:
- NET_BIND_SERVICE
- SYS_CHROOT
10. Migrating from PodSecurityPolicy
Note: PodSecurityPolicy (PSP) was deprecated in Kubernetes 1.21 and removed in 1.25. Migrating to Pod Security Admission is essential for maintaining security policies.
| Feature | PodSecurityPolicy (PSP) | Pod Security Admission |
|---|---|---|
| Policy Enforcement | enforce, audit, warn |
enforce, audit, warn |
| Configuration | Cluster-wide via PodSecurityPolicy CRD |
Namespace-level via pod-security.kubernetes.io annotations |
| Policy Levels | privileged, restricted, baseline |
privileged, restricted, baseline |
Example: Migrating PSP to Pod Security Admission
# Old PSP Configuration
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: restricted
spec:
privileged: false
allowPrivilegeEscalation: false
defaultAllowPrivilegeEscalation: false
requiredDropCapabilities:
- ALL
volumes:
- 'emptyDir'
- 'configMap'
- 'secret'
hostNetwork: false
hostIPC: false
hostPID: false
runAsUser:
rule: 'MustRunAsNonRoot'
seLinux:
rule: 'RunAsAny'
supplementalGroups:
rule: 'MustRunAs'
ranges:
- min: 1
max: 65535
fsGroup:
rule: 'MustRunAs'
ranges:
- min: 1
max: 65535
readOnlyRootFilesystem: false
# New Pod Security Admission Configuration
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: latest
Migration Steps
- Review existing PSP policies and their enforcement levels.
- Define new Pod Security Admission policies using namespace labels or annotations.
- Update namespaces to apply the new policies via
pod-security.kubernetes.iolabels. - Validate that workloads comply with the new policies using
kubectlor admission logs. - Gradually migrate workloads to ensure compatibility with new policies.
Warning: Ensure that all namespaces are updated to use Pod Security Admission before removing PSP support from the cluster.