Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Implement Kubernetes Pod Security Admission to enforce baseline and restricted security profiles at namespace level using built-in admission controller.
.claude/skills/implementing-pod-security-admission-controller/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✓→✓ | = Same ✓ | 60% | 0% |
| case-04 | ✓→✓ | = Same ✓ | 128% | 0% |
| case-05 | ✓→✓ | = Same ✓ | 140% | 0% |
| case-06 | ✓→✓ | = Same ✓ | 217% | 0% |
| case-07 | ✓→✓ | = Same ✓ | 60% | 0% |
Pod Security Admission (PSA) is a built-in Kubernetes admission controller (stable since v1.25) that enforces Pod Security Standards at the namespace level. It replaces the deprecated PodSecurityPolicy (PSP) and provides three security profiles: Privileged, Baseline, and Restricted, with three enforcement modes: enforce, audit, and warn.
AdmissionConfigurationwarn and audit first, enforce once violations reach zeroNot this skill: deciding which profile a workload should run under, or what securityContext changes Restricted demands. Use implementing-kubernetes-pod-security-standards.
| Mode | Behavior | Use Case | |------|----------|----------| | enforce | Reject pods violating policy | Production enforcement | | audit | Log violations to audit log | Pre-enforcement assessment | | warn | Show warnings to user | Developer feedback |
yaml# Restricted enforcement with audit and warn apiVersion: v1 kind: Namespace metadata: name: production labels: pod-security.kubernetes.io/enforce: restricted pod-security.kubernetes.io/enforce-version: v1.28 pod-security.kubernetes.io/audit: restricted pod-security.kubernetes.io/audit-version: v1.28 pod-security.kubernetes.io/warn: restricted pod-security.kubernetes.io/warn-version: v1.28
yaml# Baseline enforcement for staging apiVersion: v1 kind: Namespace metadata: name: staging labels: pod-security.kubernetes.io/enforce: baseline pod-security.kubernetes.io/enforce-version: v1.28 pod-security.kubernetes.io/audit: restricted pod-security.kubernetes.io/audit-version: v1.28 pod-security.kubernetes.io/warn: restricted pod-security.kubernetes.io/warn-version: v1.28
yaml# Privileged for system namespaces apiVersion: v1 kind: Namespace metadata: name: kube-system labels: pod-security.kubernetes.io/enforce: privileged
bash# Set restricted enforcement kubectl label namespace production \ pod-security.kubernetes.io/enforce=restricted \ pod-security.kubernetes.io/enforce-version=v1.28 \ pod-security.kubernetes.io/audit=restricted \ pod-security.kubernetes.io/warn=restricted # Set baseline enforcement kubectl label namespace staging \ pod-security.kubernetes.io/enforce=baseline \ pod-security.kubernetes.io/audit=restricted \ pod-security.kubernetes.io/warn=restricted # Check current labels kubectl get namespace production -o jsonpath='{.metadata.labels}' | jq .
bash# Test what would happen with restricted policy on a namespace kubectl label --dry-run=server --overwrite namespace staging \ pod-security.kubernetes.io/enforce=restricted # Output shows existing pods that would violate the policy # Warning: existing pods in namespace "staging" violate the new PodSecurity enforce level "restricted:latest"
yaml# /etc/kubernetes/psa-config.yaml apiVersion: apiserver.config.k8s.io/v1 kind: AdmissionConfiguration plugins: - name: PodSecurity configuration: 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 - kube-public - kube-node-lease - calico-system - gatekeeper-system - monitoring - falco
bash# Add to kube-apiserver manifests # /etc/kubernetes/manifests/kube-apiserver.yaml spec: containers: - command: - kube-apiserver - --admission-control-config-file=/etc/kubernetes/psa-config.yaml volumeMounts: - name: psa-config mountPath: /etc/kubernetes/psa-config.yaml readOnly: true volumes: - name: psa-config hostPath: path: /etc/kubernetes/psa-config.yaml type: File
yamlapiVersion: v1 kind: Pod metadata: name: restricted-pod namespace: production spec: securityContext: runAsNonRoot: true runAsUser: 1000 runAsGroup: 3000 fsGroup: 2000 seccompProfile: type: RuntimeDefault automountServiceAccountToken: false containers: - name: app image: myregistry/myapp:v1.0.0 securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: drop: - ALL resources: limits: cpu: 500m memory: 256Mi requests: cpu: 100m memory: 128Mi volumeMounts: - name: tmp mountPath: /tmp volumes: - name: tmp emptyDir: {}
yamlapiVersion: v1 kind: Pod metadata: name: baseline-pod namespace: staging spec: containers: - name: app image: myregistry/myapp:v1.0.0 securityContext: allowPrivilegeEscalation: false resources: limits: cpu: 500m memory: 256Mi
bash# Check existing PSPs kubectl get psp # Check which service accounts use which PSP kubectl get clusterrolebinding -o json | \ jq '.items[] | select(.roleRef.name | startswith("psp-")) | {name: .metadata.name, subjects: .subjects}'
bash# For each namespace, determine required PSA level for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do echo "Namespace: $ns" kubectl label --dry-run=server namespace $ns \ pod-security.kubernetes.io/enforce=restricted 2>&1 | head -5 done
bash# Start with audit mode kubectl label namespace production \ pod-security.kubernetes.io/audit=restricted \ pod-security.kubernetes.io/warn=restricted
bash# Check audit logs for violations kubectl get events --field-selector reason=FailedCreate -A
bashkubectl label namespace production \ pod-security.kubernetes.io/enforce=restricted
bash# Check PSA violations in events kubectl get events --all-namespaces --field-selector reason=FailedCreate # Check audit logs kubectl logs -n kube-system kube-apiserver-* | grep "pod-security.kubernetes.io" # List namespace PSA labels kubectl get namespaces -L pod-security.kubernetes.io/enforce
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | pass→pass | 17,057 | 13,371 | -22% | 1 | 1 | 0% | 2,399 | 3,834 | +60% | 0 | 0 | — |
case-02 | fail→fail | 30,359 | 29,053 | -4% | 1 | 1 | 0% | 4,494 | 6,738 | +50% | 0 | 0 | — |
case-03 | fail→fail | 22,843 | 20,791 | -9% | 1 | 1 | 0% | 3,289 | 5,524 | +68% | 0 | 0 | — |
case-04 | pass→pass | 12,117 | 9,671 | -20% | 1 | 1 | 0% | 1,388 | 3,165 | +128% | 0 | 0 | — |
case-05 | pass→pass | 12,216 | 11,109 | -9% | 1 | 1 | 0% | 1,513 | 3,624 | +140% | 0 | 0 | — |
case-06 | pass→pass | 9,581 | 9,455 | -1% | 1 | 1 | 0% | 945 | 2,996 | +217% | 0 | 0 | — |
case-07 | pass→pass | 18,708 | 12,588 | -33% | 1 | 1 | 0% | 2,408 | 3,843 | +60% | 0 | 0 | — |
case-08 | pass→pass | 14,455 | 13,123 | -9% | 1 | 1 | 0% | 1,999 | 3,714 | +86% | 0 | 0 | — |
case-09 | pass→pass | 7,610 | 13,519 | +78% | 1 | 1 | 0% | 1,593 | 3,919 | +146% | 0 | 0 | — |
case-10 | fail→fail | 21,510 | 20,061 | -7% | 1 | 1 | 0% | 2,903 | 5,061 | +74% | 0 | 0 | — |
case-11 | pass→pass | 17,005 | 11,838 | -30% | 1 | 1 | 0% | 2,620 | 3,809 | +45% | 0 | 0 | — |
case-12 | pass→pass | 10,991 | 5,026 | -54% | 1 | 1 | 0% | 1,109 | 3,159 | +185% | 0 | 0 | — |
case-13 | pass→pass | 13,674 | 11,474 | -16% | 1 | 1 | 0% | 1,582 | 3,305 | +109% | 0 | 0 | — |
case-14 | pass→pass | 19,667 | 16,437 | -16% | 1 | 1 | 0% | 2,708 | 4,382 | +62% | 0 | 0 | — |
case-15 | fail→fail | 8,244 | 5,885 | -29% | 1 | 1 | 0% | 1,629 | 3,178 | +95% | 0 | 0 | — |
case-16 | pass→pass | 12,213 | 12,753 | +4% | 1 | 1 | 0% | 2,224 | 3,682 | +66% | 0 | 0 | — |
case-17 | pass→pass | 4,986 | 3,132 | -37% | 1 | 1 | 0% | 964 | 2,865 | +197% | 0 | 0 | — |
case-18 | pass→pass | 20,210 | 18,334 | -9% | 1 | 1 | 0% | 3,585 | 5,905 | +65% | 0 | 0 | — |
case-19 | pass→pass | 13,143 | 19,056 | +45% | 1 | 1 | 0% | 2,303 | 4,630 | +101% | 0 | 0 | — |
case-20 | pass→pass | 15,222 | 17,303 | +14% | 1 | 1 | 0% | 2,597 | 5,073 | +95% | 0 | 0 | — |
case-21 | pass→pass | 6,061 | 9,898 | +63% | 1 | 1 | 0% | 945 | 3,025 | +220% | 0 | 0 | — |
case-22 | pass→pass | 13,379 | 14,605 | +9% | 1 | 1 | 0% | 2,289 | 4,733 | +107% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of 0 percentage points is the difference between those two pass rates over the 22 comparable cases.
| Model | Method | Date | Lift |
|---|---|---|---|
| gemini-3.6-flash | verified | 7/28/2026 | +14% |
Other measured skills in the registry, with their headline benchmark lift.