Skip to content

Life of a workspace

This page follows researcher1 from the login page to a running JupyterLab, naming every component on the way. Keep it open during lab 2.

sequenceDiagram
  autonumber
  actor R as researcher1 (browser)
  participant P as JupyterHub proxy
  participant H as JupyterHub hub
  participant K as Keycloak
  participant A as Kubernetes API
  participant Y as Kyverno / Pod Security
  participant C as Cilium
  participant W as Workspace pod
  R->>P: GET /jupyter/
  P->>H: not logged in
  H-->>R: redirect to Keycloak (authorize_url)
  R->>K: username + password
  K-->>R: redirect back with ?code=
  R->>H: /jupyter/hub/oauth_callback?code=
  H->>K: exchange code for token, call userinfo (in-cluster)
  K-->>H: preferred_username=researcher1, groups=[alpha]
  H->>H: sync JupyterHub groups to [alpha]
  R->>H: open spawn page
  H->>A: list namespaces with k8tre.io/type=project
  H-->>R: form offers "Project Alpha" only
  R->>H: start (profile=alpha, size=small)
  H->>H: pre_spawn_hook: must be in a project,<br/>profile re-checked against membership
  H->>A: create PVC home-researcher1 in project-alpha
  H->>A: create Pod jupyter-researcher1 in project-alpha
  A->>A: LimitRange defaults, ResourceQuota check
  A->>Y: validate (baseline PSS, Kyverno policies)
  Y-->>A: allowed
  A-->>H: created
  Note over A,W: scheduler binds, local-path provisions volumes,<br/>kubelet pulls image, Cilium assigns IP + identity
  C->>W: apply workspace-baseline + default-deny policies
  W->>H: jupyterhub-singleuser registers (8081) ✅
  H->>P: add route /jupyter/user/researcher1 → pod IP:8888
  R->>P: /jupyter/user/researcher1/lab
  P->>W: proxied ✅

Where each decision is made

Step Decision Configured in
8–9 Which groups the user is in Keycloak realm (gitops/keycloak/realm-tre.json), group mapper on the jupyterhub client
10 Groups copied into JupyterHub manage_groups, auth_state_groups_key in gitops/jupyterhub/values.yaml
12–13 Which projects are offered project_profiles() in gitops/jupyterhub/files/tre_config.py
15 Refuse users without a project; refuse forged profiles require_a_project() + KubeSpawner's profile validation
16 Where home directories live and how big singleuser.storage in values.yaml, StorageClass tre-user-home
17 Image, CPU, memory, namespace Namespace annotations written by gitops/projects/chart
18 Default limits, project totals limitrange.yaml, resourcequota.yaml in the project chart
19 What may run at all Namespace PSA labels, gitops/kyverno/*.yaml
21 Who may talk to the workspace and where it may connect networkpolicy.yaml in the project chart, Kyverno generate-default-deny
end When the workspace is stopped cull.timeout (1 hour idle) in values.yaml

Stopping

When the user clicks Stop My Server (or the culler stops it after an hour idle), the hub deletes the pod. The PVCs stay, so files in ~ and ~/shared are still there next time. The project's ResourceQuota usage drops straight away.