Pod Security Admission Is the Official Path to Retire PodSecurityPolicy in Kubernetes
PodSecurityPolicy has been deprecated by Kubernetes, but many clusters still run without any security admission control in its place. The official documentation details how Pod Security Admission solves this per namespace, without requiring an external webhook.
PodSecurityPolicy has been deprecated by Kubernetes, but many clusters still run without any security admission control in its place. The official documentation details how Pod Security Admission solves this per namespace, without requiring an external webhook.
PodSecurityPolicy (PSP) was deprecated by the Kubernetes project in favor of a native replacement. Since then, any cluster that hasn't migrated to a replacement has been running without any security admission control over privileged containers, hostPath, hostNetwork, or privilege escalation. This isn't theoretical: it's the difference between a compromised pod being contained or turning into root access to the node.
The project's official answer is Pod Security Admission (PSA), stable since version 1.25 and described in detail in the Kubernetes documentation. Unlike PSP, which required a global PodSecurityPolicy and complex RBAC to bind policy to users, PSA applies the Pod Security Standards directly per namespace, via label. There's nothing to install: the admission controller already ships built into kube-apiserver.
The Three Levels and How They Apply
PSA works with three profiles defined by the Pod Security Standards:
- privileged: no restriction, equivalent to having no policy at all.
- baseline: blocks known escalations (privileged containers,
hostNetwork,hostPID, dangerous capabilities), but doesn't require fine-grained hardening. - restricted: applies hardening best practices, including
runAsNonRoot, mandatoryseccompProfile, andallowPrivilegeEscalation: false.
The level choice isn't binary per cluster: it's per namespace, and each namespace can combine all three enforcement modes at the same time.
The Three Modes: enforce, audit, warn
The Kubernetes documentation makes clear that level and mode are separate concepts. The mode decides what happens when a pod violates the chosen policy:
| Mode | Effect |
|---|---|
enforce | The pod is rejected at creation |
audit | The violation becomes an annotation in the audit log, but the pod is created |
warn | The user gets a warning in kubectl, but the pod is created |
This separation is what makes migration safe. Instead of applying restricted in enforce mode straight away and breaking every deploy that violates the policy, you can run warn and audit first, measure the real impact in the logs, and only then tighten enforce.
How to Configure Per Namespace
Configuration is done via a label on the Namespace object, in the format pod-security.kubernetes.io/<mode>: <level>. A production namespace in transition would look like this:
apiVersion: v1
kind: Namespace
metadata:
name: pagamentos
labels:
pod-security.kubernetes.io/enforce: baseline
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/audit: restrictedIn practice, this means: nothing below baseline gets through (privileged containers are actually blocked), but anything that would violate restricted generates a warning and goes into the audit log without breaking the deploy. This is the recommended intermediate state for anyone migrating from PSP: lock down the obvious, measure the rest.
The Detail That Breaks Deploys Without Warning
There's a documented gotcha that every platform team needs to know before tightening enforce: workloads like Deployment and Job get audit and warn, but they don't get enforce directly. enforce only acts on the final Pod object, created by the workload's controller.
In practice, this means a kubectl apply on a problematic Deployment tends to go through without an immediate error: the rejection only happens when the ReplicaSet tries to create the final Pod, not at the moment the Deployment is applied. So it's worth checking the events of the resulting Pod and ReplicaSet before assuming a stuck deploy has some other cause.
Versioning: Freezing the Policy Against New Kubernetes Versions
Another point PSP never handled well is policy stability across cluster upgrades. PSA has a specific label for this, pod-security.kubernetes.io/<mode>-version, which pins the level's definition to a specific minor version (for example, v1.28) instead of always following the latest one.
This matters because it's reasonable to assume the Pod Security Standards will keep evolving between minor releases, which makes it prudent not to always rely on the latest version without prior review. Without the version pin, a cluster upgrade can silently tighten restricted already in production and reject pods that used to pass. Pinning the version gives you control over when that bar moves, decoupling the Kubernetes upgrade cycle from the security policy review cycle.
Exemptions: When Something Legitimate Needs to Break the Rule
The documentation also provides for exemptions configured statically in the admission controller, along three dimensions: username, RuntimeClassName, or an entire namespace. It's the right mechanism to, for example, allow a monitoring operator that needs hostPID without lowering the level for the whole namespace.
One caution explicitly noted: exempting a controller service account (such as system:serviceaccount:kube-system:replicaset-controller) implicitly exempts any user who has permission to create the corresponding workload. This nullifies the policy for that entire resource, not just for the specific case that prompted the exemption.
Observability: Three Metrics to Track the Migration
kube-apiserver exposes three specific Prometheus metrics for this: pod_security_evaluations_total (how many policy evaluations ran), pod_security_exemptions_total (how many requests were exempted), and pod_security_errors_total (errors that prevented normal evaluation, which cause the controller to fall back to the latest restricted profile for safety).
Tracking pod_security_evaluations_total is how you measure, before swapping warn/audit for enforce, how many pods would actually violate the new policy. Without that number, tightening the lock is a gamble, not a decision.
Where It Doesn't Pay to Force restricted Right Away
restricted is the right level for new workloads and for services that already run without special privilege. But legacy workloads with hostPath for local logs, node agents that need hostNetwork, or backup jobs that mount a host volume rarely pass restricted without a rewrite. Forcing it all at once breaks exactly the kind of workload that most needs to stay up.
The safest path, for anyone still running PSP or no policy at all in production, is: baseline in enforce first (closes the serious privileged-container gap), restricted in warn/audit in parallel, and only promote namespace by namespace to enforce: restricted after zeroing out violations in the metrics. It's slower than a clean cut, but it's what separates a migration from an incident.
Source 1: Official Kubernetes Documentation, Pod Security Admission (https://kubernetes.io/docs/concepts/security/pod-security-admission/)
Pod Security Admission | Kubernetes
Pod Security Admission An overview of the Pod Security Admission Controller, which can enforce the Pod Security Standards. Feature state: Stable since Kubernetes v1.25 The Kubernetes Pod Security Standards define different isolation levels for Pods. These standards let you define how you want to restrict the behavior of pods in a clear, consistent fashion. Kubernetes offers a built-in Pod Security admission controller to enforce the Pod Security Standards.
Pod security restrictions are applied at the namespace level when pods are created. Built-in Pod Security admission enforcement This page is part of the documentation for Kubernetes v1.37. If you are running a different version of Kubernetes, consult the documentation for that release. Pod Security levels Pod Security admission places requirements on a Pod's Security Context and other related fields according to the three levels defined by the Pod Security Standards : privileged , baseline , and restricted .
Refer to the Pod Security Standards page for an in-depth look at those requirements. Pod Security Admission labels for namespaces Once the feature is enabled or the webhook is installed, you can configure namespaces to define the admission control mode you want to use for pod security in each namespace. Kubernetes defines a set of labels that you can set to define which of the predefined Pod Security Standard levels you want to use for a namespace.
The label you select defines what action the control plane takes if a potential violation is detected: Pod Security Admission modes Mode Description enforce Policy violations will cause the pod to be rejected. audit Policy violations will trigger the addition of an audit annotation to the event recorded in the audit log , but are otherwise allowed. warn Policy violations will trigger a user-facing warning, but are otherwise allowed. A namespace can configure any or all modes, or even set a different level for different modes. For each mode, there are two labels that determine the policy used: # The per-mode level label indicates which policy level to apply for the mode. # # MODE must be one of enforce, audit, or warn. # LEVEL must be one of privileged, baseline, or restricted. pod-security.kubernetes.io/ :
# Optional: per-mode version label that can be used to pin the policy to the # version that shipped with a given Kubernetes minor version (for example v1.37). # VERSION must be a valid Kubernetes minor version, or latest. pod-security.kubernetes.io/-version :
Check out Enforce Pod Security Standards with Namespace Labels to see example usage. Workload resources and Pod templates Pods are often created indirectly, by creating a workload object such as a Deployment or Job . The workload object defines a Pod template and a controller for the workload resource creates Pods based on that template. To help catch violations early, both the audit and warning modes are applied to the workload resources. However, enforce mode is not applied to workload resources, only to the resulting pod objects.
Exemptions You can define exemptions from pod security enforcement in order to allow the creation of pods that would have otherwise been prohibited due to the policy associated with a given namespace. Exemptions can be statically configured in the Admission Controller configuration . Exemptions must be explicitly enumerated. Requests meeting exemption criteria are ignored by the Admission Controller (all enforce , audit and warn behaviors are skipped). Exemption dimensions include: Usernames: requests from users with an exempt authenticated (or impersonated) username are ignored.
RuntimeClassNames: pods and workload resources specifying an exempt runtime class name are Namespaces: pods and workload resources in an exempt namespace are ignored. Caution: Most pods are created by a controller in response to a workload resource , meaning that exempting an end user will only exempt them from enforcement when creating pods directly, but not when creating a workload resource. Controller service accounts (such as system:serviceaccount:kube-system:replicaset-controller ) should generally not be exempted, as doing so would implicitly exempt any user that can create the corresponding workload resource.
Updates to the following pod fields are exempt from policy checks, meaning that if a pod update request only changes these fields, it will not be denied even if the pod is in violation of the current policy level: Any metadata updates except changes to the seccomp or AppArmor annotations: seccomp.security.alpha.kubernetes.io/pod (deprecated) container.seccomp.security.alpha.kubernetes.io/ (deprecated) container.apparmor.security.beta.kubernetes.io/ (deprecated) Valid updates to .spec.activeDeadlineSeconds Valid updates to .spec.tolerations Metrics Here are the Prometheus metrics exposed by kube-apiserver: pod_security_errors_total : This metric indicates the number of errors preventing normal evaluation.
Non-fatal errors may result in the latest restricted profile being used for enforcement. pod_security_evaluations_total : This metric indicates the number of policy evaluations that have occurred, not counting ignored or exempt requests during exporting. pod_security_exemptions_total : This metric indicates the number of exempt requests, not counting ignored or out of scope requests.
What's next Pod Security Standards Enforcing Pod Security Standards Enforce Pod Security Standards by Configuring the Built-in Admission Controller Enforce Pod Security Standards with Namespace Labels If you are running an older version of Kubernetes and want to upgrade to a version of Kubernetes that does not include PodSecurityPolicies, read migrate from PodSecurityPolicy to the Built-In PodSecurity Admission Controller . Feedback Was this page helpful?
Yes No Thanks for the feedback. If you have a specific, answerable question about how to use Kubernetes, ask it on Stack Overflow . Open an issue in the GitHub Repository if you want to report a problem or suggest an improvement . Last modified March 07, 2024 at 4:54 PM PST: AppArmor v1.30 docs update (4f11f83a45)
Translated from the Brazilian Portuguese original · Read the original
Amazon EventBridge gets a single bus for multiple accounts, but it's not yet available in Brazil
AWS has launched an enhanced version of EventBridge's custom event bus, with guaranteed ordering, a single subscription resource, and a new pricing model. The São Paulo region is left out of the initial list.