SecurityContext and Pod Security

Kubernetes · lesson 26 of 32 · 4 min read

Drop root and capabilities in the pod, then let the namespace reject anything that did not.

Open this lesson in the learning hub

Key points

  • runAsNonRoot: true plus a numeric runAsUser means a container escape does not start life as root.
  • readOnlyRootFilesystem: true with an emptyDir mounted at /tmp is usually all a JVM service needs.
  • Drop every capability, then add back only what you genuinely use. Most Java applications need none of them.
  • Pod Security Admission enforces the baseline and restricted profiles from two labels on the namespace, with no extra components.
  • Roll it out as warn and audit first, read what would have broken, and only then switch to enforce.
  • allowPrivilegeEscalation: false and seccompProfile: RuntimeDefault are the two cheapest wins on the list.

Example

apiVersion: v1
kind: Namespace
metadata:
  name: prod
  labels:
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/warn: restricted
---
spec:
  securityContext:                 # pod level
    runAsNonRoot: true
    runAsUser: 10001
    fsGroup: 10001
    seccompProfile:
      type: RuntimeDefault
  containers:
    - name: app
      image: ghcr.io/acme/orders:1.4.2
      securityContext:             # container level
        allowPrivilegeEscalation: false
        readOnlyRootFilesystem: true
        capabilities:
          drop: ["ALL"]
      volumeMounts:
        - name: tmp
          mountPath: /tmp          # the JVM still needs somewhere to write
  volumes:
    - name: tmp
      emptyDir: {}

Non-root, read-only, no capabilities - then have the namespace enforce it for you.

This is a reading copy. The full lesson — with the visual explainer, the interactive lab and a Run button for the code — lives in the Kubernetes course, and every lesson in it is listed on the Kubernetes contents page.