How do two containers in the same Kubernetes pod share files through an emptyDir volume, and does that data survive a container crash?
answer
- one directory, many mounts
- lifetime of the pod, not container
- kubelet creates it at pod setup
- restart keeps it, reschedule wipes it
- sizeLimit, else the node disk fills
basics
~20 sAn emptyDir is an empty directory the kubelet creates when the pod starts on a node. Every container that mounts it sees the same files. It lasts as long as the pod, so a container crash and restart keeps the data.
solid answer
~40 sYou declare the volume once under `spec.volumes` with `emptyDir: {}`, and each container that needs it lists it in `volumeMounts`, at any `mountPath` it likes. The kubelet creates the directory when the pod is set up on the node, and every container, init containers included, reads and writes the same files. Its lifetime is the **pod's**, not the container's. If a container crashes and the kubelet restarts it under the pod's `restartPolicy`, the files are still there. The directory is removed only when the pod leaves the node: it is deleted, evicted or rescheduled. It is scratch space and a hand-off point between containers, such as an init container that downloads input for the main container. It is not a place for data that must outlive the pod.
code
yaml · 28 linesapiVersion: v1
kind: Pod
metadata:
name: ocr-worker-7f3k
spec:
initContainers:
- name: fetch-scan
image: registry.example.com/ocr/fetcher:2.4.1
args: ["--out", "/work/in"]
volumeMounts:
- name: work
mountPath: /work
containers:
- name: ocr
image: registry.example.com/ocr/engine:5.3.0
volumeMounts:
- name: work
mountPath: /work
- name: uploader
image: registry.example.com/ocr/uploader:1.8.2
volumeMounts:
- name: work
mountPath: /work
readOnly: true
volumes:
- name: work
emptyDir:
sizeLimit: 6Gigo deeper
Remember three facts: the volume is declared once and mounted by many containers, it starts empty, and it lives exactly as long as the pod. A container restart keeps it; deleting the pod removes it.
Explain why the directory is keyed to the pod UID, so a Deployment's replacement pod always starts empty, and how init containers use the volume to hand input to the app containers.
Show you size it: sizeLimit and ephemeral-storage requests so one pod's scratch cannot fill a node disk, read-only mounts for consumer containers, and apps that tolerate their own partial files after a restart.
Frame emptyDir as a platform default: a writable scratch mount that lets teams keep read-only root filesystems. Set the limits and guidance that stop it from quietly becoming a place where durable data is stored.
## What an emptyDir is A Kubernetes **volume** is a directory that is declared in the pod spec and mounted into one or more containers. An **emptyDir** is the simplest kind: - It starts **empty** when the pod is set up on a node. - The **kubelet** creates it, by default on the node's disk under the kubelet's working directory. - Every container in the pod that lists it in `volumeMounts` sees **the same directory**. Each container can mount it at a different `mountPath`. That shared directory is how containers in one pod pass files to each other. A container's own root filesystem is private to that container, and another container cannot see what was written into it. ## A worked example: a document-OCR worker pod Take a document-OCR pipeline in which each worker pod handles one scanned batch: 1. An **init container** `fetch-scan` downloads the scanned PDF pages into `/work/in` and exits. 2. The main `ocr` container reads `/work/in` and writes recognised text to `/work/out`. 3. A second long-running container, `uploader`, mounts the same volume **read-only** and ships `/work/out` to the results store. All three mount one emptyDir named `work`. The init container's files are still there when the app containers start, because the volume belongs to the pod and not to any single container. ## What survives what The key point for interviews is that the volume's lifetime equals the **pod's lifetime on its node**. | Event | emptyDir contents | |---|---| | A container crashes and the kubelet restarts it | **Kept**: the pod is the same pod | | A container is OOM-killed and restarted | **Kept** | | The pod is deleted, for example by `kubectl delete pod` or a rollout | **Removed** | | The pod is evicted or rescheduled to another node | **Removed**: the replacement is a new pod with a new, empty directory | | The data was on a memory-backed (`medium: Memory`) emptyDir and the node reboots | **Lost** with the node's RAM | A Deployment's replacement pod is a **new pod** with a new UID, so it always starts with an empty directory, even if the scheduler places it on the same node. ## How it compares with the other ephemeral volume kinds emptyDir is one of several volume kinds whose lifetime is tied to the pod or to the node rather than to a PersistentVolume: | Kind | Where the bytes live | Typical use | |---|---|---| | `emptyDir` | Node disk, or RAM with `medium: Memory` | Scratch space, hand-off between containers | | `hostPath` | An existing path on the node itself | Node agents that must read the host; a last resort for apps | | `projected` / `downwardAPI` | Files the kubelet writes from API data | Tokens, config files, pod metadata | | Generic ephemeral (`ephemeral.volumeClaimTemplate`) | A dynamically provisioned volume, deleted with the pod | Large per-pod scratch space served by a storage driver | **hostPath** looks similar but works differently. It exposes an existing node directory, so its data outlives the pod and a pod on a different node sees different data. Mounting parts of the host into a container also lets that container reach node files, which is why platform teams restrict it. ## Practical rules - Set `sizeLimit` on disk-backed emptyDirs. If usage goes over it, the kubelet evicts the pod. Without it, one pod's scratch can fill the node's disk. - Declare `resources.requests.ephemeral-storage` on containers that write heavily so the scheduler accounts for that disk. - Mount the volume `readOnly: true` in containers that only consume the files. - Anything that must survive the pod, such as results or checkpoints, belongs in a PersistentVolumeClaim or an external store, not in an emptyDir. - An emptyDir is the usual fix for a read-only root filesystem: mount one at `/tmp` or at the app's cache path. ```yaml apiVersion: v1 kind: Pod metadata: name: ocr-worker-7f3k spec: volumes: - name: work emptyDir: sizeLimit: 6Gi ```
- The OCR container is OOM-killed halfway through a batch. What does it find in the emptyDir when it restarts?It finds everything written before the kill: the input pages from the init container and any partial output. The kubelet restarted the container inside the **same pod**, and an emptyDir lives as long as the pod. The app should therefore handle leftovers from its own earlier attempt, for example by writing to a temporary name and renaming when done. Otherwise a restart can pick up a half-written file.
- Why does a replacement pod created by a Deployment start with an empty emptyDir, even if it lands on the same node?The replacement is a **new pod object** with a new UID, and the kubelet keys emptyDir directories by pod. When the old pod was removed, its directory was cleaned up with it. Same-node placement does not matter, because the volume never belonged to the node or to the Deployment.
An emptyDir is a whiteboard in a meeting room that is booked for one meeting. People can step out and come back and the notes are still there, but the room is wiped once the booking ends.
saying these in an interview costs you the question
- Says each container gets its own separate copy of an emptyDir
- Believes emptyDir data is wiped every time a container restarts
- Expects a rescheduled pod to find its emptyDir data on the new node
- Uses emptyDir for data that must outlive the pod, such as results
- Thinks emptyDir is a directory shared with the host like hostPath
- Never sets sizeLimit, so one pod's scratch can fill the node disk