Pod security contexts and admission

Kubernetes · Advanced · 10 min

A container escape usually starts with a privileged or root container; defaults are too permissive.

The securityContext (pod-level and per container) controls what a container may do:

  • runAsNonRoot: true, runAsUser: 10001: never run as UID 0.
  • allowPrivilegeEscalation: false: blocks setuid tricks.
  • readOnlyRootFilesystem: true: write only to mounted volumes (emptyDir for /tmp).
  • capabilities: {drop: ["ALL"]}: remove Linux capabilities, adding back only what's needed (NET_BIND_SERVICE).
  • seccompProfile: {type: RuntimeDefault}: filter dangerous syscalls.
  • Never privileged: true, hostPID, hostNetwork or hostPath mounts for ordinary apps.

Pod Security Admission (built in) enforces the Pod Security Standards per namespace via labels:

  • privileged: no restrictions (system namespaces),
  • baseline: blocks known privilege escalations (privileged, host namespaces, hostPath),
  • restricted: requires the hardened settings above.

Each level can be applied in enforce (reject), audit (log) or warn (kubectl warning) mode, so you can roll out restricted gradually.

For custom rules (allowed registries, required labels, no latest tags) use ValidatingAdmissionPolicy with CEL expressions (built in) or a policy engine like Kyverno or OPA Gatekeeper.

Example

# kubectl label ns shop pod-security.kubernetes.io/enforce=restricted \
#   pod-security.kubernetes.io/warn=restricted
apiVersion: v1
kind: Pod
metadata: {name: api, namespace: shop}
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 10001
    seccompProfile: {type: RuntimeDefault}
  containers:
    - name: api
      image: ghcr.io/acme/api:2.1.0
      securityContext:
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        capabilities: {drop: ["ALL"]}
      volumeMounts: [{name: tmp, mountPath: /tmp}]
  volumes: [{name: tmp, emptyDir: {}}]

Remember

  • Non-root, no escalation, drop all capabilities, read-only root FS, RuntimeDefault seccomp
  • Pod Security Admission: privileged/baseline/restricted per namespace
  • warn/audit modes let you roll out safely

Watch out for

  • Images that need root to start: build them to run as a non-root user instead of relaxing the namespace.

Check yourself

  1. A namespace enforces restricted. A pod without allowPrivilegeEscalation: false is applied. What happens?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: kubernetes.io/docs/concepts/security/pod-security-standards/