> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Demo Applying Pod Security Standards

> Guide to Kubernetes Pod Security Standards that explains label-driven namespace profiles privileged baseline restricted, warn audit and enforce modes, and example manifests for testing and compliance

[Gatekeeper](https://open-policy-agent.github.io/gatekeeper/) and [Kyverno](https://kyverno.io/) are full-featured policy engines, but they require installing external controllers and CRDs. Pod Security Standards (PSS) are built into Kubernetes and let you enforce security baselines at the namespace level simply by adding labels — no extra operators required.

Pod Security Standards are label-driven and evaluated by Kubernetes' built-in admission controller. Use `warn` to discover issues, `audit` to log them, and `enforce` to block non-compliant requests.

## Profiles

PSS defines three profiles targeting common security postures:

| Profile | Purpose | When to use |
| -: | - | - |
| privileged | Essentially "anything goes" — for system or infrastructure workloads that require broad host access. | System components and privileged addons. |
| baseline | Blocks the most dangerous privileges while allowing most apps to run. | General-purpose application namespaces. |
| restricted | Hardened baseline that follows security best practices (run-as-non-root, drop capabilities, seccomp, etc.). | Production workloads requiring strong isolation. |

![A screenshot of the Kubernetes documentation page titled "Pod Security Standards." It shows a table describing the Privileged, Baseline, and Restricted policy profiles along with site navigation links in the sidebars.](https://mintcdn.com/kodekloud-c4ac6d9a/jFwNGqGMK4QeJs-g/images/Prep-Course-Certified-Cloud-Native-Platform-Engineering-CNPE/Security-and-Policy-Enforcement/Demo-Applying-Pod-Security-Standards/kubernetes-pod-security-standards.jpg?fit=max\&auto=format\&n=jFwNGqGMK4QeJs-g\&q=85\&s=f4b282cc4eaf56af45bb7e7453230b25)

## Modes

Each profile can be applied in one of three modes:

| Mode | Behavior |
| - | - |
| `enforce` | Admission requests that violate the profile are blocked. |
| `audit` | Violations are recorded (logged) but requests are allowed. |
| `warn` | A warning message is shown at admission time, but requests are allowed. |

## How PSS is applied

PSS is label-driven. To set a profile and mode on a namespace, add one or more of these labels:

* `pod-security.kubernetes.io/enforce`
* `pod-security.kubernetes.io/audit`
* `pod-security.kubernetes.io/warn`

Each label's value is the profile name: `privileged`, `baseline`, or `restricted`. For example:

* `pod-security.kubernetes.io/enforce=baseline`
* `pod-security.kubernetes.io/warn=restricted`

## Inspect namespaces and labels

List namespaces and show current labels:

```bash theme={null}
kubectl get namespaces --show-labels
```

Example output:

```bash theme={null}
NAME              STATUS   AGE     LABELS
default           Active   137m    kubernetes.io/metadata.name=default
kube-flannel      Active   137m    k8s-app=flannel,kubernetes.io/metadata.name=kube-flannel,pod-security.kubernetes.io/enforce=privileged
kube-node-lease   Active   137m    kubernetes.io/metadata.name=kube-node-lease
kube-public       Active   137m    kubernetes.io/metadata.name=kube-public
kube-system       Active   137m    kubernetes.io/metadata.name=kube-system
pss-baseline      Active   9m     kubernetes.io/metadata.name=pss-baseline
pss-privileged    Active   9m     kubernetes.io/metadata.name=pss-privileged
pss-restricted    Active   9m     kubernetes.io/metadata.name=pss-restricted
```

## Apply PSS labels

Label the `pss-baseline` namespace to enforce `baseline` while auditing and warning for `restricted`:

```bash theme={null}
kubectl label namespace pss-baseline \
  pod-security.kubernetes.io/enforce=baseline \
  pod-security.kubernetes.io/audit=restricted \
  pod-security.kubernetes.io/warn=restricted
```

Expected response:

```bash theme={null}
namespace/pss-baseline labeled
```

Applying `enforce` can immediately block workloads in the target namespace. Verify workloads are compliant (or use `warn`/`audit` first) before enforcing to avoid downtime.

## Test admission with a privileged pod (should be blocked)

Here is a manifest for a privileged pod that requests host networking and privilege escalation:

```yaml theme={null}
# privileged-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: privileged-app
spec:
  hostNetwork: true
  containers:
  - name: app
    image: nginx:alpine
    securityContext:
      privileged: true
```

Apply it to the `pss-baseline` namespace:

```bash theme={null}
kubectl apply -f privileged-pod.yaml -n pss-baseline
```

Expected blocked response:

```bash theme={null}
Error from server (Forbidden): error when creating "privileged-pod.yaml": pods "privileged-app" is forbidden: violates PodSecurity "baseline:latest": host namespaces (hostNetwork=true), privileged (container "app" must not set securityContext.privileged=true)
```

## Test with a non-privileged pod (allowed by baseline, warns for restricted)

Create a simple nginx pod that does not request privileges:

```bash theme={null}
kubectl run baseline-test --image=nginx:alpine -n pss-baseline
```

Because `audit=restricted` and `warn=restricted` were set, you will see a warning showing how this pod fails the stricter `restricted` profile while the pod is still admitted:

Example output:

```bash theme={null}
Warning: would violate PodSecurity "restricted:latest": allowPrivilegeEscalation != false (container "baseline-test" must set securityContext.allowPrivilegeEscalation=false), unrestricted capabilities (container "baseline-test" must set securityContext.capabilities.drop=["ALL"]), runAsNonRoot != true (pod or container "baseline-test" must set securityContext.runAsNonRoot=true), seccompProfile (pod or container "baseline-test" must set securityContext.seccompProfile.type to "RuntimeDefault" or "Localhost")
pod/baseline-test created
```

This is useful to discover what changes are required before you move to `enforce`.

## Enforce the restricted profile

Label the `pss-restricted` namespace to enforce `restricted`:

```bash theme={null}
kubectl label namespace pss-restricted pod-security.kubernetes.io/enforce=restricted
```

Expected:

```bash theme={null}
namespace/pss-restricted labeled
```

Attempt to create the same simple nginx pod in the restricted namespace:

```bash theme={null}
kubectl run restricted-test --image=nginx:alpine -n pss-restricted
```

You should see the request blocked with specific violations:

```bash theme={null}
Error from server (Forbidden): pods "restricted-test" is forbidden: violates PodSecurity "restricted:latest": allowPrivilegeEscalation != false (container "restricted-test" must set securityContext.allowPrivilegeEscalation=false), unrestricted capabilities (container "restricted-test" must set securityContext.capabilities.drop=["ALL"]), runAsNonRoot != true (pod or container "restricted-test" must set securityContext.runAsNonRoot=true), seccompProfile (pod or container "restricted-test" must set securityContext.seccompProfile.type to "RuntimeDefault" or "Localhost")
```

## Example compliant pod for `restricted`

A pod compliant with `restricted` typically:

* runs as a non-root user (`runAsNonRoot: true`, `runAsUser: 1000`)
* disables privilege escalation (`allowPrivilegeEscalation: false`)
* drops all capabilities (`capabilities.drop: ["ALL"]`)
* sets a seccomp profile (`seccompProfile.type: RuntimeDefault`)

Example manifest:

```yaml theme={null}
# restricted-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: restricted-app
spec:
  containers:
  - name: app
    image: nginxinc/nginx-unprivileged:alpine
    securityContext:
      runAsNonRoot: true
      runAsUser: 1000
      allowPrivilegeEscalation: false
      capabilities:
        drop:
        - ALL
      seccompProfile:
        type: RuntimeDefault
```

Apply it to the `pss-restricted` namespace:

```bash theme={null}
kubectl apply -f restricted-pod.yaml -n pss-restricted
```

Expected:

```bash theme={null}
pod/restricted-app created
```

## Audit (`warn`) workflow — discover violations before enforcing

* Use `warn` to surface violations when pods are created or updated. This helps teams discover compatibility issues without breaking workloads.
* Use `audit` to log violations for monitoring and reporting.

Example — create a namespace and set `warn=baseline`:

```bash theme={null}
kubectl create namespace workload-audit
kubectl label namespace workload-audit pod-security.kubernetes.io/warn=baseline
kubectl run audit-test --image=nginx:alpine -n workload-audit
```

Since the pod conforms to `baseline`, no warnings are produced and the pod is created:

```bash theme={null}
pod/audit-test created

kubectl get events -n workload-audit
# Shows Scheduled, Pulled, Created, Started events — no warnings
```

Now change the warning label to `restricted` (use `--overwrite` to update labels) and create another pod:

```bash theme={null}
kubectl label namespace workload-audit pod-security.kubernetes.io/warn=restricted --overwrite
kubectl run audit-test-2 --image=nginx:alpine -n workload-audit
```

You will see a warning at admission time identifying what would violate `restricted`, but the pod remains created:

```bash theme={null}
Warning: would violate PodSecurity "restricted:latest": allowPrivilegeEscalation != false (container "audit-test-2" must set securityContext.allowPrivilegeEscalation=false), unrestricted capabilities (container "audit-test-2" must set securityContext.capabilities.drop=["ALL"]), runAsNonRoot != true (pod or container "audit-test-2" must set securityContext.runAsNonRoot=true), seccompProfile (pod or container "audit-test-2" must set securityContext.seccompProfile.type to "RuntimeDefault" or "Localhost")
pod/audit-test-2 created
```

Warnings appear at admission time in your terminal; you can also inspect events to find them.

## Summary

* Pod Security Standards provide a simple, built-in mechanism to enforce namespace-level security baselines without additional tooling.
* Use:
  * `warn` — discover violations at admission time,
  * `audit` — log violations for later inspection,
  * `enforce` — block non-compliant requests.
* Add labels to namespaces: `pod-security.kubernetes.io/enforce|audit|warn=<profile>`.
* Iterate: start with `warn`/`audit`, fix workloads to be compliant, then move to `enforce`.

With this workflow you can progressively harden namespaces from `baseline` to `restricted` while avoiding surprises in production.

## Links and references

* [Pod Security Standards — Kubernetes Concepts](https://kubernetes.io/docs/concepts/security/pod-security-standards/)
* [Kubernetes Pod Security Admission Controller](https://kubernetes.io/docs/concepts/security/pod-security-admission/)
* [Gatekeeper (Open Policy Agent)](https://open-policy-agent.github.io/gatekeeper/)
* [Kyverno — Kubernetes Native Policy Management](https://kyverno.io/)

> **[Watch Video](https://learn.kodekloud.com/user/courses/prep-course-certified-cloud-native-platform-engineer-cnpe/module/35a7fadb-02d8-4557-a819-2e4dcfa970cc/lesson/0a0c1ba8-a55f-4023-be39-fba7a86f5fa8)**

> **[Practice Lab](https://learn.kodekloud.com/user/courses/prep-course-certified-cloud-native-platform-engineer-cnpe/module/35a7fadb-02d8-4557-a819-2e4dcfa970cc/lesson/45b8b593-7312-4acf-b1e5-093d3bc53b62)**


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.