Despliega tu propio servidor de JupyterHub Multiusuario con Kubernetes en tu VPS
Si alguna vez tus proyectos de ciencia de datos o desarrollo colaborativo te han pedido un entorno común, JupyterHub es la herramienta definitiva. Hoy te mostraré cómo levantar una infraestructura potente y escalable con Kubernetes, para que tus equipos o estudiantes tengan acceso a sus propios notebooks en un entorno aislado, ¡directamente en tu VPS!
¿Qué es JupyterHub y por qué desplegarlo con Kubernetes?
JupyterHub permite que múltiples usuarios usen Jupyter Notebooks simultáneamente, cada uno en su espacio seguro. Con Kubernetes:
- Escalas horizontalmente cuando tu equipo crece.
- Garantizas alta disponibilidad y aislamiento de recursos.
- Automatizas el aprovisionamiento y borrado de entornos de usuario.
Es ideal para clases de programación, equipos de IA y laboratorios virtuales.
Arquitectura simplificada para principiantes curiosos
Implementaremos el diagrama más simple posible… y después ¡lo complicamos! 😏
- Un Deployment para JupyterHub
- Un Service para exponerlo vía NodePort
- Un ConfigMap con configuración básica
- Un PersistentVolumeClaim para guardar los notebooks
Ficheros yaml
: todo listo para copiar/pegar
ConfigMap: configuración inicial de JupyterHub
apiVersion: v1 kind: ConfigMap metadata: name: jupyterhub-config data: jupyterhub_config.py: | c.JupyterHub.bind_url = 'http://:8000' c.Spawner.default_url = '/lab' c.JupyterHub.admin_access = True c.Authenticator.admin_users = {'admin'}
PersistentVolumeClaim: para los datos de usuario
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: jupyterhub-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 5Gi
Deployment: con imagen oficial de JupyterHub
apiVersion: apps/v1 kind: Deployment metadata: name: jupyterhub spec: replicas: 1 selector: matchLabels: app: jupyterhub template: metadata: labels: app: jupyterhub spec: containers: - name: jupyterhub image: jupyterhub/jupyterhub:latest ports: - containerPort: 8000 volumeMounts: - mountPath: /srv/jupyterhub name: jupyterhub-data - mountPath: /etc/jupyterhub/jupyterhub_config.py name: config subPath: jupyterhub_config.py env: - name: JUPYTERHUB_BASE_URL value: "/" volumes: - name: jupyterhub-data persistentVolumeClaim: claimName: jupyterhub-pvc - name: config configMap: name: jupyterhub-config
Service: accesible vía NodePort
apiVersion: v1 kind: Service metadata: name: jupyterhub spec: type: NodePort ports: - port: 8000 targetPort: 8000 nodePort: 32080 selector: app: jupyterhub
¡A desplegar!
-
Aplica todo con
kubectl apply -f fichero.yaml
para cada fichero. -
Si usas una única máquina (Minikube o VPS sin Ingress), accede vía
IP_DEL_VPS:32080
en tu navegador. -
El usuario
admin
tendrá privilegios de admin por defecto.
Niveles extra de dificultad para los valientes
¿Quieres subir el listón? Modifica el Deployment
para añadir autenticación OAuth (Google o GitHub), configura ingress con TLS, o integra Kubespawner para que cada usuario tenga su propio Pod. ¿Lo quieres aún más pro? Investiga Helm Chart oficial de JupyterHub y personalízalo a tu gusto.
Consejos clave y Troubleshooting
-
Si los logs de JupyterHub no muestran nada al acceder, revisa los volúmenes y la conexión del
ConfigMap
. Recarga el pod si modificas la config. - El puerto 32080 debe estar abierto en tu firewall del VPS.
-
Si el PVC no se crea, verifica si tu clúster soporta almacenamiento dinámico (usa
hostPath
para pruebas rápidas en entornos locales).