Kubernetes Pod Security Standards Explained
β Bibin Wilson
In this blog, we will look into a primer on PSS and PSA concepts, that will help you to implement them in your projects and meet the required security standards.
Why Prioritize Pod Security?
As Daniel J. Walsh said, βEven smart admins can make bad decisions.β
Here is the detailed blog about securing pods using SecurityContext by running non-root pods. However, this approach does not guarantee that developers or DevOps engineers will always ensure all pods are non-root.
The best solution is to enforce security in namespaces that fall under strict security compliance. This ensures that if anyone attempts to deploy a pod running as root, the request will be denied by the API server.
This approach acts as a proactive security measure rather than a reactive one.
To implement such a workflow, Kubernetes provides the following native mechanisms:
- Pod Security Standards (PSS): A set of predefined rules that outline security best practices for pods.
- Pod Security Admission (PSA): A built-in controller that enforces these rules within namespaces or cluster-wide.
Pod Security Standards (PSS)
Pod Security Standards are a set of three predefined rule sets (profiles) that come natively in the Kubernetes core. They are designed to replace Pod Security Policies (PSPs).
Let's understand each profile in detail.
1. Privileged:
This profile is basically unrestrictive. Meaning, if you set up this profile, you can deploy any Pod with privileged access to the host.
Now, you might ask, then what is the need for this profile?
The reason is, that every Kubernetes cluster will have namespaces where we run Pods that require administrative privileges
For example,
- The default
kube-public
andkube-system
namespaces are set to Privileged because pods in these namespaces often require host and elevated access. - Tools like service meshes, CNIs, CSI drivers, logging agents, and monitoring tools (e.g., Prometheus) may need access to host resources or elevated permissions to perform their tasks.
- Sometimes privileged access is also required for investigating cluster issues or performing low-level diagnostics. For example, debugging network traffic with tools like
tcpdump
2. Baseline:
This profile enforces moderate security.
For example, it does not allow pods to use parameters like allowPrivilegeEscalation
, hostPID
, or hostIPC
. Essentially, all host-level settings are disallowed in the Baseline profile.
However, it still allows containers to run as root.
3. Restricted
This is the most restrictive profile. It adheres to all standard pod hardening security best practices.
You cannot run containers as root, add capabilities, or perform host-level operations, etc.
Please visit the official PSS documentation to view the full list of restricted and allowed actions of each profile
Enforcing Pod Security Standards
To enforce these standards on a namespace, all you need to do is add standard labels to the namespace with the profile name.
For example, to apply the Baseline profile, the label would look like this:
pod-security.kubernetes.io/enforce: baseline
pod-security.kubernetes.io/audit: baseline
pod-security.kubernetes.io/warn: baseline
In the above labels, you can see three modes:
- enforce: It enforces the profiles, meaning it will deny requests that violate the profile rules.
- audit: It allows pods to be created even if they violate the rules but adds the violations to the cluster audit log.
- warn: It allows pods to be created but displays a warning message about the rule violations.
Note: The choice of mode depends on your project requirements. For instance, if you prefer to log violations without enforcing the rules, the audit mode is a suitable option.
Here is an example manifest that creates a secure-apps
namespace and adds the restricted profile to it.
apiVersion: v1
kind: Namespace
metadata:
name: secure-apps
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
If you deploy this manifest, it will create a secure-apps
namespace and add the labels related to the Baseline PSS, indicating that this namespace should follow the Baseline profile rules for all pod deployments.
Pod Security Admission
Now that the labels are added, there needs to be a mechanism to ensure pod requests comply with the profile requirements.
Pod Security Admission is the mechanism that enforces these standards.
It is a built-in admission controller that checks every pod creation request to validate if it meets the security requirements before allowing it to run. It uses namespace labels to determine the security level to enforce.
An admission controller in Kubernetes is a built-in process (piece of code) that intercepts API requests to enforce rules or modify objects before they are stored
I have enforced the Restricted PSS for the secure-apps
namespace in my cluster. Now, if I try to create the following Nginx pod with privilegeEscalation: true
, letβs see what happens.
For example.
apiVersion: v1
kind: Pod
metadata:
name: nginx
namespace: secure-apps
spec:
containers:
- name: app-container
image: nginx
imagePullPolicy: Always
ports:
- containerPort: 5000
securityContext:
allowPrivilegeEscalation: true
If I deploy the above pod manifest, Kubernetes will block the deployment and throw a "forbidden" error, as shown below.
$ kubectl apply -f root-pod.yaml
Error from server (Forbidden): error when creating "root-pod.yaml": pods "nginx" is forbidden: violates PodSecurity "restricted:latest": allowPrivilegeEscalation != false (container "app-container" must set securityContext.allowPrivilegeEscalation=false)
Now, if I want to enable only warnings without restricting the pod deployment, all I need to do is apply the warn mode restricted label as shown below.
pod-security.kubernetes.io/warn: restricted
After enabling the warn mode, if I deploy the same pod, it will display a warning message but still allow the pod to be deployed.
Here is the output showing both the warning message and the pod creation confirmation.
$ kubectl apply -f root-pod.yaml
Warning: would violate PodSecurity "restricted:latest": allowPrivilegeEscalation != false (container "app-container" must set securityContext.allowPrivilegeEscalation=false), unrestricted capabilities (container "app-container" must set securityContext.capabilities.drop=["ALL"])
.
.
pod/nginx created
$ kubectl get po -n secure-apps
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 7s
Cluster Level Pod Security Standards
As a cluster administrator, you can enable PSS at the namespace level based on project requirements and compliance needs.
But what if you want to apply predefined PSS at the cluster level, ensuring it gets applied to all namespaces by default?
Adding restrictive rules to the cluster by default is generally not a good idea. However, you can configure warn and audit modes cluster-wide to log all pod events related to pod security.
Kubernetes provides an AdmissionConfiguration
object, which can be added to the API server configuration to apply PSS at the cluster level.
Here is an example of an AdmissionConfiguration
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: "baseline"
enforce-version: "latest"
audit: "restricted"
audit-version: "latest"
warn: "restricted"
warn-version: "latest"
exemptions:
usernames: []
runtimeClasses: []
namespaces: [kube-system]
The AdmissionConfiguration
configuration needs to be added to the API server setup using extraArgs
, as highlighted below.
Adopting PSA in Existing Systems
What if you want to adopt PSS in existing clusters?
It should be done in a phased implementation.
For example,
- Performing manual or automated scan of your cluster to get an initial overview of the security posture.
- Involve application owners or teams early to ensure they are aware of upcoming changes and can collaborate in addressing violations.
- Start with Warn and Audit modes to identify issues without breaking workloads.
- Identify components needing privileges (e.g., storage drivers, monitoring tools).
- Map workloads to appropriate Pod Security Admission (PSA) profiles (e.g., Restricted, Baseline).
- Get workloads running with broader privileges.
- Incrementally enforce PSA on namespaces after fixing violations.
- Gradually reduce privileges to comply with tighter PSA profiles.
- Continuously test and monitor for issues.
Important Note: Test the enforcement of PSA profiles in a dev or non-production environment before rolling out changes cluster-wide.
Conclusion
Hope this blog sheds some light on PSS and PSA in Kubernetes.
If you have any questions about this blog, drop them in the comments!