Kubernetes
Pod Security Policy
Troubleshooting
Security
Configuration Issues

Pod Security Policy not working as intended

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

When Pod Security Policy appears to "not work", the first thing to check is the Kubernetes version. On older clusters, PSP depended on both admission-controller enablement and RBAC permissions. On modern clusters, the simpler answer is that Pod Security Policy was removed, so it will not enforce anything at all.

Check the Cluster Version First

This question splits immediately by Kubernetes version:

  • on Kubernetes 1.24 and earlier, PSP can still exist if the admission plugin is enabled
  • on Kubernetes 1.25 and later, PSP is removed and should be replaced

So if you apply a PodSecurityPolicy object to a newer cluster and expect enforcement, nothing is wrong with your pod manifest. The feature itself is gone.

On Older Clusters, the YAML Was Never Enough

Even when PSP existed, creating the policy object alone did not enforce it. Two conditions had to be true:

  1. the PodSecurityPolicy admission controller had to be enabled on the API server
  2. the user or service account had to be authorized to use a matching PSP

A minimal restrictive PSP looked like this:

yaml
1apiVersion: policy/v1beta1
2kind: PodSecurityPolicy
3metadata:
4  name: restricted
5spec:
6  privileged: false
7  allowPrivilegeEscalation: false
8  requiredDropCapabilities:
9    - ALL
10  runAsUser:
11    rule: MustRunAsNonRoot
12  seLinux:
13    rule: RunAsAny
14  fsGroup:
15    rule: RunAsAny
16  supplementalGroups:
17    rule: RunAsAny
18  volumes:
19    - configMap
20    - emptyDir
21    - secret
22    - projected
23    - persistentVolumeClaim

That policy still did nothing if the admission plugin was off or no caller had permission to use it.

RBAC Was Often the Real Problem

A service account needed explicit RBAC permission for the use verb on the intended policy.

yaml
1apiVersion: rbac.authorization.k8s.io/v1
2kind: ClusterRole
3metadata:
4  name: use-restricted-psp
5rules:
6  - apiGroups:
7      - policy
8    resources:
9      - podsecuritypolicies
10    resourceNames:
11      - restricted
12    verbs:
13      - use

Then bind that permission to the service account:

yaml
1apiVersion: rbac.authorization.k8s.io/v1
2kind: RoleBinding
3metadata:
4  name: app-psp-binding
5  namespace: apps
6subjects:
7  - kind: ServiceAccount
8    name: app-service-account
9    namespace: apps
10roleRef:
11  apiGroup: rbac.authorization.k8s.io
12  kind: ClusterRole
13  name: use-restricted-psp

If this binding was missing, the policy could exist in the cluster and still never apply to the workload you cared about.

Multiple PSPs Could Make Behavior Look Inconsistent

Another reason PSP felt unreliable is that a cluster might contain several policies. If the caller was allowed to use a more permissive policy, the pod could be admitted under that policy instead of the restrictive one you expected.

That made troubleshooting much harder, because the policy YAML itself might look correct while the effective policy was different.

When debugging older clusters, check:

  • which PSPs exist
  • which PSPs the service account can use
  • whether a more permissive policy also matches the pod

Admission Configuration Could Be the Real Issue

On self-managed clusters, the control plane had to start with the PSP admission plugin enabled. If that was missing, the PSP objects were just inert API resources.

That produced a classic symptom:

  • the PSP object was present
  • applying it succeeded
  • forbidden pods still ran

In that case, the control plane configuration was the problem, not the policy document.

Modern Replacement: Pod Security Admission

On current Kubernetes versions, the built-in replacement is Pod Security Admission. It uses namespace labels instead of PSP objects.

bash
1kubectl label namespace apps \
2  pod-security.kubernetes.io/enforce=restricted \
3  pod-security.kubernetes.io/audit=restricted \
4  pod-security.kubernetes.io/warn=restricted

This is easier to reason about because enforcement is attached directly to the namespace and the policy levels are standardized.

If you need more custom policy logic than the built-in levels provide, tools such as Kyverno or OPA Gatekeeper are the usual next step.

Common Pitfalls

The biggest mistake is assuming that creating a PSP object alone ever guaranteed enforcement. On older clusters, admission and RBAC both had to be configured correctly.

Another common issue is troubleshooting PSP on Kubernetes 1.25+, where the feature no longer exists.

People also overlook permissive alternate PSPs that the service account is allowed to use, which makes the restrictive policy appear to be ignored.

Finally, do not focus only on the YAML. Cluster version, admission-controller setup, and service-account permissions are often the real cause.

Summary

  • Pod Security Policy only worked on older Kubernetes clusters and required both admission and RBAC setup.
  • On Kubernetes 1.25+, PSP is removed and will not enforce anything.
  • Missing use permissions were one of the most common causes of apparent PSP failure.
  • Multiple PSPs could make enforcement look inconsistent if a permissive one was also available.
  • For modern clusters, use Pod Security Admission or another current policy engine instead.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.