Implementing Pod Security Admission in Kubernetes

Kubernetes offers a built-in Pod Security admission controller to enforce Pod Security Standards.

As Kubernetes continues to evolve as the de facto standard for container orchestration, securing pods—the smallest deployable units in Kubernetes—has become more critical than ever.

Misconfigured pods can open the door to privilege escalations, host access, and data breaches, making pod-level security a cornerstone of a secure Kubernetes deployment.

With the deprecation of PodSecurityPolicies (PSPs) in Kubernetes v1.21 and their removal in v1.25, the community needed a simpler, built-in alternative.

That’s where Pod Security Admission (PSA) comes in.

Introduced as a more user-friendly and namespace-centric replacement, PSA enables Kubernetes administrators to enforce predefined security standards—privileged, baseline, and restricted—without the complexity of custom policy definitions.

In this guide, we’ll walk you through everything you need to know to effectively implement Pod Security Admission in your Kubernetes clusters, including:

  • How PSA compares to the now-deprecated PSPs

  • Enforcing PSA policies across different namespaces

  • Best practices for staging and auditing PSA enforcement

  • Migration tips from PSPs to PSA

Whether you’re building secure-by-default environments from scratch or updating legacy clusters, this guide is for you.

✅ Related reading:

🔗 For further reference, check out:

Let’s dive into what makes Pod Security Admission the future of secure pod governance in Kubernetes.


What is Pod Security Admission?

Pod Security Admission (PSA) is a built-in Kubernetes admission controller introduced as a simplified, standards-based replacement for the now-deprecated PodSecurityPolicies (PSPs).

PSA was officially promoted to beta in Kubernetes v1.23 and became the default enforcement mechanism starting with v1.25.

Purpose and Function

At its core, Pod Security Admission is designed to enforce pod-level security standards at the namespace level.

Instead of writing and managing complex policy definitions, PSA uses three predefined policy levels based on Kubernetes’ security best practices:

  • Privileged – Unrestricted; allows all pod configurations

  • Baseline – Minimally restrictive; prevents known security risks

  • Restricted – Highly secure; follows least-privilege principles

These policies are enforced by assigning labels to namespaces, which tell Kubernetes whether to enforce, audit, or warn against pods that violate a given security level.

PSA in the Kubernetes Security Model

Pod Security Admission works alongside other Kubernetes security mechanisms like:

  • Role-Based Access Control (RBAC) – manages who can perform what actions

  • Network Policies – control communication between pods

  • Admission Webhooks – extend validation or mutation of resources

  • Security Contexts – define privileges and access control within pod specs

By integrating directly into the control plane, PSA allows cluster administrators to enforce standardized controls without relying on third-party tools or custom configurations.

Key Differences from PodSecurityPolicies

FeaturePodSecurityPolicies (PSP)Pod Security Admission (PSA)
Configuration complexityHigh (YAML-based policies)Low (namespace labels)
Enforcement levelCluster-wide via RBACNamespace-specific
Custom policy definitionsSupportedNot supported (uses built-in levels)
FlexibilityVery flexibleSimpler, opinionated defaults
Deprecated/SupportedRemoved in v1.25Supported and recommended

This shift simplifies the security story in Kubernetes by promoting easier onboarding, more predictable behavior, and safer defaults out of the box.

👉 Up next: PSA Modes Explained


PSA Modes Explained

The Pod Security Admission (PSA) controller offers three modes of enforcement—enforce, audit, and warn—giving Kubernetes administrators the flexibility to adopt security policies gradually and with minimal disruption.

1. Enforce Mode

  • What it does: Blocks the creation or modification of any pod that violates the assigned security level.

  • Behavior: If a pod spec fails validation against the configured policy level, it is rejected outright.

  • Use case: Production namespaces where only compliant workloads should be allowed.

bash

 

kubectl label namespace my-namespace \
pod-security.kubernetes.io/enforce=restricted \
pod-security.kubernetes.io/enforce-version=v1.25

✅ Use this when you’re confident your workloads meet the desired security level.

2. Audit Mode

  • What it does: Allows all pods to be created or modified, but logs violations for auditing purposes.

  • Behavior: Events are recorded in the audit logs, making it useful for tracking policy violations without blocking deployments.

  • Use case: Observing potential issues before enforcing policies cluster-wide.

bash
kubectl label namespace my-namespace \
pod-security.kubernetes.io/audit=baseline \
pod-security.kubernetes.io/audit-version=v1.25

🛠️ Ideal for pre-production environments and soft-rollout phases.

3. Warn Mode

  • What it does: Allows non-compliant pods but returns a warning message to the user.

  • Behavior: Users see warnings when using kubectl or the API, helping developers spot and address issues.

  • Use case: Educating teams about policy violations during development.

bash
kubectl label namespace my-namespace \
pod-security.kubernetes.io/warn=restricted \
pod-security.kubernetes.io/warn-version=v1.25

💡 Useful for dev environments to raise awareness without disruption.

Combining Modes

You can apply different modes simultaneously in a namespace to ease your transition strategy:

bash
kubectl label namespace dev \
pod-security.kubernetes.io/enforce=baseline \
pod-security.kubernetes.io/audit=restricted \
pod-security.kubernetes.io/warn=restricted

This configuration:

  • Enforces baseline level

  • Audits and warns against violations of the stricter restricted level

🧠 Learn more about namespace-level enforcement in our Implementing Pod Security Policies post.


PSA Security Levels

The Pod Security Admission (PSA) controller uses predefined security levelsPrivileged, Baseline, and Restricted—to enforce Kubernetes workload security standards.

Each level reflects a different balance between workload flexibility and security posture.

🔓 Privileged

  • Overview: No restrictions are enforced.

  • Use Case: Rarely recommended. Intended for system-level workloads or legacy applications that require full access to host resources.

  • Allowed Features:

    • Running as root

    • Privileged containers (securityContext.privileged: true)

    • Host networking and ports

    • Host path volumes

Allowed:

yaml
securityContext:
privileged: true
hostNetwork: true

🚫 Enforcement: None – all pod specs are accepted.

🔐 Baseline

  • Overview: Applies reasonable defaults to prevent known privilege escalation vectors while maintaining compatibility with most applications.

  • Use Case: Ideal starting point for application workloads that don’t require elevated privileges.

  • Restricted Features:

    • Privileged containers are denied

    • Host namespaces and networking are disallowed

    • capabilities must drop ALL, with few exceptions added

    • Dangerous volume types (e.g., hostPath) are disallowed

Allowed Example:

yaml
securityContext:
runAsNonRoot: true
capabilities:
drop: ["ALL"]

🚫 Denied Example:

yaml
volumes:
- name: host-volume
hostPath:
path: /var/log


🛡️ Restricted

  • Overview: Enforces the strictest security policies, requiring pods to be explicitly hardened.

  • Use Case: Recommended for sensitive workloads, multi-tenant environments, or any production-grade cluster aiming for compliance.

  • Additional Constraints:

    • Must define runAsNonRoot

    • Must use readOnlyRootFilesystem

    • Drops all Linux capabilities

    • Requires Seccomp and AppArmor profiles (where supported)

Allowed Example:

yaml
securityContext:
runAsNonRoot: true
readOnlyRootFilesystem: true
seccompProfile:
type: RuntimeDefault

🚫 Denied Example:

yaml
securityContext:
runAsUser: 0


Summary 

FeaturePrivilegedBaselineRestricted
Privileged containers
Host networking / PID / IPC
hostPath volumes
Must run as non-root⚠️
readOnlyRootFilesystem
Seccomp/AppArmor enforcement

📘 Want a deep dive on securing pods? Check out our Kubernetes Security Best Practices guide.


Enabling PSA on Your Cluster

Implementing Pod Security Admission (PSA) in your Kubernetes cluster is straightforward—especially compared to legacy PodSecurityPolicies.

Since PSA is a built-in feature in newer Kubernetes versions, it requires minimal setup and leverages namespace labels for configuration.

✅ Kubernetes Version Requirements

PSA was introduced in Kubernetes v1.23 as an alpha feature, became beta in v1.24, and is enabled by default in v1.25 and later.


There’s no need to enable an external admission controller—PSA is native and ready to use in modern Kubernetes distributions.

📌 Minimum Required Version: Kubernetes v1.23+
🚀 Recommended Version: v1.25+ (GA and fully supported)

🧠 How PSA Works

Instead of applying policies to pods directly, PSA uses labels on namespaces to determine how pods in that namespace should be handled.

These labels control:

  • The security level (Privileged, Baseline, or Restricted)

  • The mode of enforcement (Enforce, Audit, Warn)

🗂️ Namespace-Level Configuration

To enable PSA in a namespace, apply labels in the following format:

shell
kubectl label namespace <namespace> \
pod-security.kubernetes.io/enforce=restricted \
pod-security.kubernetes.io/enforce-version=latest \
pod-security.kubernetes.io/warn=baseline \
pod-security.kubernetes.io/warn-version=latest \
pod-security.kubernetes.io/audit=privileged \
pod-security.kubernetes.io/audit-version=latest

Explanation:

  • enforce: Blocks non-compliant pods (e.g., restricted)

  • warn: Shows warnings for pods that violate the given level (e.g., baseline)

  • audit: Logs non-compliance to audit backends (e.g., privileged)

  • *-version: Specifies the Kubernetes version of the Pod Security Standards

🔐 Want to enforce the strictest policy?

Use:

bash
kubectl label namespace production \
pod-security.kubernetes.io/enforce=restricted

🧪 Tip: Testing Before Enforcing

Start with warn or audit mode to identify potential issues without blocking deployments. Once validated, switch to enforce.


Step-by-Step: Implementing PSA

Now that you understand the basics of Pod Security Admission (PSA), let’s walk through how to actually implement it in your Kubernetes cluster.

This step-by-step guide will help you label namespaces, test enforcement behavior, and integrate PSA into your CI/CD workflows.

🏷️ Step 1: Label Namespaces with PSA Mode and Level

Start by choosing your desired security level (privileged, baseline, or restricted) and modes (enforce, warn, audit).

Then apply the appropriate labels to your namespace:

bash
kubectl label namespace dev \
pod-security.kubernetes.io/enforce=restricted \
pod-security.kubernetes.io/enforce-version=latest \
pod-security.kubernetes.io/warn=baseline \
pod-security.kubernetes.io/warn-version=latest

You can adjust levels and modes depending on your environment.

For example:

  • In production: Use restricted in enforce mode

  • In staging: Use baseline in enforce and restricted in warn

  • In dev: Use warn only for exploratory feedback

✅ Step 2: Test Pod Creation

Try to create a pod that violates your enforced policy:

yaml
# pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: privileged-pod
spec:
containers:
- name: nginx
image: nginx
securityContext:
privileged: true

Then run:

bash
kubectl apply -f pod.yaml --namespace=dev

Depending on your PSA settings:

  • enforce: The pod will be rejected

  • warn: A warning will appear

  • audit: Logs will record the violation

🔍 Tip: You can inspect namespace labels with:

bash
kubectl get ns dev --show-labels

🔁 Step 3: Integrate with CI/CD

To shift left on security, integrate PSA compliance checks into your CI/CD pipelines. You can:

  • Use kubectl apply --dry-run=server to pre-validate manifests

  • Run automated tests against labeled test namespaces

  • Alert on violations in audit/warn modes using logging tools (e.g., ELK Stack, Fluentd, or Datadog)

For more observability comparisons, check out our posts on Datadog vs Grafana and Kibana vs Grafana.


Example Configurations

Implementing Pod Security Admission (PSA) effectively requires careful labeling of namespaces based on their environment and security requirements.

Below are real-world examples to help you configure PSA using the pod-security.kubernetes.io labels.

🔐 Enforcing “restricted” in Production

In a production environment, you want to apply the strictest security settings to prevent privilege escalation and host access.

bash
kubectl label namespace prod \
pod-security.kubernetes.io/enforce=restricted \
pod-security.kubernetes.io/enforce-version=latest

This configuration ensures that any pod not compliant with the restricted policy will be rejected.

⚠️ Warning in Staging

Staging environments are ideal for testing security posture without breaking builds.

You can set a more permissive enforce level and issue warnings for higher levels.

bash
kubectl label namespace staging \
pod-security.kubernetes.io/enforce=baseline \
pod-security.kubernetes.io/enforce-version=latest \
pod-security.kubernetes.io/warn=restricted \
pod-security.kubernetes.io/warn-version=latest

Here:

  • Non-compliant pods that don’t meet baseline will be rejected.

  • Pods violating the stricter restricted level will still be created but will trigger warnings.

🧪 Audit in Development

In dev or experimental environments, it’s common to only log violations without blocking or warning.

bash
kubectl label namespace dev \
pod-security.kubernetes.io/audit=restricted \
pod-security.kubernetes.io/audit-version=latest

This enables teams to track compliance and gradually tighten security policies without disrupting workflows.

💡 Tip: Combine multiple modes (enforce + warn + audit) in different environments to create a secure, observability-first posture that evolves with your app lifecycle.

Want to understand more about secure Kubernetes operations? Check out Implementing Pod Security Policies in Kubernetes and our guide to HPA in Kubernetes.


Troubleshooting & Tips

Implementing Pod Security Admission (PSA) can sometimes lead to unexpected pod rejections or security policy gaps.

This section covers common pitfalls and tips to help you ensure a smooth rollout.

🛑 Common Issues When Enabling PSA

  1. Pods Failing to Start After Labeling a Namespace

    • Cause: The namespace is labeled with enforce=restricted, but existing pod specs use forbidden settings (e.g., hostPID: true or running as root).

    • Solution: Review denied fields in pod YAML and refactor to comply with the enforced level.

  2. Label Typos or Missing Versions

    • Example: Misspelling pod-security.kubernetes.io/enforce as pod.security.kubernetes.io/enforce

    • Tip: Always use the full, correct label and include the *-version label to avoid unexpected default behavior.

  3. Conflicts With Legacy PSP Configurations

    • If you’re migrating from PSP, ensure no outdated admission webhooks or conflicting policies are still active.

Verifying Policy Enforcement

  • Dry Run Deployments
    Use kubectl --dry-run=server to preview whether your pod spec will be accepted under current PSA settings.

  • Audit Logs and Events
    Inspect audit logs and events in the namespace:

    bash
    kubectl get events -n your-namespace
  • Use kubectl auth can-i
    Validate if the current service account can create a specific pod with:

    bash
    kubectl auth can-i create pod --as=system:serviceaccount:<namespace>:<serviceaccount>

🚀 Best Practices for Gradual Rollout

  • Start With warn or audit in Dev
    This lets your team identify violations without disruption.

  • Progressively Apply enforce in Higher Environments
    Move from baseline to restricted once all pods are compliant.

  • Document Exceptions
    If your app needs exceptions (like certain volume types or security contexts), document and limit those to specific namespaces.

  • Automate Security Checks in CI/CD
    Validate pod specs with tools like OPA/Gatekeeper or Kyverno as part of your deployment pipelines.

Need help securing workloads at scale? Read our guide on Implementing Pod Security Policies in Kubernetes and Optimizing Kubernetes Resource Limits for complementary insights.


Alternatives to PSA

While Pod Security Admission (PSA) provides a simple, built-in solution for enforcing pod security standards, it may not cover every use case—especially in complex or regulated environments.

For teams needing more granular control or policy customization, third-party solutions like Kyverno and OPA/Gatekeeper offer powerful alternatives.

🔐 Kyverno

Kyverno is a Kubernetes-native policy engine designed specifically for configuration and security policies.

Unlike OPA, it uses Kubernetes-style YAML policies, making it easier to learn and integrate for platform teams.

Key Features:

  • Write policies as Kubernetes resources (no separate policy language)

  • Validate, mutate, and generate resources

  • Great for enforcing naming conventions, security contexts, and image registries

  • Integrates easily with CI/CD for policy testing

When to use Kyverno:

  • You want a Kubernetes-native approach

  • Your team prefers YAML over Rego (OPA’s language)

  • You need mutation capabilities (e.g., auto-adding labels or annotations)

🧠 OPA/Gatekeeper

Open Policy Agent (OPA) with Gatekeeper adds policy-as-code enforcement using Rego, a powerful query language.

Key Features:

  • Enforce complex, logic-based policies

  • Fine-grained access and compliance controls

  • Extensive auditing and dry-run support

  • Large ecosystem and community support

When to use OPA/Gatekeeper:

  • You need highly customizable or conditional policies

  • Your organization is already using OPA for other services (e.g., API security)

  • You’re enforcing strict compliance or governance rules

🆚 PSA vs. Kyverno vs. OPA

FeaturePSAKyvernoOPA/Gatekeeper
Built-in to Kubernetes✅ Yes❌ No❌ No
Policy LanguageN/A (labels)YAML (Kubernetes-style)Rego (custom DSL)
Validation✅ Basic✅ Advanced✅ Advanced
Mutation❌ No✅ Yes❌ (mostly validation only)
ComplexityLowMediumHigh

If you’re still using PSPs, see our guide on Implementing Pod Security Policies in Kubernetes.


Conclusion

As Kubernetes continues to evolve, Pod Security Admission (PSA) has emerged as a simple yet effective way to enforce security best practices at the pod level.

Replacing the now-deprecated PodSecurityPolicies, PSA provides a native and easy-to-use mechanism for defining security standards per namespace, helping teams reduce risk without the need for complex tooling.

By understanding PSA’s enforce, audit, and warn modes, and applying the right security levels (Privileged, Baseline, Restricted), you can tailor your cluster’s behavior to meet both development flexibility and production-grade security.

For many teams, PSA will be enough.

But if you need deeper customization or policy logic, tools like Kyverno or OPA/Gatekeeper are excellent alternatives.

🔒 Final takeaway:
Pod Security Admission helps you shift security left, ensuring your Kubernetes workloads meet compliance and operational safety from the start.

Call-to-action:
Start labeling your namespaces today with the appropriate PSA levels and modes. It’s a small step that makes a big impact.

Be First to Comment

    Leave a Reply

    Your email address will not be published. Required fields are marked *