KubernetesXLIX · VolumesVolumes
emptyDir — the ephemeral directory, its variants, and its traps
What you'll learn
- Describe how emptyDir works at the kubelet level
- Distinguish the medium options: disk vs memory
- Apply sizeLimit to bound emptyDir consumption
- Identify the eviction trap when emptyDir is too large
Prerequisites
Verified against Kubernetes 1.34.x · kubeadm 1.34.x · kubectl 1.34.x · etcd 3.6.x · CoreDNS 1.11.x · containerd 1.7.x / 2.x · 2026-08-16
emptyDir is the standard ephemeral volume type in
Kubernetes. It is created when the Pod is created,
destroyed when the Pod is destroyed, and lives on the
node’s filesystem (or in memory). This lesson walks the
options, the traps, and the production discipline.
How emptyDir works
When the kubelet starts a Pod with an emptyDir volume:
- The kubelet creates a directory under
/var/lib/kubelet/pods/<pod-uid>/volumes/kubernetes.io~empty-dir/<volume-name>/. - The kubelet bind-mounts the directory into the
container’s
volumeMountspaths. - The directory is empty when the Pod starts; the application writes to it during the Pod’s lifetime.
- When the Pod is deleted, the kubelet removes the directory.
The directory is on the node’s filesystem by default (ext4, xfs, or whatever the node’s root filesystem uses). The data is not replicated; it lives on one node.
The medium option
The medium field controls where the emptyDir lives:
volumes:
- name: scratch
emptyDir: {} # node filesystem (default)
- name: fast-scratch
emptyDir:
medium: Memory # tmpfs (RAM)
| Medium | Storage | Trade-off |
|---|---|---|
| (empty, default) | Node filesystem | Slowest, but durable across container restart. |
Memory | tmpfs (RAM) | Fastest, but data is lost on container restart. |
Memory is faster but volatile: a container restart
loses the data (the tmpfs is reinitialized). For data
that must survive container restart, use the default
medium.
sizeLimit
The sizeLimit field bounds the emptyDir’s size:
volumes:
- name: scratch
emptyDir:
sizeLimit: 1Gi
Without sizeLimit, the emptyDir can grow to the node’s
filesystem capacity. With sizeLimit, the kubelet
enforces the limit; writes beyond the limit fail.
The sizeLimit is enforced by the kubelet, not by the
kernel. The kubelet checks the emptyDir’s usage at
intervals; if usage exceeds the limit, the kubelet
evicts the Pod.
# Substitute your own value before running:
POD=web-5f9c7d8b6c-2xk9p
# Check the emptyDir's sizeLimit enforcement
kubectl describe pod "$POD" | grep -A5 "Volumes:"
# Type: EmptyDir (a temporary directory that shares a pod's lifetime)
# Medium:
# SizeLimit: 1Gi
The eviction trap
The kubelet’s eviction thresholds include
nodefs.inodesFree and nodefs.available. A Pod whose
emptyDir consumes too much disk can trigger node pressure,
which evicts Pods:
# Kubelet's eviction order under disk pressure
1. BestEffort Pods (no requests/limits)
2. Burstable Pods (requests < limits)
3. Guaranteed Pods (requests == limits)
A Pod with an unbounded emptyDir that fills the node’s disk triggers eviction of all Pods on the node, including the Pod with the offending emptyDir. The eviction is silent until the Pods restart.
When to use emptyDir
emptyDir is appropriate for:
- Scratch space: temporary files that the application creates and deletes during a single run.
- Cache: data that can be reconstructed if lost (e.g., compiled artifacts, intermediate results).
- Process state: shared state between containers in the same Pod (e.g., a sidecar that reads the main container’s output).
- Tmpfs for sensitive data: secrets that should not
touch disk (
medium: Memory).
emptyDir is not appropriate for:
- Database data (use PVC).
- Uploaded files (use PVC or object storage).
- Any data that must survive Pod deletion.
- Any data that must survive node failure.
The shared emptyDir pattern
A common pattern is two containers sharing an emptyDir:
apiVersion: v1
kind: Pod
metadata:
name: app-with-sidecar
spec:
containers:
- name: app
image: app:v1
volumeMounts:
- name: shared
mountPath: /output
- name: sidecar
image: log-forwarder:v1
volumeMounts:
- name: shared
mountPath: /input
volumes:
- name: shared
emptyDir: {}
The app writes to /output; the sidecar reads from
/input and forwards the data. Both containers see the
same directory because they share the Pod’s mount
namespace.
Quiz
Knowledge check · 4 questions
Q1. A Pod has an `emptyDir` volume with `medium: Memory`. The container restarts. What happens to the data in the emptyDir?
Q2. An emptyDir volume without `sizeLimit` can grow to fill the node's filesystem, triggering node pressure eviction.
Q3. Your team runs a workload that writes large temporary files to an emptyDir. The node has 100 GB of disk space; the workload writes 80 GB to the emptyDir. Walk through the failure mode and the fix.
Workload writes large temporary files (compilation cache) to an emptyDir. The emptyDir has no sizeLimit. The node has 100 GB total. After the workload runs, the node has 10 GB free. The kubelet reports DiskPressure.
Q4. Explain the difference between emptyDir's default medium and `medium: Memory`, and when each is appropriate.
Passing score: 75%. Answers are checked in this browser.
Production discipline
- Set
sizeLimiton every emptyDir. An unbounded emptyDir is a node-pressure waiting to happen. - Use the default medium unless you have a reason for tmpfs. Container restart loses tmpfs data.
- Do not use emptyDir for stateful data. The data is on one node’s filesystem; node failure destroys it.
- Monitor emptyDir consumption. A workload that approaches the sizeLimit triggers Pod eviction.
- Document the emptyDir usage in the Pod spec. The volume name and the sizeLimit make the intent explicit.