Graph
Cases4 cases
1 to 4 of 4
IL-0099User servers on 2i2c's Earthscope hub took over 15 minutes to start and kernels were killed during a workshop, because a profile option guaranteed 8 GB of memory with no limit on 32 GB nodes2i2c2025- Symptoms
On 12 May 2025 at 20:15 EEST a Freshdesk ticket reported that users' servers on the Earthscope hub were taking more than 15 minutes to start and that their kernels were being killed. It happened during a workshop and also affected other instructors using the hub; a second report said a short course of about 30 users was having major problems.
- Trigger
A workshop with about 30 users on a profile option that guaranteed 8 GB of memory and set no memory limit on 32 GB nodes.
- Root cause
- Component
- Contributing factor
- Detection
A Freshdesk support ticket from the community at 20:15 EEST, brought to the team's attention in the #support-freshdesk Slack channel at 20:49.
- Remediation
- ran a helm rollout and hub redeploy, which partly improved server starts
- made the 'medium' profile available and raised its memory guarantee to reduce overcommitment
- pre-warmed the cluster with 15 nodes for the 30-user workshop
- set explicit memory limits, with the guarantee equal to the limit, on the community's small-node profile options (https://github.com/2i2c-org/infrastructure/pull/6047)
- Action items
- Write an incident report
- Hold an internal retrospective about the incident (https://github.com/2i2c-org/meta/issues/2194)
- Lessons
A memory guarantee without a limit lets a user server grow into memory that other pods on the same node were counting on, and on a shared node that ends with users' pods evicting each other. Setting the guarantee equal to the limit removes the overcommitment. For a known workshop, pre-warming enough nodes ahead of time keeps server start times short.
IL-0070Critical pods on core nodes evicted when Prometheus began scraping about 200 nodes after a dask-gateway scale-up2i2c2023- Symptoms
The hub pod of the prod JupyterHub on the leap cluster (leap.2i2c.org) restarted unexpectedly during a large node scale-up, and a user opened a support ticket. The ingress-nginx and proxy pods kept running.
- Trigger
A user's dask-gateway workload added about 100 dask-worker nodes within a minute, and Prometheus started scraping the metrics exporters on about 200 nodes.
- Root cause
- Component
- Contributing factor
- Detection
A user support ticket (2i2c Freshdesk ticket 414) about the leap hub; the engineer then looked at Grafana and the cluster's nodes and events.
- Action items
- Configure CPU and memory requests for the hub and proxy pods (#2127; at least 100m CPU was proposed)
- Make the Grafana OOMKiller dashboard work (#2213)
- Move LEAP cloud infrastructure to shared nodes (#2209)
- Update resource requests and limits, mainly for ingress-nginx and Prometheus (#2324)
- Decide whether Prometheus should scrape dask worker pods (#2366)
- Lessons
Prometheus load grows with the number of nodes, so a burst of autoscaled nodes can push a nearly full core node over the edge and evict the pods that matter most. Core pods that request 10m of CPU get a tenth of the CPU share of busy neighbours that request 100m. Kubernetes events expire after an hour, so evidence of OOM kills needs a dashboard that keeps it.
IL-0500UToronto JupyterHub logins and server starts returned 500 errors when the hub's sqlite database disk filled up2i2c2022- Symptoms
On 31 October 2022 at 6:27 PM Pacific time, users of the UToronto JupyterHub run by 2i2c could no longer log in or start their servers, and the hub answered with 500 errors. Users who were already logged in could keep using the hub.
- Trigger
The JupyterHub log file, written to the same 10G disk as the hub's sqlite database, grew until the disk was completely full.
- Root cause
- Component
- Contributing factor
- Detection
A user emailed 2i2c support at 7:13 PM that users could not log in; the team acknowledged the issue at 8:33 PM. There was no alert for the problem.
- Remediation
- Compressed the hub log file into /tmp from a shell in the hub pod, because it could not be compressed in place on the full disk
- Copied the compressed log to a local machine so the hub pod could be restarted without losing it
- Resized the hub database disk (the hub-db-dir PVC) from 10G to 60G
- Restarted the hub pod, which came back with the larger disk and restored service
- Action items
- Stop keeping hub logs on the same disk as the hub database
- Add a Grafana graph of free space on the JupyterHub database disk
- Alert on elevated error rates
- Lessons
Kubernetes dynamic volume resizing let the hub database disk grow from 10G to 60G without much effort. The risk of keeping logs on the database disk had been identified during the earlier migration, but the team had no solid process for following it through, and because no alert existed the team had to wait for a person to report the outage.
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.
These 4 cases involve Node pool and Container memory limit. 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 exhaustion4 cases
- Component
- Contributing factor
- Organisation
IL-0099User servers on 2i2c's Earthscope hub took over 15 minutes to start and kernels were killed during a workshop, because a profile option guaranteed 8 GB of memory with no limit on 32 GB nodes2i2c2025IL-0070Critical pods on core nodes evicted when Prometheus began scraping about 200 nodes after a dask-gateway scale-up2i2c2023IL-0500UToronto JupyterHub logins and server starts returned 500 errors when the hub's sqlite database disk filled up2i2c2022IL-0094Student pods filled the shared nodes of a JupyterHub cluster and starved the hub's core pods, freezing the hub2i2c2020