Pod Security Admission
Purpose: For security officers, provides PSA configuration via Kubespray including admission controller list and API server flags.
Overview
Pod Security Admission (PSA) is a built-in Kubernetes admission controller that enforces the Pod Security Standards at the namespace level. openCenter configures PSA at cluster provisioning time through Kubespray's k8s_hardening.yml, applying cluster-wide defaults that affect all namespaces unless explicitly exempted.
Configuration
PSA is configured via the following Kubespray variables in group_vars/all/k8s_hardening.yml:
# Admission controllers enabled on the API server
kube_apiserver_enable_admission_plugins:
- PodSecurity
- EventRateLimit
- AlwaysPullImages
# Pod Security Admission defaults (cluster-wide)
kube_pod_security_default_enforce: baseline
kube_pod_security_default_enforce_version: latest
kube_pod_security_default_audit: restricted
kube_pod_security_default_audit_version: latest
kube_pod_security_default_warn: restricted
kube_pod_security_default_warn_version: latest
These translate to API server flags:
--admission-control-config-file=/etc/kubernetes/admission-control/admission-control-config.yaml
Pod Security Standards
| Level | Enforcement | Behavior |
|---|---|---|
baseline | enforce | Rejects pods that violate baseline rules (privileged, hostPID, hostNetwork, etc.) |
restricted | audit | Logs violations to the API server audit log but does not reject |
restricted | warn | Returns a warning to the client (visible in kubectl output) but does not reject |
The baseline profile blocks the most dangerous pod configurations. The restricted profile is stricter (requires runAsNonRoot, drops all capabilities, restricts volume types) but is applied only in audit/warn mode to avoid breaking workloads that have not yet been hardened.
Namespace-Level Overrides
Individual namespaces can override the cluster defaults using labels:
apiVersion: v1
kind: Namespace
metadata:
name: hardened-app
labels:
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: latest
Platform namespaces (e.g., flux-system, kyverno) may require baseline or privileged enforcement depending on their workload requirements. These exemptions are documented in the cluster's overlay configuration.
Verification
Check the effective PSA configuration for a namespace:
kubectl get namespace <namespace> -o jsonpath='{.metadata.labels}' | jq .
Test a pod against the enforced profile without creating it:
kubectl run test-pod --image=nginx --dry-run=server -o yaml
If the pod violates the enforced profile, the API server returns an error. If it violates the audit/warn profile, the response includes a warning header.
Review audit log entries for PSA violations:
# On a control plane node
grep "PodSecurity" /var/log/kubernetes/audit/audit.log | tail -20
Behaviors and Edge Cases
- PSA evaluates the pod spec at admission time. Changing namespace labels does not retroactively affect running pods.
- The
latestversion tracks the cluster's Kubernetes version. Pinning to a specific version (e.g.,v1.29) freezes the policy definitions. - PSA runs before webhook-based admission controllers (Kyverno). A pod rejected by PSA never reaches Kyverno.
- The
privilegedlevel permits all pod configurations and is equivalent to disabling PSA for that namespace.
Further Reading
- Defense-in-Depth Model — how PSA fits into the overall security architecture
- Kyverno Policy Catalog — resource-level policies that complement PSA