Cases3 cases
1 to 3 of 3
- Symptoms
A Kubernetes worker node paged with NodeFilesystemFilesFillingUp, the node_exporter mixin alert that predicts a filesystem will run out of inodes. The engineer checked disk space first: df -h showed the root filesystem 83% used, 103G used and 22G available. df -i showed inodes 67% used, 11M used and 5.3M free.
- Trigger
Several versions of a single-stage Node.js image, each shipping more than 40,000 files, were held on the node; containerd unpacked every layer with a distinct digest into its own snapshot, each with a full copy of node_modules.
- Root cause
- Component
- Contributing factor
- Detection
The NodeFilesystemFilesFillingUp alert from the node_exporter mixin fired on the predicted inode trend while inode use was at 67%.
- Action items
- Build the image in multiple stages so the final image contains only the compiled assets
- Add a flat alert on root filesystem inode use above 80% for 30 minutes alongside the predictive alert
- Put a Prometheus query on a dashboard that shows, per node, inode usage minus disk usage, sorted from the highest
- Remove unused images from nodes with crictl rmi --prune to free old snapshots
- Lessons
kubelet's background cleanup works on bytes only. A workload heavy in small files gets no early intervention for inodes, and the first thing kubelet does at 5% free inodes is evict pods. Watch inode use on nodes separately from disk use, and keep dependency trees out of runtime images.
- Symptoms
On 30 May 2019, in the run-up to the Kubernetes 1.15 code freeze, Prow test jobs in the k8s-prow-build cluster failed in surprising ways or were aborted partway through. Jobs were reported to GitHub as failed while Deck still showed them as running, because pods exited without uploading `finished.json`, the file most Prow tooling uses to tell a job's state.
- Trigger
A spike in test load before the Kubernetes 1.15 code freeze pushed disk I/O on the build nodes far beyond the IOPS that GCP allows for 250 GB disks.
- Root cause
- Component
- Contributing factor
- Detection
Several users reported jobs that GitHub showed as failed but Deck showed as still running, and the first report came on Slack at 13:26. Alerting for these failures did not exist or did not work.
- Remediation
- Requested and received additional disk quota
- Brought up 55 nodes with 500 GB disks in a new node pool
- Migrated all nodes from the 250 GB disk pool to the 500 GB disk pool by draining old nodes, finishing at 23:55
- Action items
- Create or fix monitoring so the oncall is paged when tide stops doing things
- Set a process and guidelines for adding new members to the oncall rotation, with preparation and extra support
- Lessons
Prow metrics were not recorded before the incident, which made it hard to understand, and alerting for these failures did not exist or did not work. After the cause was found and a fix devised, nothing happened for another two hours. The team counts it as luck that someone who recognised IOPS as the problem happened to be around to look.
IL-0040Parallel Helm installs saturated small gp2 root volumes on a kops cluster and left all three workers NotReady with the kubelet or Docker downSaltside2017- Symptoms
While running the CI process on a local machine to test an application Helm chart, the SRE lead watched the pods with watch kubectl get pods. All pods reached Running, and then some went back to Pending. Two hours later the problem had grown and some pods showed the phase Unknown.
- Trigger
A CI run installed the application's Helm charts for all four markets (Efritin.com, Tonaton.com, Ikman.lk and Bikroy.com) on the nonproduction cluster at the same time.
- Root cause
- Component
- Contributing factor
- Detection
The SRE lead saw pods go from Running back to Pending while watching kubectl get pods during the CI run; no monitoring raised an alert, even when all three workers were not ready.
- Remediation
- terminated the three worker nodes and let the auto scaling group replace them
- Action items
- Fix the Datadog integration for the nonproduction AWS account and repeat the installs with telemetry
- Increase the worker root EBS volumes from 20GB to 120GB
- Keep common base images pulled on every node with a DaemonSet until kops supports user hooks
- Configure different allocation limits for the different layers in Kubernetes
- Discuss a highly available Tiller with the Helm team
- Find a way to throttle the number of newly created pods
- Lessons
An ordinary deploy of the application could collapse the cluster, because the default 20GB gp2 root volumes could not keep up with parallel image pulls and container starts. Without node metrics and pod phase metrics, three NotReady workers raised no alert. A single Tiller replica can block the deploy that would fix an outage.
These 3 cases involve kubelet and Node root disk. kubegap audits a Kubernetes cluster for gaps like these, read-only, from Claude Code or Codex; its checks cite public reports like the ones in this library.
By root cause1
Capacity exhaustion3 cases
- Contributing factor
IL-0071Worker node running out of inodes while disk space looked fine, because containerd kept a full node_modules tree in each of several image layer snapshotsIL-0401Prow jobs on the k8s-prow-build GKE cluster failed and merges stalled as nodes hit IOPS throttling and kernel panicsIL-0040Parallel Helm installs saturated small gp2 root volumes on a kops cluster and left all three workers NotReady with the kubelet or Docker downSaltside2017