Cases6 cases
1 to 5 of 6
IL-0129Throughput of the 384-GPU SmolLM3 pretraining run collapsed because shared WekaFS storage evicted dataset shards to S3, then kept dropping on local NVMe because the nanotron dataloader built an index that grew with the step countHugging Face2025- Symptoms
Within hours of launching the full SmolLM3 pretraining run (3B parameters, 11T tokens, 384 H100 GPUs on 48 nodes), training throughput fell steeply, with repeated sharp drops. The team expected a steady 13,500 to 14,000 tokens per second, and none of the throughput ablations run beforehand on the same 48 nodes had shown drops.
- Trigger
Launching the full run with the whole ~24 TB dataset on shared WekaFS storage and the real step count for 11T tokens, both far larger than in the ablation runs.
- Root cause
- Component
- Contributing factor
- Detection
The team watched training throughput in tokens per second and saw it fall within hours of launch; node-monitoring metrics then tied the large fall to spikes in disk read latency.
- Remediation
- moved the training data from WekaFS to the local NVMe RAID scratch storage on each node
- copied the dataset to replacement nodes from a healthy node with fpsync, cutting the copy from 3 hours to 1.5 hours
- kept a spare node with the dataset preloaded in the Slurm reservation to swap in when a node failed
- reproduced the drops on a single node and with step counts of about 3M and 32k to rule out hardware and isolate the step count
- replaced nanotron's nanosets dataloader with the TokenizedBytes dataloader copied from the SmolLM2 setup, which removed the drops
- pre-shuffled the tokenized sequences offline for each epoch with different seeds (about 1 hour) to fix the noisier loss from TokenizedBytes
- Lessons
Ablations on data subsets and a short step horizon did not exercise either cause: a shared cache-and-evict filesystem near its capacity, and a dataloader index that grows with the step count. Reproducing the drops on one node separated hardware from software, and varying only the step count pointed at the dataloader. The team chose proven replacements over repairs under deadline pressure, taking an existing dataloader instead of fixing nanosets and offline shuffling instead of changing the dataloader, and warns that too many such shortcuts leave a patchwork system that is hard to maintain.
IL-0006VPC subnets ran out of IP addresses because the AWS VPC CNI kept IPs on full nodes, and WARM_IP_TARGET changes then blocked pod starts after every pod deletionNeon2025- Symptoms
On 16 May 2025, in Neon's Kubernetes cluster in AWS us-east-1, new compute pods were scheduled but could not start and failed with IP allocation errors. Each Neon compute is a Postgres database running in a lightweight virtual machine in its own pod, so without new pods, idle customer databases could not be woken up.
- Trigger
On 16 May the Neon control plane's periodic job that terminates idle computes started failing. Compute creations continued, and the number of active computes rose from about 5k to about 8.1k within minutes. On 19 May, a follow-up change that set WARM_IP_TARGET back to 1 started the second round of failures.
- Root cause
- Component
- Contributing factor
- Detection
As cluster-autoscaler added nodes, the team saw IP allocation errors on new pods that were scheduled but could not start. The rate of successful pod starts and VPC subnet metrics were then used to follow the problem.
- Remediation
- Set WARM_IP_TARGET=1 to release IPs held by nodes without free CPU or memory
- Fixed the control plane's periodic job so idle computes were terminated again
- Restarted the aws-node DaemonSet several times, each with a temporary improvement
- Set WARM_IP_TARGET=0, MINIMUM_IP_TARGET=0 and WARM_ENI_TARGET=0, which let nodes allocate enough IPs and stabilised the cluster
- On 19 May, set WARM_IP_TARGET back to 0 after setting it to 1 failed again
- Enlarged the pool of pre-created warm compute pods to absorb failed pod starts
- Action items
- Open a pull request to AWS CNI to improve how ipamd releases IPs in this situation
- Follow up with AWS Support about the roughly 100 subnet IPs that were never allocated, for reasons Neon could not explain
- Change the architecture to support horizontal scaling
- Lessons
With default settings AWS CNI can keep many IPs on nodes that cannot use them, so the share of subnet IPs assigned to pods does not tell how close the subnet is to running out. WARM_IP_TARGET and WARM_ENI_TARGET follow different logic, a warm IP target of zero switches to the ENI logic, and IPs in cooldown count toward the target, which behaves badly under high pod churn. Changing these settings during an incident without knowing that logic prolonged the outage, and reverting a setting did not bring back the earlier healthy state.
IL-0094Student pods filled the shared nodes of a JupyterHub cluster and starved the hub's core pods, freezing the hub2i2c2020- Symptoms
At 08:52 PM IST a report came in from WER that many students could not access the JupyterHub and that it was frozen; pages were stuck and nothing was usable. A rise in activity was visible by 09:02 PM, but the usual fixes, such as opening an incognito window and restarting servers, did not help.
- Trigger
WER students' pods used a good chunk of their memory limit (tests had shown they almost always use just under 1G of their 2G limit, against a 512M guarantee) on nodes shared with the hub's core pods.
- Root cause
- Component
- Contributing factor
- Detection
WER reported stuck pages and students unable to reach the hub in a GitHub issue (2i2c-org/docs#27).
- Remediation
- removed memory overcommit for the WER students
- raised resource guarantees for all core pods, which restarted them and moved some to a new node
- Action items
- Put user pods in a separate pool so they do not create pressure on the core pods (infrastructure#89)
- Set limits on the support infrastructure (Prometheus, Grafana, ingress) as well (infrastructure#90)
- Document and think about overcommit ratios for memory usage (infrastructure#91)
- Set up better Grafana dashboards to monitor resource usage (infrastructure#92)
- Document how people can get kubectl access to the cluster so others can look into issues too (infrastructure#87)
- Lessons
Core pods without resource guarantees get whatever is left on a node, so when user pods on the same nodes fill the CPU and memory, the hub that serves everyone freezes. The memory overcommit ratio has to come from measured use: WER students used just under 1G against a 512M guarantee, which a 4x overcommit could not hold.
IL-0064CPU-heavy pods packed onto one Google Cloud node drove it to kernel panics, and the crash moved from node to node until the site was downMoonlight2019- Symptoms
On Friday, January 18, Moonlight's API began returning occasional errors that looked like connection problems with its Redis database. The API checks Redis on every authenticated request to validate the session. At the same time the Kubernetes monitoring reported some nodes and pods as unresponsive.
- Trigger
The Kubernetes scheduler put several CPU-heavy pods on the same node, including all three replicas of the website and the server-side rendering pods.
- Root cause
- Component
- Contributing factor
- Detection
API errors that looked like Redis connectivity problems, and Kubernetes monitoring that showed nodes and pods as unresponsive. Google Cloud Support later found the link between sustained 100% CPU and kernel panics.
- Remediation
- added anti-affinity rules to all major deployments so their pods spread across nodes
- Action items
- Keep working with Google Cloud support to find and fix the cause of the node kernel panics
- Lessons
Three replicas give no fault tolerance if the scheduler places them all on one node; anti-affinity rules make the spread explicit. A node failure that comes from the workload itself moves with the workload when the scheduler reschedules it.
IL-0075Kubernetes API servers pegged on CPU when the cluster grew to about 290 nodes, traced to Datadog agents polling the APICivis Analytics2019- Symptoms
After Civis released its new script infrastructure on Kubernetes internally in September 2018, developers reported that kubectl commands were slow, and users intermittently could not start notebooks and services.
- Trigger
Migrating clients' Python, R and container scripts from the in-house Bocce system to Kubernetes (the project called Croquet) pushed the cluster to about 290 EC2 instances under a large script load.
- Root cause
- Component
- Contributing factor
- Detection
Developer reports of slow kubectl commands and user reports of notebooks and services failing to start, then high CPU on the master nodes.
- Remediation
- moved internal users back to the old Bocce infrastructure
- resized the three master nodes from m4.large to m4.4xlarge
- changed the Datadog setup so per-node agents no longer polled the API server for service metadata
- raised max-requests-inflight for non-mutating requests from 400 to 1200
- grew the etcd EBS volumes from 20 to 100 GB (100 to 300 IOPS)
- switched client scripts from the ClusterFirst DNS policy to Default
- Action items
- Upgrade etcd from 2.2.1 to 3.x once Kops supports a safe migration
- Solve the in-cluster DNS timeouts so client scripts can talk to other workloads in the cluster
- Lessons
Kubernetes can reach thousands of nodes only after tuning, and third-party DaemonSets are a common cause of control plane load: an agent on every node that polls or watches the API server multiplies with the cluster size. Datadog, kube2iam and the fluentd metadata filter all showed this. A small configuration change often fixes it, but finding it took load testing and the API server access logs.
These 6 cases involve Pod scheduling and placement and Cluster autoscaler. 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 exhaustion6 cases
- Component
- Contributing factor
- Unverified assumption6Automation amplification2Excessive blast radius2No capacity planning2Unreviewed defaults1Unknown limit1Harmful manual action1Monitoring blind spot1No resource requests or limits1Overlapping failures1Retry storm1Ineffective rollback1Single point of failure1Unrepresentative staging1
IL-0129Throughput of the 384-GPU SmolLM3 pretraining run collapsed because shared WekaFS storage evicted dataset shards to S3, then kept dropping on local NVMe because the nanotron dataloader built an index that grew with the step countHugging Face2025IL-0006VPC subnets ran out of IP addresses because the AWS VPC CNI kept IPs on full nodes, and WARM_IP_TARGET changes then blocked pod starts after every pod deletionNeon2025IL-0094Student pods filled the shared nodes of a JupyterHub cluster and starved the hub's core pods, freezing the hub2i2c2020IL-0064CPU-heavy pods packed onto one Google Cloud node drove it to kernel panics, and the crash moved from node to node until the site was downMoonlight2019IL-0075Kubernetes API servers pegged on CPU when the cluster grew to about 290 nodes, traced to Datadog agents polling the APICivis Analytics2019IL-0036A reindex Job that kept failing exhausted one node after another until the whole cluster was downUniverse2017