Incident Library

IL-0500 2i2c · 2022-10-31kubernetesdatabase

UToronto JupyterHub logins and server starts returned 500 errors when the hub's sqlite database disk filled up

The UToronto JupyterHub stored its hub logs on the same 10G disk as the hub's sqlite database. It was the only hub run by 2i2c with this layout. The commit that set it up during an earlier migration noted that the layout was not ideal and only copied the hub's prior configuration; the write-up says the likely reason was that the hub did not use Azure for logging at all and the team wanted to keep detailed logs for analytics. The risk had been identified during that migration, but there was no process to follow it through. The log file eventually filled the disk, database operations could no longer succeed, and hub logins and server starts failed from 6:27 PM until about 9:00 PM Pacific time, 2 hours 33 minutes in all.

Once the issue was acknowledged, the hub logs made the cause clear. The log file could not be compressed in place on the full disk, so an engineer opened a shell in the hub pod with kubectl exec and gzipped jupyterhub.log into /tmp, which cut its size by about ten times; the log was kept rather than deleted in case it was needed for analytics. Deleting the uncompressed file would not free space while the JupyterHub process still held it open, so the hub process had to restart, and because a pod restart would also lose /tmp, the compressed file was first copied to a local machine with kubectl cp. While the copy ran, the hub-db-dir PVC was edited from 10G to 60G, so that a single pod restart applied the resize too. The hub pod restarted at 8:59 PM with the larger disk and service came back. The compressed log was copied back to the hub disk at 10:01 PM, and the hub kept writing its logs to that disk after the incident.

Severity
–
Scope
UToronto JupyterHub: new logins and server starts failed with 500 errors; users already logged in kept working
Users affected
UToronto JupyterHub users who were not already logged in
Region
–
Time to detect
46m
Time to resolve
2h 33m

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.

The hub pod's logs contained "Rolling back session due to database error" from JupyterHub, followed by a SQLAlchemy traceback that ended in "sqlite3.OperationalError: database or disk is full".

Nothing alerted on the problem. A user emailed 2i2c support at 7:13 PM, the team acknowledged the issue at 8:33 PM, and at 8:47 PM the hub logs and the hub configuration showed that the hub's log file and its sqlite database shared one disk, and that the disk was full. The start time was worked out later from Grafana logs of the last successful login.

Symptom High error ratePersistent volume full

Root cause

Trigger
The JupyterHub log file, written to the same 10G disk as the hub's sqlite database, grew until the disk was completely full.

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

Action items

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.

Sources

References

Related cases

Check your cluster for this

kubegap audits a Kubernetes cluster for conditions like the ones in this case, Database, Persistent volumes and stateful sets, JupyterHub among them, read-only, from Claude Code or Codex. Its checks cite public reports like this one.

For AI tools and scripts

The API needs no key. The MCP server offers search_incidents, get_incident, list_incidents, get_topic and vocab; both are explained on API and MCP.