Kubernetes 1.25 changes the contract for pod security policy
PodSecurityPolicy is removed as Pod Security Admission becomes stable. The replacement provides predefined validation levels without reproducing PSP's mutation and fine-grained policy model.
Replacing a security mechanism requires preserving the intended restrictions, not merely enabling its successor. Kubernetes 1.25 removes PodSecurityPolicy and makes Pod Security Admission stable. The new mechanism has a smaller policy model and deliberately lacks some of PSP's capabilities. A cluster can therefore complete the software upgrade without having completed the policy migration.
The August 23 release announcement describes PSP's removal after deprecation in 1.21. It says the usability changes needed for PSP would have introduced breaking changes. The replacement is consequently a different design, with migration work that depends on how a cluster used the old mechanism.
I favour a built-in policy model whose decisions can be understood from declared configuration. That preference fits Kubernetes' reconciliation approach. It also makes the absence of mutation important, because the source definition must contain the security settings required for admission.
PSP's problems shaped a narrower replacement
The Pod Security beta introduction describes several shortcomings of PSP. Its policy authorization model was difficult to deploy with controllers. A lack of dry-run and audit capabilities complicated adoption, while a large and inconsistent configuration model made policies hard to understand.
Pod Security Admission addresses those concerns with predefined Pod Security Standards. Administrators select a level for a namespace, with separate modes governing rejection and reporting. The model provides an out-of-the-box policy vocabulary without requiring a custom rule for every restricted field.
That simplification also defines what the mechanism does not provide. The beta introduction explicitly says it lacks complete feature parity with PSP. It cannot mutate a resource to repair a violation. It does not offer fine-grained control over every allowed field value or arbitrary resource type.
Those limits are relevant to existing policy, not only to hypothetical future requirements. A PSP that supplied security defaults changed the object before execution. Replacing that with validation alone means the submitted configuration must already contain the values needed to pass.
A policy migration therefore needs a semantic account of what the old mechanism did. A restriction and an injected default have different destinations in the new arrangement. Validation can reject a missing setting, but it cannot silently supply it. The application source or another explicitly chosen mechanism must own that setting.
Namespace labels select policy and reporting
Pod Security Standards define privileged, baseline, and restricted levels. Privileged is unrestricted. Baseline aims to prevent known privilege escalations while keeping restrictions limited. Restricted applies stronger requirements that can affect compatibility.
The modes describe what happens when a request violates the chosen standard. Enforce rejects a violating Pod. Audit records violations in audit annotations without blocking the request. Warn returns a warning to the user without denying admission.
A namespace can use different levels for those modes. That permits an existing enforcement level and a stricter reporting level to coexist. It also gives an operator a way to observe the effect of a proposed restriction before making it an admission requirement.
The version label matters independently of the level. A policy can be pinned to the definition shipped with a particular Kubernetes version. This keeps the selected checks stable as the cluster's software changes. Without an explicit version, the policy uses the latest definition available to that server.
For example, the following Namespace selects baseline enforcement while reporting against restricted policy. The version labels keep both choices tied to the 1.25 definitions.
apiVersion: v1
kind: Namespace
metadata:
name: applications
labels:
pod-security.kubernetes.io/enforce: baseline
pod-security.kubernetes.io/enforce-version: v1.25
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/audit-version: v1.25
pod-security.kubernetes.io/warn: restricted
pod-security.kubernetes.io/warn-version: v1.25
This configuration does not claim that every workload is restricted-compliant. It rejects violations of baseline and reports the gap against restricted. Those are different policy outcomes, expressed separately in the object's labels.
The distinction is useful for communicating security posture. A warning is evidence of a reported violation, not evidence that admission blocked it. Enforce and reporting modes need to remain identifiable when describing what a cluster actually prevents.
Stable admission does not select a universal policy
The fact that Pod Security Admission is stable does not by itself specify every namespace's restriction level. Namespace labels and admission configuration determine the policy. The beta introduction also describes cluster-wide defaults and exemptions through API server admission configuration.
That creates an administrative boundary. The cluster can supply defaults, while namespaces can carry explicit policy labels. Exemptions need their own consideration because an exempt request does not have the same evaluation path as an ordinary request subject to policy.
This is another reason to avoid describing the upgrade as a complete security outcome. Installing 1.25 establishes the version and available mechanism. It does not prove which objects the policy evaluates or which violations the selected settings reject.
The earlier migration guidance begins by removing reliance on mutation from existing PSPs. It then uses warning or audit modes before enforcement and removal of the old admission plugin. In 1.25, PSP itself is gone, so any unfinished dependence on its behaviour needs a replacement outside that removed mechanism.
My preference is to keep those settings in versioned configuration beside the workloads they govern. A pod rejected for missing a required security value should lead to an explicit source change. That makes the next admission attempt explainable from the declared object.
Debugging no longer depends on the application image
Ephemeral containers also become stable in 1.25. The release announcement describes them as containers added for limited use within an existing Pod. Their intended use includes troubleshooting a container that has crashed or whose image does not contain debugging tools.
This capability separates the tools needed to inspect a workload from the tools included in the normal application image. A production image does not have to carry an interactive environment solely because an operator might need one later. The debugging operation can use an additional container in the existing pod context.
That does not remove the security implications of debugging access. The operation introduces another container into a running workload environment. It belongs in the same discussion of declared privilege and admission boundaries, even though its purpose differs from an ordinary application container.
The stable milestone is useful because it establishes maturity for that operational path. The release announcement traces its beta status to 1.23. It does not imply that every old method of troubleshooting disappears or that a debugging container can inspect every possible failure without limits.
Kernel resource management also reaches a stable milestone
The release graduates cgroup v2 support to stable while continuing to support cgroup v1. The announcement connects this work to distributions that already default to the newer Linux interface. Kubernetes needs to operate with the resource-management interface supplied by its host environment.
This is a compatibility milestone at a different layer from admission. Admission evaluates requested pod configuration before storage. Cgroup support concerns how node software manages running processes through the kernel. Both can affect workload behaviour, but neither substitutes for the other.
The distinction matters when describing a cluster's guarantees. A policy that permits a resource setting does not establish how the node enforces every runtime property. Likewise, a supported kernel interface does not decide which privileges an API request may ask for.
Local ephemeral storage capacity isolation also reaches stable in this release. The announcement describes limiting consumption of shared local storage, including emptyDir use, with eviction when a pod exceeds its limit. That gives the storage constraint an operational consequence instead of treating it as descriptive metadata.
API acceptance and implementation support remain separate
The stable NetworkPolicy port-range field supplies another useful example. The release makes endPort stable, allowing a rule to describe a range instead of only a single port. Its announcement explicitly warns that the network policy provider must support the field.
If the provider lacks that support, the documented result is a policy covering only the single port field. A resource accepted by the API server therefore does not prove that the selected network implementation enforces the requested range.
That warning belongs alongside the Pod Security migration because both concern the gap between configuration syntax and operative policy. A valid object is necessary, but its meaning depends on the responsible component and the capabilities that component actually implements.
Kubernetes 1.25 supplies a stable built-in pod admission model and removes the old one. The remaining work is to express intended restrictions under the new model, place previously injected defaults into an explicit owner, and retain policy version choices in configuration. Those choices determine what the cluster rejects when the next workload reaches admission.