💻 Coding
Kubernetes Pod Security Admission Rollout Planner: Namespace Labels for Baseline and Restricted, Audit and Warn First, Dry-Run Checks, securityContext Fixes, and Exemption Rules
Plan a Pod Security Admission rollout for a Kubernetes cluster: pick baseline or restricted per namespace, roll out with warn and audit labels before enforce, run server side dry-run label checks, fix workload securityContext fields to pass restricted, and keep exemptions narrow and documented.
0Reviews
Prompt
Act as a Kubernetes platform engineer who rolls out Pod Security Admission (PSA) across clusters after the removal of PodSecurityPolicy in Kubernetes 1.25, without breaking running workloads. Inputs: - Cluster details: Kubernetes version, distribution (EKS, GKE, AKS, on prem), and whether a policy engine like Kyverno or Gatekeeper is also running: [ClusterInfo] - Namespaces with owner team and workload types (web apps, jobs, DaemonSets, operators, CI runners): [NamespaceList] - Current warnings or violations, pasted from kubectl label dry-run output or audit logs: [CurrentViolations] - Workload specs or securityContext snippets that fail today: [WorkloadSpecs] - Exceptions the team believes it needs (privileged agents, host networking, CNI or CSI drivers): [ExceptionRequests] - Rollout window and change process: [RolloutWindow] - Output format: [Format] Generate: 1. A target level per namespace from NamespaceList: privileged, baseline, or restricted, with the reason, and pod-security.kubernetes.io version labels pinned to the cluster minor version from ClusterInfo. 2. A phased label plan: warn and audit at the target level first, enforce later, with the exact kubectl label commands per phase. 3. Dry-run checks: kubectl label --dry-run=server --overwrite commands per namespace and how to read the warnings in CurrentViolations. 4. securityContext fixes for each spec in WorkloadSpecs to meet restricted: runAsNonRoot, allowPrivilegeEscalation false, capabilities drop ALL, seccompProfile RuntimeDefault, and no hostPath or host namespaces, as YAML patches. 5. An exemption plan from ExceptionRequests: keep system agents in a namespace labeled privileged, or use the AdmissionConfiguration exemptions (usernames, runtimeClasses, namespaces) only where the distribution allows it, each with an owner and review date. 6. A rollout calendar inside RolloutWindow with a rollback step (remove or relax the enforce label). 7. A check for overlap with any policy engine in ClusterInfo so rules do not conflict. Constraints: - Use only namespaces, specs, and violations in the inputs; do not invent workload names. - Never move a namespace to enforce before its warnings are cleared or exempted. - Keep YAML valid and minimal. No em dashes.
Instructions
Replace every [bracket] with your details before running. Works on ChatGPT, Claude, and Gemini.
Generated Output
This image was generated using the prompt above.

Examples
Example Input
ClusterInfo: EKS, Kubernetes 1.30, no Kyverno or Gatekeeper, PSP already removed during the 1.25 upgrade, no PSA labels set yet NamespaceList: - payments-api (team Payments): Deployments, web API - reports (team Data): CronJobs that write to S3 - ci-runners (team Platform): GitLab runners that build images with Docker in Docker - monitoring (team Platform): node exporter DaemonSet with hostNetwork and hostPID, Prometheus CurrentViolations (from kubectl label --dry-run=server --overwrite ns payments-api pod-security.kubernetes.io/enforce=restricted): Warning: existing pods in namespace "payments-api" violate the new PodSecurity enforce level "restricted:latest" Warning: api-7c9f-xk2: allowPrivilegeEscalation != false, unrestricted capabilities, runAsNonRoot != true, seccompProfile WorkloadSpecs: payments-api container has no securityContext; image runs as user 1000 already per Dockerfile USER 1000 ExceptionRequests: ci-runners needs privileged for Docker in Docker; monitoring needs hostNetwork and hostPID RolloutWindow: two weeks, change tickets required, Tuesday and Thursday deploys only Format: levels, label phases, dry-run, YAML fixes, exemptions, calendar, overlap
Example Output
TARGET LEVELS (version pinned to v1.30)
| Namespace | Target | Reason |
| payments-api | restricted | Plain web API; image already runs as UID 1000 |
| reports | restricted | CronJobs with no host access needed; verify with dry-run |
| ci-runners | privileged | Docker in Docker needs privileged; plan to move to rootless builds later |
| monitoring | privileged | node exporter uses hostNetwork and hostPID; keep it isolated here |
LABEL PHASES
Phase 1 (warn and audit only):
kubectl label --overwrite ns payments-api pod-security.kubernetes.io/warn=restricted pod-security.kubernetes.io/warn-version=v1.30 pod-security.kubernetes.io/audit=restricted pod-security.kubernetes.io/audit-version=v1.30
kubectl label --overwrite ns reports pod-security.kubernetes.io/warn=restricted pod-security.kubernetes.io/warn-version=v1.30 pod-security.kubernetes.io/audit=restricted pod-security.kubernetes.io/audit-version=v1.30
kubectl label --overwrite ns ci-runners pod-security.kubernetes.io/enforce=privileged pod-security.kubernetes.io/enforce-version=v1.30
kubectl label --overwrite ns monitoring pod-security.kubernetes.io/enforce=privileged pod-security.kubernetes.io/enforce-version=v1.30
Phase 2 (enforce, after warnings are cleared):
kubectl label --overwrite ns payments-api pod-security.kubernetes.io/enforce=restricted pod-security.kubernetes.io/enforce-version=v1.30
kubectl label --overwrite ns reports pod-security.kubernetes.io/enforce=restricted pod-security.kubernetes.io/enforce-version=v1.30
DRY-RUN CHECKS
kubectl label --dry-run=server --overwrite ns payments-api pod-security.kubernetes.io/enforce=restricted
kubectl label --dry-run=server --overwrite ns reports pod-security.kubernetes.io/enforce=restricted
Reading the payments-api warning: four fields fail on pod api-7c9f-xk2: allowPrivilegeEscalation, capabilities, runAsNonRoot, seccompProfile. All four are fixed by the patch below. Pin the version in the dry-run too (enforce-version=v1.30) so "latest" does not change results after an upgrade.
YAML FIX (payments-api Deployment)
spec:
template:
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
seccompProfile:
type: RuntimeDefault
containers:
- name: api
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
If the app writes to local disk, add an emptyDir volume rather than running as root.
EXEMPTIONS
- ci-runners and monitoring stay in namespaces labeled privileged. No cluster wide exemptions needed.
- EKS does not let you edit the API server AdmissionConfiguration, so namespace labels are the exemption tool here.
- Owners and review: ci-runners, team Platform, review in 90 days with a rootless build plan; monitoring, team Platform, review in 90 days.
- Keep these namespaces locked down with RBAC so other teams cannot deploy into them.
CALENDAR
- Week 1 Tue: Phase 1 labels on all four namespaces (change ticket).
- Week 1 Thu: payments-api deploy with the securityContext patch; rerun dry-run.
- Week 2 Tue: reports dry-run; fix any CronJob warnings.
- Week 2 Thu: Phase 2 enforce on payments-api and reports once dry-run shows no warnings.
Rollback: kubectl label --overwrite ns <name> pod-security.kubernetes.io/enforce=baseline (or remove the enforce label) and file a ticket.
POLICY ENGINE OVERLAP
No Kyverno or Gatekeeper, so PSA is the only pod admission control. If one is added later, avoid duplicate rules for the same fields.