💻 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.

0.0
0Reviews
P
October 9, 2026

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.

Kubernetes Pod Security Admission Rollout Planner: Namespace Labels for Baseline and Restricted, Audit and Warn First, Dry-Run Checks, securityContext Fixes, and Exemption Rules - Result

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.

Reviews (0)

Please login to leave a review.
Loading reviews...