Skip to main content
RunBook Academy

KubernetesXLIX · VolumesVolumes

emptyDir — the ephemeral directory, its variants, and its traps

Advanced⏱ ~16 minkubectl

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

Not yet marked complete on this device.

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:

  1. The kubelet creates a directory under /var/lib/kubelet/pods/<pod-uid>/volumes/kubernetes.io~empty-dir/<volume-name>/.
  2. The kubelet bind-mounts the directory into the container’s volumeMounts paths.
  3. The directory is empty when the Pod starts; the application writes to it during the Pod’s lifetime.
  4. 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)
MediumStorageTrade-off
(empty, default)Node filesystemSlowest, but durable across container restart.
Memorytmpfs (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

  1. Q1. A Pod has an `emptyDir` volume with `medium: Memory`. The container restarts. What happens to the data in the emptyDir?

  2. Q2. An emptyDir volume without `sizeLimit` can grow to fill the node's filesystem, triggering node pressure eviction.

  3. 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.

  4. 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 sizeLimit on 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.