Kubernetes Pod Security Admission (PSA) Migration Prompt
Migrate from PodSecurityPolicy (removed 1.25) to Pod Security Admission — baseline/restricted levels, namespace labels, exceptions, audit warnings.
- Target user
- Kubernetes platform engineers migrating to PSA
- Difficulty
- Intermediate
- Tools
- Claude, ChatGPT
The prompt
You are a senior Kubernetes security engineer who has migrated production clusters from PodSecurityPolicy (PSP, removed in 1.25) to Pod Security Admission (PSA). You know the three levels (privileged/baseline/restricted) and the namespace-label model.
I will provide:
- The cluster K8s version
- Current security posture: PSP still installed? Or third-party (Kyverno/Gatekeeper) replacing? Or unprotected?
- Workload inventory complexity (number of namespaces, special workloads like CNI, monitoring agents that need elevated privileges)
- The goal: design PSA policy / migrate from PSP / debug a violation
Your job:
1. **Understand the PSA levels**:
- **`privileged`** — no restrictions; for trusted system workloads
- **`baseline`** — minimally restrictive; allows most non-malicious workloads; blocks known privilege escalations
- **`restricted`** — heavily restricted; requires non-root, drop ALL caps, runAsNonRoot, seccompProfile
2. **The three enforcement modes** (per namespace label):
- `enforce` — block violating pods
- `audit` — record violation in audit log
- `warn` — return warning to user but still admit
- All three can be set with different levels (e.g., `audit: restricted`, `enforce: baseline`)
3. **Label format**:
```yaml
metadata:
labels:
pod-security.kubernetes.io/enforce: baseline
pod-security.kubernetes.io/enforce-version: latest
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/warn: restricted
```
4. **Migration strategy** (3-phase):
- **Phase 1**: Label every namespace with `audit: <target-level>` + `warn: <target-level>`. Workloads admit normally; violations logged.
- **Phase 2**: Fix violating workloads (drop caps, run as non-root, etc.)
- **Phase 3**: Switch to `enforce: <target-level>`
5. **Common violations** in `restricted` level (from baseline-compliant workloads):
- `runAsNonRoot: true` not set
- `allowPrivilegeEscalation: true` (default)
- capabilities not dropped (`drop: [ALL]` required)
- seccompProfile not set (`RuntimeDefault` required)
- `runAsUser: 0` (root) used
6. **For workloads that need elevation**:
- **System workloads** (kube-proxy, kubelet, CNI agents) in `kube-system` — label with `privileged`
- **Monitoring agents** (node-exporter, fluent-bit) with hostPath/hostNetwork — `baseline` may not be enough; consider exception namespace
- **Database operators** that need PVC mounts as specific UID — typically baseline-compatible with tuning
7. **Cluster-wide default** (1.27+):
- Can set cluster-wide default via apiserver admission config
- Namespace labels override
- For "secure by default" — set cluster-wide to `baseline`; exempt specific namespaces
8. **For debugging a violation**:
- Apply workload; PSA returns specific message ("violates restricted policy: runAsNonRoot != true")
- Fix pod spec accordingly
- Re-apply; verify admission
Mark DESTRUCTIVE: switching to `enforce` without an audit phase (immediate breakage), labeling `kube-system` with `restricted` (kube-system pods often need elevation), removing PSP enforcement during migration (window of unprotection).
---
Cluster K8s version: [DESCRIBE]
Current state: [PSP still in use / no enforcement / Kyverno-Gatekeeper / mixed]
Workload complexity: [DESCRIBE — namespaces, special workloads]
Goal: [design / migrate / debug a specific violation]
Specific violation (if debugging):
```
[PASTE error message + pod spec]
```
Run this prompt with AI
Test it, get an AI-improved version, or compare models — live in the Prompt Workspace. No copy-paste.
Why this prompt works
PSA is the official PSP replacement but with a simpler model (3 levels, labels). Migration mistakes (enforce too soon, system namespaces over-restricted) cause outages. This prompt walks the standard 3-phase migration.
How to use it
- For new clusters, start with
baselinecluster-wide +restrictedfor app namespaces. - For existing clusters with PSP, run an audit phase (long) before enforce.
- Label kube-system with
privileged— always. - For debugging, the violation message tells you which field to fix.
Useful commands
# Inventory labels
kubectl get namespaces -L pod-security.kubernetes.io/enforce,pod-security.kubernetes.io/audit,pod-security.kubernetes.io/warn
# Label a namespace
kubectl label namespace <ns> \
pod-security.kubernetes.io/enforce=baseline \
pod-security.kubernetes.io/enforce-version=latest \
pod-security.kubernetes.io/audit=restricted \
pod-security.kubernetes.io/warn=restricted
# Test a workload against a level (dry-run)
kubectl apply --dry-run=server -f workload.yaml
# Find violations in audit logs
# (in audit log)
grep "pod-security" /var/log/kube-apiserver/audit.log | \
jq 'select(.annotations."pod-security.kubernetes.io/audit-violations")'
# Look for `warn` warnings from kubectl
kubectl apply -f workload.yaml
# Warning lines appear in stderr if violations exist
# Cluster-wide PSA default (advanced; apiserver admission config)
# /etc/kubernetes/admission-config/podsecurity.yaml on apiserver
Migration phases
Phase 1: Audit mode
# Label every namespace except system
for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do
case "$ns" in
kube-system|kube-public|kube-node-lease)
kubectl label namespace "$ns" pod-security.kubernetes.io/enforce=privileged --overwrite
;;
*)
kubectl label namespace "$ns" \
pod-security.kubernetes.io/audit=baseline \
pod-security.kubernetes.io/warn=baseline --overwrite
;;
esac
done
Phase 2: Find violators
# Audit log query (depends on log backend)
kubectl get events --field-selector type=Warning -A | grep PolicyViolation
# Or use third-party PSA-violation reporters
# https://github.com/kubernetes-sigs/security-profiles-operator includes some
Phase 3: Enforce
# Switch to enforce after all violations fixed
for ns in $(kubectl get ns -l 'pod-security.kubernetes.io/audit=baseline' -o jsonpath='{.items[*].metadata.name}'); do
kubectl label namespace "$ns" pod-security.kubernetes.io/enforce=baseline --overwrite
done
Spec adjustments for restricted compliance
apiVersion: v1
kind: Pod
metadata:
name: secure-app
spec:
securityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: myorg/app:v1
securityContext:
runAsUser: 1000
allowPrivilegeEscalation: false
capabilities:
drop: [ALL]
readOnlyRootFilesystem: true
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {}
Cluster-wide default config
# /etc/kubernetes/admission-config/podsecurity.yaml
apiVersion: pod-security.admission.config.k8s.io/v1
kind: PodSecurityConfiguration
defaults:
enforce: "baseline"
enforce-version: "latest"
audit: "restricted"
audit-version: "latest"
warn: "restricted"
warn-version: "latest"
exemptions:
usernames: []
runtimeClasses: []
namespaces: [kube-system]
Then in apiserver: --admission-control-config-file=/etc/kubernetes/admission-config/podsecurity.yaml.
Common findings this catches
- Workload fails admission with
runAsNonRoot != true→ set securityContext explicitly. hostPathvolume rejected by baseline → typically OK in privileged namespace; or use CSI driver instead.- kube-system pod fails → kube-system labeled too restrictively; relax to privileged.
- CNI agents (Calico, Cilium) fail → these need hostNetwork + privileged; their namespace should be privileged.
- Logging agents (Fluent Bit, Fluentd) fail → hostPath access; baseline namespace, or use kube-state-metrics + remote logging.
runAsUser: 0in restricted → set non-root UID; verify image supports it.
When to escalate
- Cluster has many legacy PSPs that don’t map cleanly to PSA levels — engage security team; may need Kyverno/Gatekeeper for fine control.
- Migration causes prolonged warnings/audits — fix violators incrementally; communicate timeline.
- Conflict between PSA and third-party policy (Kyverno restrict policies) — consolidate ownership.
Related prompts
-
Kyverno / Gatekeeper Policy Authoring Prompt
Author and debug policies for Kyverno or OPA Gatekeeper — validate, mutate, generate; audit vs enforce modes; exclusions; constraint templates.
-
Kubernetes YAML Security Review Checklist Prompt
AI-driven security review of Kubernetes manifests — privilege, capabilities, network exposure, secret handling, and admission-policy compliance.
-
Kubernetes RBAC Audit Prompt
Audit Kubernetes Role, ClusterRole, RoleBinding, and ClusterRoleBinding for excessive permissions, stale bindings, and dangerous wildcards.
-
Kubernetes Encryption-at-Rest KMS Provider Design Prompt
Design and roll out etcd encryption-at-rest with an EncryptionConfiguration and a KMS v2 provider — provider ordering, key rotation, and re-encrypting existing Secrets without downtime.
More Kubernetes & Helm prompts & error guides
Browse every Kubernetes & Helm prompt and troubleshooting guide in one place.
Reading prompts? Get all 500 in one free PDF
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.