Kubernetes - Low disk space alerts
July 09, 2026 — LiveStream

Disclosure: some links above are affiliate links — if you buy through them I may earn a small commission at no extra cost to you. Thanks for supporting the channel!
Running into Kubernetes low disk space alerts can be a real headache, often leading to service disruptions if not addressed swiftly. This comprehensive guide will walk you through the essential steps to diagnose, troubleshoot, and effectively resolve disk space issues within your Kubernetes pods, particularly focusing on common culprits like growing log files and the tricky df vs du discrepancies.
Understanding Kubernetes Low Disk Space Alerts: Why They Matter
Imagine you're running a critical application in a Kubernetes pod. Suddenly, your monitoring system starts screaming about low disk space. What happens next? Potentially, the pod might get evicted, the application could crash, or worse, data corruption might occur. This isn't just an inconvenience; it's a direct threat to your application's availability and stability.
Kubernetes pods, by default, often utilize ephemeral storage (local disk on the node) for things like application binaries, temporary files, and crucially, logs. While convenient, this ephemeral nature means that if an application generates a lot of data, that storage can quickly fill up. Alerts are usually triggered by metrics collected from tools like Prometheus and visualized in Grafana, warning you when disk usage crosses predefined thresholds (e.g., 80% or 90%). Ignoring these alerts is like ignoring a ticking time bomb. High disk utilization can lead to:
- Pod Eviction: The Kubernetes scheduler might evict pods from a node if that node's ephemeral storage reaches capacity, leading to downtime for your application.
- Application Crashes: Many applications need scratch space or rely on writing logs to function correctly. If disk space runs out, they'll fail.
- Performance Degradation: Disk-intensive operations can slow down significantly on a full disk, impacting user experience.
- Unreliable Operations: Databases, message queues, and other stateful applications are particularly sensitive to disk space and can become unstable or corrupt data.
Common culprits for disk space hogging include:
- Log files: Especially verbose applications or those with misconfigured log rotation can fill up disks quickly.
- Temporary files: Applications might create temporary files that aren't properly cleaned up.
- Old application versions/artifacts: Sometimes, deployments might leave old code or build artifacts behind.
- Cache data: Caches that grow unbounded can also be a significant issue.
The key is to act fast and systematically. Don't just delete files blindly; understand what is consuming space and why, then apply a sustainable solution.
Diagnosing Disk Usage in a Kubernetes Pod: The Initial Investigation
When a low disk space alert hits, your first step is to get inside the affected pod and see what's going on. This is where your kubectl skills come in handy.
Getting Started: Finding Your Pod
Before you can troubleshoot, you need to identify the specific pod causing the issue. You'll typically get the pod name or deployment name from your alert, but if not, you can list pods in the relevant namespace.
kubectl get pods -n <namespacename>
Replace <namespacename> with the actual namespace your application resides in. For example, if your Vault application is in the vault namespace, you'd run:
kubectl get pods -n vault
This command will list all pods in that namespace, showing their status, age, and ready state. Find the pod that's likely causing the issue – often, it's one belonging to a deployment that's logging excessively or has been flagged by your monitoring. In our example, let's assume it's vault-0.
Executing into the Pod: Your Entry Point
Once you have the pod name, you need to "exec" into it. This allows you to run commands inside the container as if you were SSHed into a traditional server.
kubectl exec -it -n <namespacename> <pod-name> -- /bin/sh
Let's break this down:
kubectl exec: The command to execute a command in a container.-it: This combines-i(interactive) and-t(TTY – pseudo-terminal). It's crucial for getting an interactive shell experience. Without it, your commands won't execute interactively, and you won't see output or be able to type.-n <namespacename>: Specifies the namespace where the pod is running.<pod-name>: The name of your target pod, e.g.,vault-0.--: This is a separator. Any arguments after--are passed directly to the command being executed inside the container./bin/sh: The shell you want to open inside the container. Sometimes/bin/bashmight be available, but/bin/shis generally more common and guaranteed to be present in most minimal container images.
So, for our Vault example, you'd run:
kubectl exec -it -n vault vault-0 -- /bin/sh
Now you're inside the pod, ready to investigate!
The Go-To Commands: df and du
Inside the pod, the first two commands you'll reach for are df and du. They both deal with disk space, but they tell you different things, and understanding their distinction is absolutely crucial.
df -Th: Filesystem Disk Space Report
The df command (disk filesystem) reports disk space usage for filesystems mounted on the system. The options here are important:
-T: Displays the filesystem type (e.g.,ext4,xfs).-h: Shows sizes in human-readable format (e.g.,Gfor gigabytes,Mfor megabytes).
Run this command first:
df -Th
You'll see output similar to this:
Filesystem Type Size Used Avail Use% Mounted on
overlay overlay 9.8G 9.0G 312.4M 97% /
tmpfs tmpfs 64M 0 64M 0% /dev
tmpfs tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
/dev/vdb ext4 9.8G 9.0G 312.4M 97% /vault/audit
shm tmpfs 64M 0 64M 0% /dev/shm
tmpfs tmpfs 3.9G 12K 3.9G 1% /run/secrets/kubernetes.io/serviceaccount
Interpreting df output:
Filesystem: The name of the filesystem.Type: The type of filesystem (e.g.,ext4).Size: Total size of the filesystem.Used: Space currently used.Avail: Space available for use.Use%: Percentage of the filesystem used. This is often the metric that triggers your alerts.Mounted on: The directory where this filesystem is mounted.
From the example, we can see that /dev/vdb mounted on /vault/audit is at 97% usage! This immediately tells us where the problem area is – the /vault/audit directory.
du -shc /*: Directory Disk Usage Report
The du command (disk usage) estimates file space usage. Unlike df, du checks the size of files and directories from the perspective of what's actually on disk by traversing the file tree.
-s: Summarizes usage for each argument.-h: Human-readable format.-c: Displays a grand total./*: Check all top-level directories.
Now, run this to find out which specific directory within the problem mount point is consuming space:
du -shc /*
The output might look something like this (simplified):
20.0K /bin
4.0K /dev
...
9.0G /vault
...
9.1G total
This tells us that /vault is consuming almost all the space. Since df pointed to /vault/audit, let's cd into /vault and then drill down further.
cd /vault
du -shc *
This will give you a more granular view:
20.0K audit
12K bin
...
9.0G audit/vault_audit.log
...
Ah, vault_audit.log! Now we have our culprit. The df command told us where the filesystem was full (/vault/audit), and du helped us pinpoint the exact file within that directory (vault_audit.log).
Crucial Insight: When df and du Disagree
Sometimes, you might find that df -Th shows high disk usage (e.g., 97%), but du -shc /* reports significantly less (e.g., only 5GB used on a 10GB partition). This discrepancy is a critical diagnostic indicator, often pointing to a specific issue: deleted files that are still held open by a running process. When a file is deleted, its entry is removed from the directory structure, but the disk space isn't freed until all processes that have an open file handle to it release that handle. We'll cover how to handle this in a later section. For now, if df and du agree, you're on the right track!
Tackling the Root Cause: Managing Large Log Files (Vault Audit Log Example)
Now that you've identified a large log file, like vault_audit.log, consuming excessive disk space, it's time to resolve the issue. Our strategy will involve archiving the log, moving it off the pod, and then safely deleting it.
Identifying the Culprit (Revisited)
We've already established that vault_audit.log in /vault/audit is the problem. Ensure you are in the correct directory within the pod:
cd /vault/audit
You can run ls -lah here to confirm the file's size and existence.
ls -lah
Solution Strategy: Archiving and Deleting Log Files
This process assumes you need to retain the log file for compliance, auditing, or debugging purposes. If it's truly ephemeral and not needed, you could skip the transfer steps.
Step 1: Renaming for Archiving
To prevent the application from continuing to write to the massive log file while you're dealing with it, and to prepare it for archiving, rename it. Use a date-stamped format so you know exactly when it was archived.
mv vault_audit.log vault_audit_MM-DD-YYYY.log
Replace MM-DD-YYYY with the current date. For example:
mv vault_audit.log vault_audit_10-21-2021.log
Why rename?
- The application will typically create a new
vault_audit.logfile, allowing it to continue logging without interruption to the old, large file. This ensures your service keeps running while you manage the old log. - The timestamp makes it clear which archived log you are dealing with.
After renaming, you can confirm with ls -lah that the new name is visible and potentially a new (small) vault_audit.log has been created by the application.
Step 2: Securely Transferring the File Out of the Pod
Now, you need to get this renamed log file from the Kubernetes pod to your local machine (or an intermediate jump host) before it can be uploaded to long-term storage. You'll need a new terminal window for this, as your current terminal is "exec'd" into the pod.
kubectl cp <namespace>/<pod-name>:/path/to/pod/file /local/path/on/your/machine
Using our example:
kubectl cp vault/vault-0:/vault/audit/vault_audit_10-21-2021.log /home/joe/vault_audit_10-21-2021.log
vault/vault-0: Combines the namespace (vault) and pod name (vault-0)./vault/audit/vault_audit_10-21-2021.log: The full path to the renamed log file inside the pod./home/joe/vault_audit_10-21-2021.log: The destination path and filename on your local machine.
Monitoring the transfer: For large files, kubectl cp can take a while. To see its progress in real-time, open yet another terminal tab and navigate to your local destination folder.
cd /home/joe
watch ls -lah
The watch command will continuously execute ls -lah every 2 seconds by default, showing you the growing size of the file as it transfers. Once the file size stabilizes and matches the size reported by ls -lah inside the pod (before renaming), the transfer is complete.
Step 3: Offloading to S3 (or Similar Cloud Storage)
Once the file is safely on your local machine, it's time to upload it to long-term, cost-effective cloud storage like AWS S3. This step typically involves logging into your cloud provider's console or using their CLI tools.
For AWS S3, you would:
- Log in to the AWS Management Console.
- Navigate to the S3 service.
- Locate the appropriate S3 bucket and desired prefix (folder structure), e.g.,
metricgaming-eu-west-2-prod-logs > topics/ > vault-audit-log/. - Upload the
vault_audit_10-21-2021.logfile from your local machine to this location.
If you prefer command-line tools for automation or larger files, you could use the AWS CLI:
aws s3 cp /home/joe/vault_audit_10-21-2021.log s3://metricgaming-eu-west-2-prod-logs/topics/vault-audit-log/vault_audit_10-21-2021.log
This ensures the file is preserved for future needs and frees up your local machine's space.
Step 4: Deleting the Archived File from the Pod
With the log file safely offloaded to S3, you can now delete the original archived file from the pod. Switch back to your terminal where you are "exec'd" into the pod.
rm vault_audit_10-21-2021.log
Verification is key: After deletion, immediately run df -Th to confirm the disk space has been freed up. You should see a significant drop in Use% for the /vault/audit mount point.
Filesystem Type Size Used Avail Use% Mounted on
/dev/vdb ext4 9.8G 36.0M 9.2G 0% /vault/audit
This looks much better! The disk space has been reclaimed.
Finally, ensure your application is happily writing to a new, smaller vault_audit.log by checking the directory again:
watch ls -lah
You should see a vault_audit.log file present, and its size should be growing steadily but slowly, indicating normal operation.
When df and du Disagree: Handling Deleted Files Held Open by Processes
This is where things get a bit more advanced, but it's a very common scenario in containerized environments. As we discussed earlier, if df -Th shows high disk usage but du -shc /* (or du -shc * after cding into problem directories) reports significantly less, it's almost certainly because files have been deleted from the filesystem but are still being held open by a running process. This prevents the operating system from actually freeing up the disk blocks.
The Problem Explained
When a process opens a file, it gets a file descriptor. Even if another process (or you, using rm) deletes that file, the actual data blocks on the disk won't be released until all processes holding an open descriptor to that file close it. In Kubernetes, this often happens with logging. A log file might be periodically rotated and deleted by a log rotation tool, but if the application process continues to write to the old, deleted inode (the file descriptor it initially opened), the space remains consumed.
Identifying Open Deleted Files with lsof
To find these phantom files, we use the lsof (list open files) command.
lsof 2>/dev/null | grep deleted
Let's break this down:
lsof: Lists all open files and the processes that own them.2>/dev/null: Redirects standard error (usually permission denied errors) to/dev/nullto keep the output clean.grep deleted: Filters the output to show only lines containing the string "deleted".
The output will look something like this:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
vault 12 vault 3w REG 259,1 912345678 12345 /vault/audit/vault_audit.log.old (deleted)
Interpreting lsof output:
COMMAND: The name of the process holding the file.PID: The Process ID of the holding process. This is what we need!USER: The user running the process.FD: File Descriptor.3wmeans file descriptor 3, opened for writing.TYPE: Type of file (REG for regular file).DEVICE,SIZE/OFF,NODE: Technical details about the file.NAME: The name and path of the file, crucially followed by(deleted).
In our example, the vault process with PID 12 is holding open a vault_audit.log.old file that has been deleted. This is the reason df still reports high usage!
The Solution: Restarting/Killing the Holding Process
The only way to free up the disk space held by these deleted files is for the process holding them to release its file descriptor. This usually means restarting the application or, as a last resort, killing the process.
Caution is paramount here. Killing a process can lead to application downtime. Always explore graceful restart options first, if available for your application or Kubernetes deployment. For example, if it's a deployment, you might consider kubectl rollout restart deployment/<deployment-name> which gracefully terminates and restarts pods.
However, if you're in an emergency situation and a graceful restart isn't immediately possible or effective, or if it's a standalone process, you might need to kill it.
Identify the PID from the lsof output (e.g., 12 for the vault process).
kill -9 12
kill: The command to send signals to processes.-9: TheSIGKILLsignal. This is a "non-catchable, non-ignorable kill." It forcefully terminates the process. Use it with care!
A more robust way to kill all processes holding deleted files (if you're sure you want to do this for all of them in the container):
lsof | grep "deleted" | awk '{print $2}' | xargs kill -9
Let's break this powerful one-liner:
lsof | grep "deleted": Finds all lines with "deleted" files.awk '{print $2}': Extracts the second column from each line, which is the PID.xargs kill -9: Takes the PIDs fromawkand passes them as arguments tokill -9.
After killing the process, it's highly likely your application in that pod will restart (if managed by a Deployment, StatefulSet, etc.) or simply stop. If it's a stateful application, be prepared for recovery procedures.
Verification
Once the process holding the deleted file is terminated, the disk space should be freed. Verify this immediately with df -Th:
df -Th
You should now see the Use% drop significantly for the affected filesystem.
Filesystem Type Size Used Avail Use% Mounted on
/dev/vdb ext4 9.8G 36.0M 9.2G 0% /vault/audit
This confirms the disk space has been reclaimed.
Proactive Measures and Best Practices to Prevent Low Disk Space
While reactive troubleshooting is essential, implementing proactive measures is key to preventing these incidents in the first place.
- Log Rotation Policies: This is probably the most crucial step. Configure your applications or use tools like
logrotatewithin containers to automatically rotate, compress, and delete old log files. For Kubernetes, consider configuring your container runtime's logging driver (e.g., Docker'sjson-filedriver hasmax-sizeandmax-fileoptions) or integrating with a sidecar pattern for log management. - Centralized Logging Solutions: Instead of storing logs directly in pods, push them to a centralized logging system like Elasticsearch, Splunk, Loki, or Graylog. This decouples log storage from pod ephemeral storage, making pods leaner and more resilient. Tools like Fluentd or Filebeat can be deployed as DaemonSets to collect and forward logs efficiently.
- Monitoring and Alerting: Ensure you have robust monitoring in place (e.g., Prometheus with node-exporter) to collect disk usage metrics and configure alerts in Grafana or Alertmanager to notify you well before critical thresholds are reached. Monitor both
Use%and inode usage. - Resource Requests and Limits (Ephemeral Storage): For Kubernetes 1.8+, you can set
ephemeral-storagerequests and limits in your pod definitions. This allows the scheduler to ensure nodes have enough local storage for pods and prevents a single rogue pod from consuming all node storage.resources: limits: cpu: "1" memory: "1Gi" ephemeral-storage: "5Gi" # Limit ephemeral storage to 5GB requests: cpu: "500m" memory: "512Mi" ephemeral-storage: "2Gi" # Request 2GB of ephemeral storage - Persistent Volumes for Stateful Data: For applications requiring persistent storage (databases, message queues, etc.), always use Persistent Volumes (PVs) and Persistent Volume Claims (PVCs) rather than relying on ephemeral storage. This ensures data survives pod restarts and provides dedicated, expandable storage.
- Application-Level Cleanup: Implement garbage collection or cleanup routines within your applications for temporary files, cache data, or old build artifacts that might accumulate over time.
- Regular Audits: Periodically audit your deployments for applications known to be verbose or those that might have misconfigured logging.
By adopting these best practices, you can significantly reduce the frequency and impact of Kubernetes low disk space alerts, ensuring your clusters run smoothly and reliably.
Key Takeaways
- Act Quickly: Low disk space can lead to pod eviction and service disruption; immediate diagnosis is crucial.
dfvs.du: Usedf -Thto see filesystem usage and identify the mounted point, thendu -shc /*(and subsequentcdanddu) to pinpoint the exact file or directory consuming space.- Log Management: For large log files, rename, transfer out of the pod (e.g.,
kubectl cpto local, then upload to S3), and then safely delete. df/duDiscrepancy: Ifdfreports high usage butdudoesn't, deleted files held open by processes are the likely cause.lsofandkill -9: Uselsof | grep deletedto find processes holding open deleted files, andkill -9 <PID>(or theawkone-liner) to release the disk space (with caution).- Proactive Prevention: Implement log rotation, centralized logging, ephemeral storage limits, and robust monitoring to prevent future disk space issues.
Frequently Asked Questions
What is ephemeral storage in Kubernetes?
Ephemeral storage refers to the temporary, non-persistent local disk space available to a pod. It's tied to the pod's lifecycle and typically resides on the node where the pod runs. If a pod restarts or is rescheduled to another node, any data stored in its ephemeral storage is lost. This storage is commonly used for things like container images, application binaries, and, crucially, logs and temporary files.
Why is df showing high disk usage while du shows less?
This discrepancy almost always indicates that files have been deleted from the filesystem, but one or more processes are still holding open file descriptors to those deleted files. Until all processes release their hold, the operating system cannot free the disk blocks associated with those files, and df will continue to report them as "used" space. lsof is the command to diagnose this.
How can I prevent logs from filling up my Kubernetes pods?
The best approaches include implementing log rotation policies within your containers, configuring your container runtime's logging drivers (e.g., max-size, max-file for Docker), and migrating to a centralized logging solution (like ELK stack, Loki, Splunk) where logs are streamed off the pods to dedicated storage. You can also set ephemeral storage limits in your pod specifications.
Is it safe to kill -9 a process in a Kubernetes pod?
Executing kill -9 is a forceful termination and should be considered a last resort. It does not allow the process to shut down gracefully, potentially leading to data corruption or incomplete operations. If the pod is managed by a Deployment or StatefulSet, Kubernetes will likely restart it, but there might be a brief service interruption. Always try to identify the cause, gracefully restart the application or the pod (kubectl rollout restart deployment/<name>), and only use kill -9 if other options are exhausted and you understand the potential impact.
Facing disk space issues in Kubernetes can be daunting, but with the right tools and a systematic approach, you can quickly identify and resolve them. The key is to understand your environment, know your commands, and always prioritize proactive measures. For a visual walkthrough of these steps and more practical insights, make sure to check out the original video on the @explorenystream channel. Don't forget to subscribe for more expert DevOps content!