CKAD field manual
k8s SecurityContext YAML example
Linux splits “root” into capabilities (bind :80, load modules, …). These fields take them away from the container process. drop ALL, then add only what the question names.
apiVersion: v1
kind: Pod
metadata:
name: locked
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000
containers:
- name: app
image: nginx:1.27
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
add: ["NET_BIND_SERVICE"]
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
add: ["NET_BIND_SERVICE"]
resources:
requests:
cpu: "100m"
memory: 128Mi
limits:
cpu: "200m"
memory: 256Mi
Fields
- securityContext
- On spec: who the process is (user/group) for every container. On a container: what that process may do.
- runAsNonRoot
- Uid must not be 0. Fails if the image USER is 0 and you did not set runAsUser.
- runAsUser
- Numeric uid for the process. Pair with runAsNonRoot so the image cannot sneak back to 0.
- fsGroup
- Pod field. Volume files get this gid so a non-root process can read them.
- allowPrivilegeEscalation
- false = the process cannot gain extra privileges later (setuid to root is blocked). Container-only.
- readOnlyRootFilesystem
- true = `/` is read-only. The process cannot write into the image. Mount emptyDir on /tmp if it needs scratch.
- capabilities
- Slices of root. A container starts with a default set, not zero. drop ALL, then add what the question names.
- drop
- drop: [ALL] first. That removes NET_ADMIN, SYS_ADMIN, CHOWN — every extra power.
- add
- After drop ALL, give back only this. NET_BIND_SERVICE = bind ports below 1024 (80, 443) without being root.
- requests
- What the scheduler guarantees. The Pod will not start without it.
- limits
- Cap. Over memory limit → OOMKilled.
Watch
- Pod securityContext = who (runAsUser, fsGroup) for every container. Container securityContext = what that process may do. allowPrivilegeEscalation, capabilities, and readOnlyRootFilesystem are container-only — the API rejects them on the Pod.
- allowPrivilegeEscalation: false — the process cannot become more privileged after start. A setuid binary cannot jump to root. runAsNonRoot alone does not block that.
- readOnlyRootFilesystem: true — `/` cannot be written. The process cannot drop files into the image. If it needs /tmp, mount an emptyDir there.
- capabilities are slices of root. A container starts with a default set, not none. drop: [ALL] removes every one. add: [NET_BIND_SERVICE] gives back only “bind TCP/UDP ports below 1024” so a uid 1000 process can still listen on :80.
- runAsNonRoot: true fails if the image runs as 0 and you did not set runAsUser.
Official docs Security Context