Aller au contenu

JupyterHub

Aperçu

JupyterHub fournit l'environnement de notebooks multi-utilisateurs pour AKKO, accessible à https://lab.akko.local. Il authentifie les utilisateurs via Identité (Keycloak) SSO et lance des pods Kubernetes individuels (akko-notebook) par utilisateur, chacun équipé d'une boîte à outils complète pour l'ingénierie et l'analyse de données.

Architecture

                Keycloak SSO
                    |
           +--------+--------+
           |   JupyterHub    |  (image akko-jupyterhub)
           |  lab.akko.local   |
           +--------+--------+
                    |  KubeSpawner
        +-----------+-----------+
        |           |           |
   +---------+ +---------+ +---------+
   | alice   | |  bob    | | carol   |  (conteneurs akko-notebook)
   | notebook| | notebook| | notebook|
   +---------+ +---------+ +---------+
  • JupyterHub fonctionne comme un service hub central derrière Traefik.
  • KubeSpawner crée un pod akko-notebook par utilisateur authentifié.
  • Chaque pod utilisateur dispose de 6 Go de RAM et 2 CPU maximum.
  • Le travail de chaque utilisateur est persisté dans un PersistentVolumeClaim : akko-user-{username}.

Noyaux disponibles

Noyau Version Notes
Python 3 base scipy-notebook Noyau par défaut, stack données complet
R (IRkernel) R système + tidyverse, sf, DBI, RPostgres Prêt pour le géospatial
Julia (IJulia) 1.11.3 Packages DataFrames, CSV pré-installés
Scala 2.13 (Almond) 0.14.0-RC15 Pour les développeurs Moteur de calcul (Spark) Scala, REPL Ammonite

Choisir sa version de Python

Au lancement d'un serveur, l'écran de spawn propose un menu déroulant Stack. La même image slim (Python + JupyterLab + code-server) est publiée pour trois interpréteurs Python : vous choisissez celui dont votre projet a besoin.

Choix Interpréteur Tag d'image
JupyterLab · Python 3.11 Python 3.11 akko-notebook-slim:py3.11-<date>
JupyterLab · Python 3.12 (recommandé) Python 3.12 akko-notebook-slim:py3.12-<date>
JupyterLab · Python 3.13 Python 3.13 akko-notebook-slim:py3.13-<date>
Polyglotte Python 3.12 + R + Julia + Scala + Quarto akko-notebook-full:py3.12-<date>

Chaque image est taggée py<MAJEUR.MINEUR>-<date> (immuable, reproductible). La ligne Python est un argument de build (NB_BASE) : le même Dockerfile produit les trois images — voir helm/scripts/build-notebooks-matrix.sh.

Vérifier l'interpréteur depuis un notebook :

import sys
print(sys.version)   # ex. 3.13.x pour le profil Python 3.13

Base Python 3.11

L'upstream jupyter/scipy-notebook ne publie plus de tag python-3.11.x récent ; AKKO épingle le dernier conservé (python-3.11.10). La ligne 3.11 est donc gelée sur cette base — reproductible, mais sa couche OS est plus ancienne que les lignes 3.12 / 3.13. Préférez 3.12 (recommandé) ou 3.13 pour les nouveaux projets.

Packages Python pré-installés

L'image akko-notebook embarque un stack complet d'ingénierie de données :

Ingénierie de données & Lakehouse

Package Fonction
pyspark 3.5.1 Client Spark Connect
trino Pilote Python DB-API pour Moteur de requête (Trino)
pyiceberg[s3fs] Client Python Apache Iceberg
duckdb Base de données analytique embarquée
polars Bibliothèque DataFrame rapide
pandas Bibliothèque DataFrame (depuis la base scipy-notebook)
pyarrow Format colonnaire en mémoire
dbt-core + dbt-trino Framework de transformation de données
sqlalchemy + sqlalchemy-trino Boîte à outils SQL avec dialecte Moteur de requête
boto3 SDK AWS/object storage S3
psycopg2-binary Pilote PostgreSQL

Analytique & Visualisation

Package Fonction
altair Visualisation statistique déclarative
plotly Graphiques interactifs
folium Cartes Leaflet.js
geopandas DataFrames géospatiales
great-expectations Validation de la qualité des données

IA & LLM

Package Fonction
jupyter-ai[all] Assistant IA dans JupyterLab
langchain + langchain-ollama Framework d'orchestration LLM
langchain-community Intégrations communautaires

Extensions JupyterLab

Extension Fonction
jupyterlab-git Intégration Git
jupyterlab-lsp Language Server Protocol
jupyterlab-execute-time Affichage du temps d'exécution des cellules
jupyterlab-code-formatter Formatage Black + isort
jupyterlab-favorites Barre latérale de fichiers favoris
jupyterlab-mermaid Rendu de diagrammes Mermaid (architecture, flux, diagrammes ER) directement dans les notebooks
jupyter-resource-usage Indicateur d'utilisation RAM/CPU
ipywidgets Widgets interactifs

code-server (VS Code dans le navigateur)

Chaque conteneur notebook inclut code-server, offrant une expérience VS Code complète dans le navigateur. Il est accessible via le lanceur JupyterLab ou le chemin proxy /code-server.

Extensions pré-installées :

  • Langages : Python, R, Julia, Scala (kernel Almond), Go
  • Données : SQLTools (pilotes PostgreSQL + Moteur de requête), Rainbow CSV, Data Table viewer
  • dbt : dbt Power User
  • DevOps : Docker, REST Client, GitLens, Error Lens
  • Quarto : Extension Quarto pour la rédaction de rapports
  • Diagrammes : Mermaid (diagrammes inline dans les notebooks et les cellules Markdown)
  • Thème : Dracula + Material Icon Theme

Extensions système

Les extensions sont installées dans /opt/code-server-extensions (système, immuables) et liées symboliquement dans le répertoire personnel de chaque utilisateur au démarrage du conteneur via un hook before-notebook.d.

Publication Quarto

Quarto (v1.6.43) est pré-installé pour la rédaction et le rendu de rapports de données. La sortie HTML rendue peut être écrite dans le volume published-reports, qui est partagé avec le service AKKO Docs à l'adresse https://docs.akko.local.

# Rendre un rapport Quarto depuis un terminal notebook
quarto render 04-akko-banking-report.qmd --to html \
  --output-dir ~/published-reports/

Notebooks partagés

Le répertoire notebooks/ de l'hôte est monté en lecture seule dans chaque conteneur utilisateur à l'emplacement /home/{username}/work/notebooks/. Cela fournit des notebooks de référence partagés :

Notebook Description
akko-banking-demo.ipynb Démo bancaire de bout en bout (Spark Connect + Moteur de requête)
rag-pipeline-demo.ipynb Pipeline RAG (Runtime LLM local (Ollama) + pgvector + LangChain)
spark-iceberg-demo.ipynb Opérations sur les tables Moteur de calcul Iceberg

Montage en lecture seule

Les notebooks partagés sont en lecture seule. Pour les modifier, copiez-les d'abord dans votre répertoire work/.

Variables d'environnement

Les variables d'environnement suivantes sont injectées dans chaque conteneur notebook utilisateur par le spawner JupyterHub :

Variable Valeur par défaut Fonction
TRINO_HOST trino Nom d'hôte du coordinateur Moteur de requête
TRINO_PORT 8080 Port HTTP de Moteur de requête
SPARK_REMOTE sc://spark-connect:15002 Point d'accès gRPC Spark Connect
OLLAMA_HOST http://ollama:11434 API LLM Runtime LLM local
STORAGE_ENDPOINT http://storage:9000 Point d'accès S3 object storage
POSTGRES_AKKO_PASSWORD (depuis .env) Mot de passe PostgreSQL
POLARIS_ROOT_SECRET (depuis .env) Secret OAuth2 Catalogue Iceberg (Polaris)
STORAGE_ACCESS_KEY (depuis .env) Clé d'accès object storage
STORAGE_SECRET_KEY (depuis .env) Clé secrète object storage
DBT_PROFILES_DIR /home/{user}/work/dbt Emplacement des profils dbt
NB_USER (dynamique) Nom d'utilisateur depuis Identité

Authentification & RBAC

JupyterHub utilise Identité SSO via le GenericOAuthenticator (flux d'autorisation OpenID Connect par code).

  • Client ID : jupyterhub
  • Scopes : openid, profile, email
  • Claim du nom d'utilisateur : preferred_username
  • Auto-login : activé (redirige directement vers Identité)
  • Utilisateurs admin : configurable via la variable d'environnement JUPYTERHUB_ADMIN_USER

Groupes Identité

Les groupes Identité (akko-admin, akko-engineer, akko-analyst, akko-viewer) contrôlent l'accès à travers la plateforme AKKO. JupyterHub autorise actuellement tous les utilisateurs authentifiés (allow_all = True), mais les groupes Identité se propagent aux services en aval comme Moteur de requête pour le RBAC à granularité fine.

Limites de ressources

Ressource Limite
Mémoire 6 Go par conteneur utilisateur
CPU 2 coeurs par conteneur utilisateur
Délai de lancement 180 secondes

Gestion des ressources

Arrêt automatique des serveurs inactifs (Cull)

JupyterHub arrête automatiquement les serveurs notebook inactifs pour libérer les ressources du cluster (CPU, RAM). Cela est géré par le composant intégré jupyterhub-idle-culler.

Paramètre Défaut Description
cull.enabled true Activer l'arrêt automatique des serveurs inactifs
cull.timeout 1800 Secondes d'inactivité avant arrêt (30 min)
cull.every 300 Fréquence de vérification (5 min)
cull.maxAge 28800 Durée de vie maximale d'un serveur en secondes (8h), même si actif

Pour modifier ces valeurs, éditez values-dev.yaml (ou votre fichier de valeurs production) :

jupyterhub:
  cull:
    enabled: true
    timeout: 3600       # 1 heure d'inactivité
    every: 300          # vérification toutes les 5 minutes
    maxAge: 43200       # 12 heures max

Puis appliquez :

helm upgrade akko helm/akko/ -n akko -f <votre-fichier-values>.yaml \
  --set-file akko-keycloak.realm.data=<fichier-realm>.json

Les données utilisateur sont préservées

L'arrêt automatique ne supprime que le pod (ressources de calcul). Les fichiers de l'utilisateur sont stockés sur un PersistentVolumeClaim (claim-<username>) qui persiste entre les redémarrages. Quand l'utilisateur se reconnecte, un nouveau pod est créé et le PVC est remonté automatiquement.

Recommandations pour la production

  • Data Scientists avec des entraînements longs : augmentez timeout à 7200 (2h) et maxAge à 86400 (24h).
  • Environnements sensibles aux coûts : réduisez timeout à 600 (10 min).
  • Ateliers / démos : définissez maxAge à 14400 (4h) pour garantir le nettoyage après la session.

Problèmes connus

Points d'attention importants

  • CHOWN_HOME_OPTS=-R ne fonctionne pas avec les volumes en lecture seule : L'image notebook utilise CHOWN_HOME=no et un hook personnalisé before-notebook.d qui exécute chown 2>/dev/null || true.
  • jupyterlab-drawio : Ne jamais installer -- force JupyterLab 3.
  • jupyterlab-lsp : Doit être >= 5 pour la compatibilité JupyterLab 4.
  • emailVerified dans Identité : Tous les utilisateurs de test doivent avoir emailVerified=true dans Identité, sinon oauth2-proxy les rejette.