how to set read-only root filesystems in Kubernetes
Explains how to set read-only root filesystems in Kubernetes so compromised pods cannot write malware or modify binaries. Use this when hardening workloads and you want an extra layer that forces all writes into explicit volumes or tmpfs. Not for workloads that legitimately need to write to their root filesystem.
TL;DR
Set readOnlyRootFilesystem: true in the container securityContext so the pod's root filesystem cannot be written to. Mount an emptyDir or tmpfs volume wherever the app needs scratch space. Most apps work fine with this once you give them a writable temp dir.
The query
how to set read-only root filesystems in KubernetesUse this when
- You are hardening Kubernetes workloads and want to block binary tampering in running pods
- A scan flags your pods for writable root filesystems
- You want defense in depth on top of non-root users and dropped capabilities
- You are writing a pod security baseline for your org
Not for
- Apps that must write to arbitrary paths at runtime; redesign their write paths first
- Replacing image scanning or admission control; this is one layer of many
- Stateful apps without volumes; give them real volumes, not a writable root
Steps
- Add the securityContext to your pod spec. Under each container set
securityContext: readOnlyRootFilesystem: true. Expected output: the manifest diff shows the new field on every container. - Give the app writable scratch space. Add an emptyDir volume mounted at /tmp (and anywhere else the app writes, like a cache dir). Expected output: the pod spec includes the emptyDir volume and its mounts.
- Deploy to a test namespace and exercise the app. Run through the app's normal flows and watch for read-only filesystem errors in the logs. Expected output: the app runs normally, no "read-only file system" errors.
- Fix the write paths that surface. Point caches and temp files at the mounted volumes instead of the container root. Expected output: all errors resolved by volume mounts, no exceptions carved out.
- Roll out per workload. Apply namespace by namespace, starting with stateless services. Expected output: the change is live on the first namespace with no incidents.
- Enforce it with policy. Add an admission rule (Kyverno, OPA, or Pod Security Standards) that rejects pods without the flag. Expected output: a test deploy missing the flag is rejected by the admission controller.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst_jalpts9mLtj9d-w8lPRV3Q
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.