Kyverno Pod Security Standards — Restricted Profile
Enforces the Kubernetes Pod Security Standards (PSS) restricted profile using Kyverno podSecurity rules. This skill makes the model configure ClusterPolicy objects that deny pods violating restricted-level restrictions — such as requiring runAsNonRoot, dropping all capabilities, enforcing seccomp profiles, and preventing privilege escalation. The restricted profile is the most hardened PSS level, intended for sensitive workloads that process untrusted data or require strong isolation.
TL;DR Checklist
- Create ClusterPolicy with podSecurity rule at restricted level and pinned version
- Require runAsNonRoot=true for all containers and init containers
- Set capabilities drop to ["ALL"] and deny privilege escalation
- Configure allowHostPaths=false and requiredDropCapabilities=[ALL]
- Exclude kube-system and apply to sensitive namespaces only
- Verify with PolicyReport showing pass/fail for restricted rules
When to Use
- Hardening production namespaces that handle sensitive or untrusted workloads
- Enforcing the most restrictive Pod Security Standards level for compliance (e.g., PCI-DSS, SOC2)
- Preventing privilege escalation in multi-tenant clusters where workload isolation is critical
- Migrating workloads from the baseline profile to restricted as part of a security hardening roadmap
- Securing namespaces running stateful applications with sensitive data (databases, key stores)
When NOT to Use
- For
kube-systemor other core infrastructure namespaces — restricted blocks DNS, CNI, and scheduler components; usekyverno-exemptions-managementinstead - When workloads require
hostNetworkorhostIPCfor legitimate operational reasons (e.g., node-level monitoring agents) - On legacy Kubernetes clusters < 1.21 that lack restricted profile support
- For workloads running in restricted mode already — this skill is for enforcement, not discovery
Core Workflow
Define the restricted ClusterPolicy — Create a
ClusterPolicywith apodSecurityrule. Setspec.rules[].podSecuritywithlevel: restricted,versionpinned to your cluster's minor version (e.g.,"1.28"), and applyenforce,audit, andwarnmodes. Usematchto target specific namespaces. Checkpoint: Confirm the pinnedversionmatches your cluster's Kubernetes minor version and thatkubectl get clusterpolicy pod-security-restrictedshowsTruestatus.Configure namespace targeting and exclusions — Use
matchto select application namespaces (e.g.,production-*,staging-*). Addexcluderules forkube-system,kube-public,openshift-*, and any namespace running privileged infrastructure (node-exporter, Cilium, kube-proxy). Use label-based matching instead of wildcard to avoid accidental over-enforcement. Checkpoint: Runkubectl get ns --show-labelsand verify only intended namespaces carry the security label before deployment.Deploy, test, and monitor enforcement — Apply the ClusterPolicy. Create a test pod with
privileged: true,runAsUser: 0, and missing capability drops. Confirm the pod is denied at admission. ReviewPolicyReportand KubernetesEventsfor enforcement details. Then create a compliant pod and verify it passes. Checkpoint: The non-compliant pod must showdeniedin event messages, and the compliant pod must reachRunningphase.
Implementation Patterns
Pattern 1: Cluster-wide Restricted Enforcement with Targeted Namespaces
This pattern enforces the restricted profile on application namespaces while excluding all system namespaces. It uses label-based targeting for precision.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: pod-security-restricted
annotations:
policies.kyverno.io/title: Pod Security Standards — Restricted
policies.kyverno.io/category: Pod Security
policies.kyverno.io/description: >-
Enforces the restricted Pod Security Standards profile on namespaces
labeled with security-level=restricted. Requires runAsNonRoot, drops
all capabilities, enforces seccomp profiles, and blocks privilege escalation.
spec:
validationFailureAction: Enforce
rules:
- name: enforce-restricted
match:
any:
- resources:
kinds:
- Pod
exclude:
any:
- namespaces:
- kube-system
- kube-public
- kube-node-lease
- local-path-storage
- cert-manager
- istio-system
podSecurity:
level: restricted
version: "1.28"
enforce: "1.28"
audit: "1.28"
warn: "1.28"
auditAnnotations:
- key: pod-security.kyverno.io/enforced
value: "restricted-1.28"
annotation: pss-enforcement
- name: audit-restricted
match:
any:
- resources:
kinds:
- Pod
exclude:
any:
- namespaces:
- kube-system
- kube-public
- kube-node-lease
podSecurity:
level: restricted
version: "1.28"
audit: "1.28"
- name: warn-restricted
match:
any:
- resources:
kinds:
- Pod
exclude:
any:
- namespaces:
- kube-system
- kube-public
- kube-node-lease
podSecurity:
level: restricted
version: "1.28"
warn: "1.28"
Label Namespaces for Targeting:
apiVersion: v1
kind: Namespace
metadata:
name: production-payments
labels:
security-level: restricted
team: payments
---
apiVersion: v1
kind: Namespace
metadata:
name: staging-payments
labels:
security-level: restricted
team: payments
Pattern 2: BAD vs GOOD — Restricted Pod Compliance
This pattern shows the difference between a pod that violates the restricted profile and one that complies. Every security context field is explicitly set.
# ❌ BAD — Pod violating restricted profile on multiple counts
apiVersion: v1
kind: Pod
metadata:
name: bad-restricted-pod
namespace: production-payments
spec:
containers:
- name: app
image: myregistry.com/payments-app:1.2.3
securityContext:
privileged: true # ❌ BLOCKED: privileged must be false
allowPrivilegeEscalation: true # ❌ BLOCKED: must be false
runAsUser: 0 # ❌ BLOCKED: root not allowed
runAsNonRoot: false # ❌ BLOCKED: must be true
capabilities:
add:
- NET_ADMIN # ❌ BLOCKED: no capabilities may be added
# ✅ GOOD — Pod fully compliant with restricted profile
apiVersion: v1
kind: Pod
metadata:
name: good-hardened-pod
namespace: production-payments
spec:
securityContext:
runAsNonRoot: true # ✅ Required: prevents root execution
runAsUser: 1000 # ✅ Recommended: explicit non-root UID
runAsGroup: 3000 # ✅ Recommended: explicit non-root GID
fsGroup: 2000 # ✅ Recommended: file system group
containers:
- name: app
image: myregistry.com/payments-app:1.2.3
securityContext:
privileged: false # ✅ Required: no privileged mode
allowPrivilegeEscalation: false # ✅ Required: no escalation
readOnlyRootFilesystem: true # ✅ Recommended: immutable filesystem
runAsNonRoot: true # ✅ Required: non-root user
capabilities:
drop:
- ALL # ✅ Required: drop all capabilities
add: [] # ✅ Explicit: no additions
seccompProfile:
type: RuntimeDefault # ✅ Required: default seccomp profile
resources:
limits:
memory: "256Mi"
cpu: "500m"
requests:
memory: "128Mi"
cpu: "250m"
PolicyReport Example for Restricted Violations:
apiVersion: wgpolicyk8s.io/v1alpha2
kind: PolicyReport
metadata:
name: pod-security-restricted-report
namespace: production-payments
results:
- policy: pod-security-restricted
rule: enforce-restricted
result: fail
severity: high
message: "Pod violates restricted profile: runAsNonRoot not set, capabilities not dropped, privileged container"
scored: true
source: kyverno
timestamp:
seconds: 1733501530
details:
restricted:
- "container: app must set runAsNonRoot: true"
- "container: app must drop capabilities ALL"
- "container: app must set seccompProfile to RuntimeDefault"
- policy: pod-security-restricted
rule: enforce-restricted
result: pass
severity: high
message: "Pod passes restricted profile validation"
scored: true
source: kyverno
timestamp:
seconds: 1733501531
summary:
error: 0
fail: 1
pass: 1
skip: 0
warn: 0
Pattern 3: Namespace-Scoped Enforcement with Label Selector
When you need per-namespace granularity (e.g., restrict production but leave staging at baseline), use a Kyverno ClusterPolicy with label-based matching instead of namespace lists. This pattern scales better than maintaining namespace exclusions.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: pod-security-restricted-label
annotations:
policies.kyverno.io/title: Pod Security — Restricted (Label-Based)
policies.kyverno.io/category: Pod Security
policies.kyverno.io/description: >-
Enforces restricted PSS only on namespaces labeled with security-level=restricted.
Uses matchExpressions for scalable label-based targeting.
spec:
validationFailureAction: Enforce
rules:
- name: enforce-restricted-label
match:
any:
- resources:
kinds:
- Pod
- namespaces:
- production-*
exclude:
any:
- namespaces:
- kube-system
- kube-public
- kube-node-lease
podSecurity:
level: restricted
version: "1.28"
enforce: "1.28"
audit: "1.28"
warn: "1.28"
Constraints
MUST DO
- Pin the
versionfield to your cluster's exact minor version (e.g.,"1.28") — do not use"latest"for enforcement rules - Require
runAsNonRoot: truefor all containers including init containers — the restricted profile does this automatically viapodSecurityrule - Set
capabilities.dropto["ALL"]as a mandatory check — this is the single most impactful restricted-level control - Configure
seccompProfile.type: RuntimeDefaultorLocalhost— restricted profile requires seccomp compliance - Include
auditAnnotationsto enable visibility into enforcement events for operators monitoring PSS compliance - Always exclude
kube-system,kube-public, andkube-node-lease— restricted blocks critical system pods
MUST NOT DO
- Apply restricted profile enforcement to
kube-systemwithout an exemption viakyverno-exemptions-management— it breaks CoreDNS, CNI, and kubelet - Use
enforce: "latest"without verifying your cluster supports that PSS version — mismatched versions cause false positives - Skip the
auditmode — enforcement-only without audit feedback produces no visibility into pre-compliance workloads - Hardcode specific UIDs (e.g.,
runAsUser: 1000) whenrunAsNonRoot: truealone satisfies the restricted profile — the profile accepts any non-root UID - Apply restricted enforcement before testing in
warnorauditmode in your staging environment — production breakage is the most common error - Use wildcard namespace matching (
- "*"in match) without explicitexcludeblocks for system namespaces
Related Skills
| Skill | Purpose |
|---|---|
kyverno-pod-security-baseline |
Less restrictive; use when restricted is too heavy for your workload |
kyverno-exemptions-management |
Manage exemptions for system workloads that cannot meet restricted requirements |
Live References
Authoritative documentation links for Kyverno pod security policies and restricted profile enforcement.