Incident Library

IL-0506 UC Berkeley · 2017-02-09kubernetesdatabase

UC Berkeley DataHub logins failed and students got empty home directories after the JupyterHub database was overwritten

Shortly after midnight on 9 February 2017, an operator debugging earlier 400 errors opened a shell in the DataHub hub pod, installed sqlite3, attached jupyterhub.sqlite and changed a user's server entry to see whether a wrong value would cause a problem. When nothing changed for the account, the operator started sqlite3 again without attaching the database and ran `.save jupyterhub.sqlite`, which overwrote the database file with an empty one; sqlite3 does this without any confirmation. All tables were gone. Users who logged in got new user ids, and because PVC names were built from the user id, the hub gave them new, empty disks.

At 1:28 AM the hub was scaled to 0 replicas and the team rebuilt the sqlite database from the Kubernetes PVCs, whose names contain a sanitized form of the username and the user id. The rebuilt database was attached at 2:42 AM and the admin page showed about 1000 users again. In the rebuild, cookie_id was left empty for many users, although JupyterHub expects it always to be a uuid, and everyone with an empty cookie_id was logged in as the first such user in the table. Changing one character near the end of the cookie secret had no effect, because JupyterHub uses only part of the secret; changing one at the beginning did log everyone out. In the meantime students were advised to use ds8.berkeley.edu, which crashed because it lacked resources for a data8-level class.

At 10:45 AM a script filled in cookie_id for all users, the hub was restarted and all user pods were deleted, and most users were back. Users with a '.' in their name had been rebuilt with a '-' instead, so those users attached to new empty PVCs; at 11:15 AM a script dropped the new users with '.' and renamed the older '-' users to use '.'. The all-clear was given at 11:17 AM.

Severity
–
Scope
UC Berkeley DataHub: logins failed with proxy errors, users saw empty home directories, and some were logged in as another user
Users affected
DataHub users, about 1000 accounts
Region
–
Time to detect
35m
Time to resolve
10h 52m

Symptoms

At about 1 AM on 9 February 2017, UC Berkeley's DataHub was reported down: users trying to log in got a proxy error. The hub pod was running, but its log was full of sqlite errors.

From 0:25:59 AM the hub logs showed "sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: proxies", and the same error followed for the hub table, the two tables used most often.

At 1:12 AM a student could log in but found all his notebooks gone. The JupyterHub admin panel listed only about 50 users where there had been about 1000, and `kubectl get pvc` showed that the student now had two PVCs, one 21 days old and one 5 minutes old: the hub had created a new account and a new, empty persistent disk because it had lost track of the old one.

After the database was rebuilt, some users were logged in as one particular other user. Changing the cookie secret and deleting all user pods logged everyone out but did not stop it. Later, users with a '.' in their username still got an empty home directory after everyone else was fine.

Symptom Service outageData lossMisrouted requests

Root cause

Trigger
While debugging, an operator ran `.save jupyterhub.sqlite` in sqlite3 inside the hub pod without having attached the database, which replaced the JupyterHub database file with an empty one.

Detection

DataHub was reported down at about 1 AM, when users got a proxy error at login. At 1:12 AM a user reported that he could log in but all his notebooks were gone.

Remediation

Action items

Lessons

–

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.