Jupyter Server restart terminates active kernels: diagnosing kernel-state continuity during migration
0 reputation · 22 Jul 2021, 15:18 UTC
0 reputation · 22 Jul 2021, 15:18 UTC
A small Jupyter deployment requires migration to a new host while keeping user-visible downtime minimal. The goal is to cut over routes and sessions with as little interruption as possible, specifically for active notebook kernels.
Core Jupyter Server behavior dictates that a server process restart terminates all child kernels, since kernels are not persisted in memory across restarts. The documented jupyter_server REST API (/api/kernels, /api/contents) can inventory active sessions and autosaved notebook content, but it does not provide a mechanism to checkpoint or migrate in-memory kernel state. JupyterHub rolling restarts with container-based spawners can start new pods before old ones stop, reducing perceived downtime for new logins, yet kernel variables and execution state are still lost. This creates an unresolved decision: whether to accept a brief maintenance window with expected kernel-state reset, or to invest in an external orchestration layer that decouples kernels from the server lifecycle--core Jupyter offers no built-in live kernel migration.
What is the minimal acceptable duration of kernel-state interruption during a proxy-cutover migration? Can the /api/kernels and /api/contents endpoints reliably prompt users to save state before a planned restart? Is it feasible to externalize kernel state without a custom spawner, given core Jupyter's current API surface?
35275 reputation · 22 Jul 2021, 19:27 UTC
Minimal interruption duration: 30–120 seconds for proxy cutover plus kernel restart time. Zero-downtime kernel migration is not achievable with core Jupyter Server alone.
API reliability for user prompting: /api/kernels and /api/contents reliably enumerate active kernels and verify notebook checkpoints, but they cannot automate kernel-state save. Users must manually execute checkpoint code (e.g., %store, pickle, explicit notebook save) before the maintenance window.
Externalizing kernel state without a custom spawner: Not feasible with core Jupyter's current API surface. Options require deployment changes: Jupyter Kernel Gateway / Enterprise Gateway (kernels in separate pods), ipykernel's experimental checkpointing (IPython 8+, not production-ready), or a custom kernel manager proxying to persistent kernel processes.
GET /api/kernels returns kernel metadata (id, name, last_activity, connections). GET /api/contents returns notebook file contents including autosaved checkpoints (default interval 120 s). Neither endpoint provides a checkpoint, snapshot, or migration API for in-memory kernel state.If your deployment uses a reverse proxy (nginx, Traefik, Kubernetes Service) for the cutover, TCP connection draining can be sub-second. The dominant latency is kernel process startup on the new host and client-side reconnection logic (JupyterLab/Notebook 7+ auto-reconnect). Expect 30–120 seconds total interruption per kernel.
GET /api/kernels to list active kernels per user. Call GET /api/contents to verify each notebook has a recent checkpoint.%store -r, pickle.dump, or File → Save and Checkpoint).connections count to drop to zero on each kernel (or enforce a hard timeout).Are you running JupyterHub with a spawner that supports named servers or kernel gateway integration (e.g., KubeSpawner with kernel_gateway_enabled)? If yes, kernels can survive single-user server restarts, and the migration strategy shifts to draining the gateway instead of the server. If no, the above maintenance-window approach is the only core-Jupyter path.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.