A hardened securityContext runs the container as a non-root user, disallows privilege escalation, mounts the root filesystem read-only, drops all Linux capabilities and uses the runtime's default seccomp profile. These settings line up with the Restricted Pod Security Standard, so they also help you pass admission checks.
Pod level versus container level
The securityContext under spec applies to all containers in the pod. A securityContext on a container applies to that container only, and per the Kubernetes docs it overrides the pod setting where both exist. Put user, group and seccomp at pod level, and the container-specific hardening at container level.
The checklist
Copy this and adjust the user IDs:
spec:
securityContext:
runAsUser: 1000
runAsGroup: 3000
runAsNonRoot: true
fsGroup: 2000
seccompProfile:
type: RuntimeDefault
containers:
- name: app
image: registry.example.com/app:1.4.2
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
privileged: false
capabilities:
drop: ["ALL"]
What each does:
- runAsUser and runAsGroup: all container processes run with that UID and primary GID. The docs note that if runAsGroup is omitted, the primary group is root.
- runAsNonRoot: the kubelet refuses to start a container that would run as UID 0.
- fsGroup: adds a supplementary group to processes and sets group ownership on volumes.
- allowPrivilegeEscalation: false: controls the no_new_privs flag. It defaults to true when unset, so you must set it.
- readOnlyRootFilesystem: mounts the root filesystem read-only. Writable paths must come from volumes.
- capabilities drop ALL: removes Linux capabilities. Add back only what the process needs, such as NET_BIND_SERVICE for ports below 1024.
- seccompProfile RuntimeDefault: applies the container runtime's default filter.
Things that break and how to fix them
The app writes to its own directory. Mount an emptyDir at that path, or at tmp.
The app binds port 80. Move it to 8080, or add NET_BIND_SERVICE back.
Files are owned by root. Rebuild the image with a USER instruction and correct ownership, or set fsGroup for mounted volumes.
The docs warn that the user or group must have the permissions the application needs, and a mismatch causes file access failures.
Verify
Check the effective user in a running pod:
kubectl exec -it POD_NAME -- id
The output shows uid, gid and groups. Then check admission with Pod Security labels in warn mode, as covered in Pod Security admission rollout.
Safeguard policies and gates can check manifests in the pull request for these fields, so a missing setting is caught in review.
Rolling it out across many workloads
Do not edit fifty manifests by hand. Put the settings in a shared Helm values file or a kustomize base, and let each service override only what it must. Add a policy check in CI that fails when a manifest omits the fields, and list the exceptions in one place with owners and dates.
Quick check
Is runAsNonRoot enough on its own?
No. It does not stop privilege escalation or remove capabilities. Set the full list.
Do I need all of these in every pod?
Aim for yes. Document any exception, such as an added capability, with the reason.
Sources
- Configure a Security Context for a Pod or Container, Kubernetes documentation
- Pod Security Standards
Last reviewed: 19 October 2026.