Migrate from PodSecurityPolicy to the PodSecurity admission controller

This page shows you how to continue to enforce many Pod-level security controls in your Google Kubernetes Engine (GKE) clusters by migrating from PodSecurityPolicy to the PodSecurity admission controller.

Overview

PodSecurityPolicy was a Kubernetes admission controller that let you enforce Pod-level security controls such as the Kubernetes Pod Security Standards, providing granular control over the security configuration of your deployed workloads. The Kubernetes project deprecated PodSecurityPolicy and removed the feature entirely in Kubernetes v1.25.

If you currently use PodSecurityPolicy in your GKE clusters, disable the feature before you upgrade to GKE version 1.25 and later.

To learn more about the deprecation and removal of PodSecurityPolicy, refer to PodSecurityPolicy deprecation.

PodSecurity and PodSecurityPolicy

The PodSecurity admission controller is an admission controller that is enabled by default in GKE versions 1.23 and later. PodSecurity allows you to enforce the policies defined in the Pod Security Standards on your deployed workloads. PodSecurity lets you continue to implement recommended Pod-level security configurations in your clusters after you migrate from PodSecurityPolicy. Unlike PodSecurityPolicy, PodSecurity doesn't support custom configurations.

Requirements and limitations

  • PodSecurity is available in GKE versions 1.23 and later.
  • PodSecurity doesn't terminate Pods that are already running on your nodes, even if they violate the applied policy.
  • PodSecurity doesn't mutate fields. If you use any mutating fields in your PodSecurityPolicy, modify your Pod spec to ensure that those fields are present when you deploy the workloads.

Before you begin

Before you start, make sure you have performed the following tasks:

  • Ensure that you have enabled the Google Kubernetes Engine API.
  • Enable Google Kubernetes Engine API
  • Ensure that you have installed the Google Cloud CLI.
  • Set up default Google Cloud CLI settings for your project by using one of the following methods:
    • Use gcloud init, if you want to be walked through setting project defaults.
    • Use gcloud config, to individually set your project ID, zone, and region.

    gcloud init

    1. Run gcloud init and follow the directions:

      gcloud init

      If you are using SSH on a remote server, use the --console-only flag to prevent the command from launching a browser:

      gcloud init --console-only
    2. Follow the instructions to authorize the gcloud CLI to use your Google Cloud account.
    3. Create a new configuration or select an existing one.
    4. Choose a Google Cloud project.
    5. Choose a default Compute Engine zone.
    6. Choose a default Compute Engine region.

    gcloud config

    1. Set your default project ID:
      gcloud config set project PROJECT_ID
    2. Set your default Compute Engine region (for example, us-central1):
      gcloud config set compute/region COMPUTE_REGION
    3. Set your default Compute Engine zone (for example, us-central1-c):
      gcloud config set compute/zone COMPUTE_ZONE
    4. Update gcloud to the latest version:
      gcloud components update

    By setting default locations, you can avoid errors in gcloud CLI like the following: One of [--zone, --region] must be supplied: Please specify location.

  • Ensure that you have a GKE Autopilot or Standard cluster running version 1.23 or later.
  • Check your PodSecurityPolicy resources for mutating field configurations. Add those fields to your Pod manifests so that any workloads already running on your nodes conform with a policy defined in the Pod Security Standards. For instructions, refer to Simplify and standardize Pod Security Policies.

Configure the PodSecurity admission controller in your cluster

The PodSecurity admission controller enforces the Pod Security Standards at the namespace level. You must configure the controller to enforce one of the policies defined by the Pod Security Standards in each namespace. The following policies are available:

  • Restricted: Most restrictive policy. Complies with Pod hardening best practices.
  • Baseline: Minimally restrictive policy that prevents known privilege escalations. Allows all default values for fields in Pod specifications.
  • Privileged: Unrestricted policy that allows anything, including known privilege escalations. Apply this policy with caution.

To migrate your PodSecurityPolicy configuration to the PodSecurity admission controller, do the following in every namespace in your cluster. These steps are described in detail in the sections that follow.

  1. Apply the Restricted policy in dry-run mode to the namespace and check for violations.
  2. If your Pods violate the Restricted policy, apply the less restrictive Baseline policy in dry-run mode to the namespace and check for violations.
  3. If your Pods violate the Baseline policy, modify your Pod specs to fix the violations.
  4. When the Baseline policy no longer returns violations, apply the policy in enforce mode to the namespace.

To avoid potential downtime if PodSecurity rejects new Pods, perform these steps in a staging environment. Alternatively, you can apply the identified policy in audit mode instead of enforce mode and review your audit logs to find potential rejected Pods.

audit mode doesn't enforce the policy. GKE deploys the Pods and adds entries to the GKE audit logs.

List all namespaces in your cluster

Get a list of all namespaces in your cluster. Repeat the steps in the following sections for every namespace in the list:

kubectl get ns

In the following GKE versions, GKE ignores policies that you apply to the kube-system namespace:

  • 1.23.6-gke.1900 and later
  • 1.24.0-gke.1200 and later

In earlier GKE versions, avoid enforcing policies in kube-system.

Apply each policy of the Pod Security Standards in dry-run mode

In the following steps, you'll apply each policy in dry-run mode, starting with the most restrictive Restricted policy. If the output shows a warning, either modify the violating Pod spec to comply with the policy, or try the less restrictive Baseline policy. If the output doesn't show a warning, you can then apply the Baseline policy without dry-run mode.

  1. Apply the Restricted policy in dry-run mode:

    kubectl label --dry-run=server --overwrite ns NAMESPACE \
        pod-security.kubernetes.io/enforce=restricted
    

    If a Pod in the namespace violates the Restricted policy, the output is similar to the following:

    Warning: existing pods in namespace "NAMESPACE" violate the new PodSecurity enforce level "restricted:latest"
    namespace/NAMESPACE labeled
    

    If the Restricted policy displays a warning, modify your Pods to fix the violation and try the command again. Alternatively, try the less restrictive Baseline policy in the following step.

  2. Apply the Baseline policy in dry-run mode:

    kubectl label --dry-run=server --overwrite ns NAMESPACE \
        pod-security.kubernetes.io/enforce=baseline
    

    If a Pod in the namespace violates the Baseline policy, the output is similar to the following:

    Warning: existing pods in namespace "NAMESPACE" violate the new PodSecurity enforce level "baseline:latest"
    namespace/NAMESPACE labeled
    

If your Pods violate the Baseline policy, modify your Pods to fix the violations and repeat this step until GKE no longer displays a warning.

Enforce the policy on a namespace

When you identify the policy that works for a namespace, apply the policy to the namespace in enforce mode:

kubectl label --overwrite ns NAMESPACE \
    pod-security.kubernetes.io/enforce=POLICY

Replace POLICY with the name of the policy, which can be one of restricted, baseline, or privileged.

Ensure that you repeat the preceding steps for every namespace in your cluster.

Disable the PodSecurityPolicy feature on your cluster

After you configure the PodSecurity admission controller for every namespace in your cluster, disable the PodSecurityPolicy feature:

gcloud beta container clusters update CLUSTER_NAME \
    --no-enable-pod-security-policy

Replace CLUSTER_NAME with the name of your GKE cluster.

When you upgrade your cluster to GKE version 1.25, GKE automatically removes all remaining PodSecurityPolicy objects, including those added by GKE, Anthos Config Management, and any PodSecurityPolicy objects that you previously defined.

Recommendations

  • Try to conform to the Restricted policy where possible. Audit your applications to see if the configuration can be hardened further.
  • You can lock the Pod security mode to a specific Kubernetes minor version by adding the pod-security.kubernetes.io/MODE-version: VERSION label to the kubectl label commands in the previous steps. Replace VERSION with the Kubernetes version number, such as v1.24.
  • After you disable the PodSecurityPolicy feature, review your running applications to check for disruptions or gaps in the security configuration.
  • After you configure PodSecurity, update your namespace creation process to automatically apply a PodSecurity label to all new namespaces. For information, see Review namespace creation process

What's next