TKG releases v1.25 and later enable the Pod Security Admission (PSA) controller. With PSA you can uniformly enforce pod security using namespace labels.

PSA Enabled in TKR 1.25 and Later

The Pod Security Admission controller is a Kubernetes controller that lets you apply security standards to pods running on TKG clusters. By default, TKG releases v1.25 and later enable the Pod Security Admission (PSA) controller. The PSA controller replaces the Pod Security Policy (PSP) controller, which is deprecated and removed. See also Configure PSP for TKR 1.24 and Eariler.

TKG release v1.25 is a transitional release with PSA configured to warn. Starting with TKG release v1.26, PSA is enforced. You should plan to migrate pod workloads from PSP to PSA in anticipation of upgrading TKG clusters. Refer to Migrate from Pod Security Policy to the Built-In Pod Security Admission Controller for guidance.

Configuring PSA Cluster-wide

Starting with vSphere 8 Update 3, you can configure PSA cluster-wide using the podSecurityStandard ClusterClass variable that is available with the v1beta1 API. See Cluster v1beta1 API.

PSA Modes

The PSA controller supports three pod security modes: enforce, audit, and warn. The table lists and describes each PSA mode.
Table 1. PSA Modes
MODE Description
enforce Security violations cause the pod to be rejected.
audit Security violations trigger the addition of an audit annotation to the event recorded in the audit log, but are otherwise allowed.
warn Security violations trigger a user-facing warning, but are otherwise allowed.

PSA Standards

The PSA controller defines three levels of pod security standards that are intended to cover the security spectrum. The pod security standards are cumulative and range from permissive to restrictive. The table lists and describes each PSA standard.
Table 2. PSA Standards
LEVEL Description
privileged Unrestricted control, providing the widest possible level of permissions. This security standard allows for known privilege escalations.
baseline Minimally restrictive control which prevents known privilege escalations. This security standard allows the default (minimally specified) pod configuration.
restricted Heavily restricted control, following pod hardening best practices.

PSA Namespace Labels

The PSA controller enforces pod security at the Kubernetes namespace level. You use namespace labels to define the PSA modes and levels you want to use for pods in a given namespace.

Kubernetes provides a set of labels that you can use to define which of the standards to use for a namespace. The label you apply defines what action the Kubernetes control plane takes if a PSA violation is detected. For a given Kubernetes namespace, you can configure any or all modes, or set a different level for different modes.

The PSA namespace label syntax is as follows:
# MODE must be one of `enforce`, `audit`, or `warn`.
# LEVEL must be one of `privileged`, `baseline`, or `restricted`.
pod-security.kubernetes.io/<MODE>=<LEVEL>

You can also apply a per-mode version label that can be used to pin the security standard to the Kubernetes version. See Enforce Pod Security Standards with Namespace Labels for more information.

Default PSA for TKG Clusters

By default, TKG clusters provisioned with TKG release v1.25 have PSA modes warn and audit set to restricted for non-system namespaces. This is a no-force setting: the PSA controller generates a warning and audit notification if a pod violates security, but the pod is not rejected.

By default, TKG clusters provisioned with TKG releases v1.26 and later have the PSA mode enforce set to restricted for non-system namespaces. If a pod violates security, it is rejected. You must configure PSA on the namespace to run pods with less restrictive control.
Important: Some system pods running in the kube-system, tkg-system, and vmware-system-cloud-provider namespaces require elevated privileges. These namespaces are excluded from pod security. In addition, pod security on system namespaces cannot be changed.
The table lists the default PSA configuration for TKG clusters.
Table 3. Default PSA for TKG Clusters
TKr Version Default PSA
TKr v1.25

mode: warn | level: restricted

mode: audit | level: restricted

mode: enforce | level: not set

TKr v1.26 and later

mode: enforce | level: restricted

Configuring PSA Using Namespace Labels

For TKG release v1.25, use the following example command to change the security levels for a given namespace so that PSA warnings and audit notifications are not generated.
kubectl label --overwrite ns NAMESPACE pod-security.kubernetes.io/audit=privileged 
kubectl label --overwrite ns NAMESPACE pod-security.kubernetes.io/warn=privileged
For TKG releases v1.26 and later, use the following example command to downgrade the PSA standard from restricted to baseline.
kubectl label --overwrite ns NAMESPACE pod-security.kubernetes.io/enforce=baseline
For example, to enforce the baseline standard on the default namespace:
kubectl label --overwrite ns default pod-security.kubernetes.io/enforce=baseline
For TKG releases v1.26 and later, use the following example command to downgrade the PSA standard from restricted to privileged.
kubectl label --overwrite ns NAMESPACE pod-security.kubernetes.io/enforce=privileged
For example, to enforce the privileged standard on the default namespace:
kubectl label --overwrite ns default pod-security.kubernetes.io/enforce=privileged

For TKG releases v1.26 and later, use the following example commands to relax PSA across all non-system namespaces.

kubectl label --overwrite ns --all pod-security.kubernetes.io/enforce=privileged
kubectl label --overwrite ns --all pod-security.kubernetes.io/warn=restricted

Configuring Security Context for Individual Pods

If you try to run a pod that violates PSA, you revive an error message indicating this. Such as:
{"opType":"CREATE_POD","succeeded":false,"err":"creating pod example-pod: pods 
\"example-pod\" is forbidden: violates PodSecurity \"restricted:latest\": 
allowPrivilegeEscalation != false (container \"example-container\" must set 
securityContext.allowPrivilegeEscalation=false), unrestricted capabilities 
(container \"example-container\" must set securityContext.capabilities.drop=[\"ALL\"]), 
runAsNonRoot != true (pod or container \"example-container\" must set securityContext.runAsNonRoot=true), 
seccompProfile (pod or container \"example-container\" must set securityContext.seccompProfile.type to 
\"RuntimeDefault\" or \"Localhost\")","events":[]}
Instead of setting PSA on an entire namespace, you can configure the security context for an individual pod. To allow an individual pod to run, in the pod specification you can set the security context as follows:
apiVersion: v1
kind: Pod
metadata:
  name: example-pod 
spec:
  containers:
  - image: gcr.io/google_containers/busybox:1.24
    name: example-container
    command: ["/bin/sh", "-c", "echo 'hello' > /mnt/volume1/index.html && chmod o+rX /mnt /mnt/volume1/index.html && while true ; do sleep 2 ; done"]
    securityContext:
      allowPrivilegeEscalation: false
      runAsNonRoot: true
      seccompProfile:
        type: "RuntimeDefault"
      capabilities:
        drop: [all]
    volumeMounts:
    - name: example-volume-mount
      mountPath: /mnt/volume1
  restartPolicy: Never
  volumes:
  - name: example-volume
    persistentVolumeClaim:
    claimName: example-pvc