Despliega tu propio servidor de JupyterHub multiusuario con Kubernetes

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!

  1. Aplica todo con kubectl apply -f fichero.yaml para cada fichero.
  2. Si usas una única máquina (Minikube o VPS sin Ingress), accede vía IP_DEL_VPS:32080 en tu navegador.
  3. 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).
Avatar

Por Mid