Hi, I followed the steps for setting up a kubernetes cluster to host the infrastructure necessary for JupyterHub on AWS EC2
So far so good, I managed to embed it on a web app by adding extra config parameters and to prepopulate the jupyterhub server with notebooks that our team has written.
Now, I was trying to add a spawner class so that whenever a user wants to open a specific notebook or directory of notebooks, JupyterHub only shows those notebooks. For example, Jupyterhub pulls a docker container that contains all the notebooks, but when the user goes to the “Loops” lesson, Jupyterhub will only show the directory with the specific notebooks.
So, I’ve been trying different things, but after changing the default spawner (or what I think is the default spawner), jupyterhub returns a 500 error.
The config.yaml
file is very minimal now, because I tried multiple things, and I just wanted to check what was going on. Here’s the config file that I currently have:
singleuser:
image:
name: aicorecompany/custom-jupyterhub
tag: 0.0.5
lifecycleHooks:
postStart:
exec:
command: ["cp", "-r", "../../tmp/.", "/home/jovyan"]
hub:
networkPolicy:
egress:
- ports:
- port: 6443
- port: 443
extraConfig:
csp: |
c.JupyterHub.tornado_settings = {
'headers': {
'Content-Security-Policy': "frame-ancestors 'self' http://localhost:3000",
}
}
customSpawner: |
import os
import logging
from jupyterhub.spawner import LocalProcessSpawner
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
class CustomSpawner(LocalProcessSpawner):
def __init__(self, *args, **kwargs):
logger.info('===CustomSpawner===')
super().__init__(*args, **kwargs)
c.JupyterHub.spawner_class = CustomSpawner
After upgrading the helm chart, this is what kubectl logs hub returns:
Loading /usr/local/etc/jupyterhub/secret/values.yaml
No config at /usr/local/etc/jupyterhub/existing-secret/values.yaml
Loading extra config: csp
Loading extra config: customSpawner
[I 2024-05-29 13:41:57.492 JupyterHub app:2885] Running JupyterHub version 4.1.5
[I 2024-05-29 13:41:57.492 JupyterHub app:2915] Using Authenticator: jupyterhub.auth.DummyAuthenticator-4.1.5
[I 2024-05-29 13:41:57.492 JupyterHub app:2915] Using Spawner: builtins.CustomSpawner
[I 2024-05-29 13:41:57.492 JupyterHub app:2915] Using Proxy: jupyterhub.proxy.ConfigurableHTTPProxy-4.1.5
[I 2024-05-29 13:41:57.603 JupyterHub app:2005] Not using allowed_users. Any authenticated user will be allowed.
[I 2024-05-29 13:41:57.689 JupyterHub app:2954] Initialized 0 spawners in 0.003 seconds
[I 2024-05-29 13:41:57.699 JupyterHub metrics:279] Found 8 active users in the last ActiveUserPeriods.twenty_four_hours
[I 2024-05-29 13:41:57.701 JupyterHub metrics:279] Found 8 active users in the last ActiveUserPeriods.seven_days
[I 2024-05-29 13:41:57.702 JupyterHub metrics:279] Found 8 active users in the last ActiveUserPeriods.thirty_days
[I 2024-05-29 13:41:57.702 JupyterHub app:3168] Not starting proxy
[I 2024-05-29 13:41:57.719 JupyterHub app:3204] Hub API listening on http://:8081/hub/
[I 2024-05-29 13:41:57.719 JupyterHub app:3206] Private Hub API connect url http://hub:8081/hub/
[I 2024-05-29 13:41:57.720 JupyterHub app:3215] Starting managed service jupyterhub-idle-culler
[I 2024-05-29 13:41:57.720 JupyterHub service:386] Starting service 'jupyterhub-idle-culler': ['python3', '-m', 'jupyterhub_idle_culler', '--url=http://localhost:8081/hub/api', '--timeout=3600', '--cull-every=600', '--concurrency=10']
[I 2024-05-29 13:41:57.726 JupyterHub service:134] Spawning python3 -m jupyterhub_idle_culler --url=http://localhost:8081/hub/api --timeout=3600 --cull-every=600 --concurrency=10
[I 2024-05-29 13:41:57.730 JupyterHub app:3273] JupyterHub is now running, internal Hub API at http://hub:8081/hub/
[I 2024-05-29 13:41:57.934 JupyterHub log:192] 200 GET /hub/api/ (jupyterhub-idle-culler@::1) 11.81ms
[I 2024-05-29 13:41:57.944 JupyterHub log:192] 200 GET /hub/api/users?state=[secret] (jupyterhub-idle-culler@::1) 7.72ms
INFO:builtins:===CustomSpawner===
[I 2024-05-29 13:42:30.784 JupyterHub log:192] 200 GET /hub/home (ivan@::ffff:100.96.2.253) 49.18ms
[I 2024-05-29 13:42:37.227 JupyterHub provider:660] Creating oauth client jupyterhub-user-ivan
[E 2024-05-29 13:42:37.251 JupyterHub user:887] Unhandled error starting ivan's server: "getpwnam(): name not found: 'ivan'"
Traceback (most recent call last):
File "/usr/local/lib/python3.11/site-packages/jupyterhub/user.py", line 801, in spawn
url = await gen.with_timeout(timedelta(seconds=spawner.start_timeout), f)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/jupyterhub/spawner.py", line 1682, in start
env = self.get_env()
^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/jupyterhub/spawner.py", line 1629, in get_env
env = self.user_env(env)
^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/jupyterhub/spawner.py", line 1616, in user_env
home = pwd.getpwnam(self.user.name).pw_dir
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
KeyError: "getpwnam(): name not found: 'ivan'"
[E 2024-05-29 13:42:37.300 JupyterHub pages:314] Error starting server ivan: "getpwnam(): name not found: 'ivan'"
Traceback (most recent call last):
NoneType: None
[W 2024-05-29 13:42:37.300 JupyterHub web:1873] 500 GET /hub/spawn/ivan (::ffff:100.96.2.253): Unhandled error starting server ivan
[E 2024-05-29 13:42:37.330 JupyterHub log:184] {
"X-Forwarded-Host": "a663379ab913744cab78cb88abb14884-1613608875.eu-west-1.elb.amazonaws.com",
"X-Forwarded-Proto": "http",
"X-Forwarded-Port": "80",
"X-Forwarded-For": "::ffff:100.96.2.253",
"Upgrade-Insecure-Requests": "1",
"Cookie": "_xsrf=[secret]; jupyterhub-hub-login=[secret]; jupyterhub-session-id=[secret]",
"Referer": "http://a663379ab913744cab78cb88abb14884-1613608875.eu-west-1.elb.amazonaws.com/hub/home",
"Connection": "keep-alive",
"Accept-Encoding": "gzip, deflate",
"Accept-Language": "en-US,en;q=0.5",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8",
"User-Agent": "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:125.0) Gecko/20100101 Firefox/125.0",
"Host": "a663379ab913744cab78cb88abb14884-1613608875.eu-west-1.elb.amazonaws.com"
}
[E 2024-05-29 13:42:37.330 JupyterHub log:192] 500 GET /hub/spawn/ivan (ivan@::ffff:100.96.2.253) 133.20ms
So the questions are:
- What am I doing wrong? I am sure there is something that I am making fundamentally wrong. If I remove the customSpawner extraConfig, everything works great
- Am I going the right path to implement the requirements I mentioned above for single notebook usage? Perhaps there is something I missed in the docs that already enables that
Thanks for your help!