Disk Pressure Forensics
Use this when a filesystem is full, nearly full, or df reports usage that
normal du output does not explain.
First Principles
df measures allocated blocks on the filesystem.
du measures visible directory entries from the current permissions view.
- A large
df versus du gap usually means deleted-open files, inaccessible
paths, mounts, snapshots, or accounting outside the user's view.
Diagnostic Order
- Confirm the filesystem and mount:
- Measure visible usage from a privileged view when available:
du -xhd1 <mount>
- repeat inside the largest directories
- Check deleted but still open files:
lsof +L1
- restart or stop only the specific process that owns the deleted file if the
service impact is acceptable.
- Check journal growth:
journalctl --disk-usage
- use size-based vacuuming instead of deleting journal files by hand.
- Look for un-reaped workspaces:
- old clones, worktrees, virtual environments, package caches, build outputs,
test artifacts, and temporary archives.
- Check permission blind spots:
- root-owned directories can make unprivileged
du under-report.
- suppressed errors can turn a permission problem into a false "empty" result.
Kubernetes Local-Path Trap
On single-node k3s or similar clusters, local-path PersistentVolumes,
container images, writable overlay layers, pod logs, and kubelet eviction
accounting can all share the node root filesystem. A pod may report its mounted
state path as "full" even when its PVC request looks large enough, because the
PVC is just a directory on the same root disk.
When Kubernetes reports DiskPressure=True:
- Check the node condition and kubelet summary first:
kubectl describe node <node>
kubectl get --raw /api/v1/nodes/<node>/proxy/stats/summary
- Separate
imageFs from local-path PVC usage:
- containerd image/snapshot data is usually under
/var/lib/rancher/k3s/agent/containerd
- local-path PVC data is usually under
/var/lib/rancher/k3s/storage
- If GitOps controllers are down because of disk pressure, merge the desired
source change first, then use a short controller-gap bridge that applies the
same declared manifest. Record it as bridge work, not a new source of truth.
- Stop recurring CronJobs that pull large images before trying deeper cleanup;
a failed image pull can consume the last free blocks repeatedly.
Cleanup Rules
- Prefer deleting caches, build outputs, and clearly abandoned temp work.
- Do not delete live worktrees, state directories, credentials, or logs needed
for incident reconstruction without an explicit owner decision.
- For recurring pressure, codify cleanup as a timer or job with an allowlist and
a dry-run mode.
- In Kubernetes incidents, prefer service-native cleanup before manual host
deletion:
- delete terminal
Failed / Succeeded pods when their logs have been
captured
- use
crictl rmi --prune for unused images
- prune only allowlisted rebuildable cache paths such as
.cache, .npm,
tmp, or language-server caches; do not prune databases, sessions,
credentials, queues, or archives unless they have an owner-approved backup
Done
- You can explain the
df usage with concrete evidence.
- Any cleanup target is identified by path, age, owner, and reason.
- Recurrence has either a declared guard or a recorded follow-up.
1---2name: disk-pressure-forensics3description: Use when disk usage is high, df and du disagree, or an agent must diagnose full filesystems without deleting valuable work.4---56# Disk Pressure Forensics78Use this when a filesystem is full, nearly full, or `df` reports usage that9normal `du` output does not explain.1011## First Principles1213- `df` measures allocated blocks on the filesystem.14- `du` measures visible directory entries from the current permissions view.15- A large `df` versus `du` gap usually means deleted-open files, inaccessible16 paths, mounts, snapshots, or accounting outside the user's view.1718## Diagnostic Order19201. Confirm the filesystem and mount:21 - `df -h`22 - `findmnt`232. Measure visible usage from a privileged view when available:24 - `du -xhd1 <mount>`25 - repeat inside the largest directories263. Check deleted but still open files:27 - `lsof +L1`28 - restart or stop only the specific process that owns the deleted file if the29 service impact is acceptable.304. Check journal growth:31 - `journalctl --disk-usage`32 - use size-based vacuuming instead of deleting journal files by hand.335. Look for un-reaped workspaces:34 - old clones, worktrees, virtual environments, package caches, build outputs,35 test artifacts, and temporary archives.366. Check permission blind spots:37 - root-owned directories can make unprivileged `du` under-report.38 - suppressed errors can turn a permission problem into a false "empty" result.3940## Kubernetes Local-Path Trap4142On single-node k3s or similar clusters, `local-path` PersistentVolumes,43container images, writable overlay layers, pod logs, and kubelet eviction44accounting can all share the node root filesystem. A pod may report its mounted45state path as "full" even when its PVC request looks large enough, because the46PVC is just a directory on the same root disk.4748When Kubernetes reports `DiskPressure=True`:4950- Check the node condition and kubelet summary first:51 - `kubectl describe node <node>`52 - `kubectl get --raw /api/v1/nodes/<node>/proxy/stats/summary`53- Separate `imageFs` from local-path PVC usage:54 - containerd image/snapshot data is usually under55 `/var/lib/rancher/k3s/agent/containerd`56 - local-path PVC data is usually under `/var/lib/rancher/k3s/storage`57- If GitOps controllers are down because of disk pressure, merge the desired58 source change first, then use a short controller-gap bridge that applies the59 same declared manifest. Record it as bridge work, not a new source of truth.60- Stop recurring CronJobs that pull large images before trying deeper cleanup;61 a failed image pull can consume the last free blocks repeatedly.6263## Cleanup Rules6465- Prefer deleting caches, build outputs, and clearly abandoned temp work.66- Do not delete live worktrees, state directories, credentials, or logs needed67 for incident reconstruction without an explicit owner decision.68- For recurring pressure, codify cleanup as a timer or job with an allowlist and69 a dry-run mode.70- In Kubernetes incidents, prefer service-native cleanup before manual host71 deletion:72 - delete terminal `Failed` / `Succeeded` pods when their logs have been73 captured74 - use `crictl rmi --prune` for unused images75 - prune only allowlisted rebuildable cache paths such as `.cache`, `.npm`,76 `tmp`, or language-server caches; do not prune databases, sessions,77 credentials, queues, or archives unless they have an owner-approved backup7879## Done8081- You can explain the `df` usage with concrete evidence.82- Any cleanup target is identified by path, age, owner, and reason.83- Recurrence has either a declared guard or a recorded follow-up.