跳转到主要内容

JupyterHub Python仓库模板

项目描述

JupyterHub空闲清理器服务

GitHub Workflow Status - Test Latest PyPI version GitHub Discourse Gitter

jupyterhub-idle-culler 提供一个 JupyterHub 服务,通过 JupyterHub 识别和停止空闲或长时间运行的 Jupyter 服务器。它完全通过交互 JupyterHub 的 REST API 来工作,通常配置为 JupyterHub 管理服务,由 JupyterHub 本身启动。

设置

设置涉及三个部分

  1. 安装 Python 包。
  2. 配置 JupyterHub 权限以与 JupyterHub 的 REST API 交互。
  3. 配置其启动方式,无论是作为 JupyterHub 管理服务还是作为独立脚本。

安装

pip install jupyterhub-idle-culler

权限

在 JupyterHub 2.0 之前,jupyterhub-idle-culler 需要完全管理权限,以便有足够的权限代表用户停止服务器。

JupyterHub 2.0 引入了 作用域 以实现更细粒度的权限控制。这意味着配置的清除器服务不再需要完全管理权限。它只能分配所需的权限。

jupyterhub-idle-culler 需要以下作用域才能运行

  • list:users - 访问用户列表 API,我们从中获取要清除的用户信息
  • read:users:activity - 读取用户的 last_activity 字段
  • read:servers - 读取用户的 servers 字段
  • delete:servers - 停止用户的服务器,如果传递了 --remove-named-servers,则删除命名服务器
  • admin:users (可选) - 如果传递了 --cull-users,则删除用户

要为服务分配适当的权限,请在 jupyterhub_config.py 中声明一个角色

c.JupyterHub.load_roles = [
    {
        "name": "jupyterhub-idle-culler-role",
        "scopes": [
            "list:users",
            "read:users:activity",
            "read:servers",
            "delete:servers",
            # "admin:users", # if using --cull-users
        ],
        # assignment of role's permissions to:
        "services": ["jupyterhub-idle-culler-service"],
    }
]

作为 hub 管理服务

jupyterhub_config.py 中,将以下字典添加到 c.JupyterHub.services 列表中,以便为空闲清除器服务

c.JupyterHub.services = [
    {
        "name": "jupyterhub-idle-culler-service",
        "command": [
            sys.executable,
            "-m", "jupyterhub_idle_culler",
            "--timeout=3600",
        ],
        # "admin": True,
    }
]

其中

  • "command" 表示服务将由 Hub 管理,并且
  • "admin": True 授予此服务管理权限,并且仅用于 jupyterhub < 2.0;请参阅 [上面][权限]。

作为独立脚本

jupyterhub-idle-culler 也可以作为独立脚本运行。它可以使用服务令牌访问 hub 的 api。

jupyterhub_config.py 中将服务令牌注册到 JupyterHub

c.JupyterHub.services = [
    {
        "name": "jupyterhub-idle-culler-service",
        "api_token": "...",
        # "admin": True,
    }
]

其中

  • "api_token" 包含一个密钥令牌,例如使用 openssl rand -hex 32 生成的,并且
  • "admin": True 授予此服务管理权限,并且仅用于 jupyterhub < 2.0;请参阅 [上面][权限]。

将相同的令牌存储在 JUPYTERHUB_API_TOKEN 环境变量中。然后手动启动 jupyterhub-idle-culler

export JUPYTERHUB_API_TOKEN=api_token_above...
python3 -m jupyterhub_idle_culler [--timeout=900] [--url=http://localhost:8081/hub/api]

命令行标志

  --api-page-size                  Number of users to request per page, when
                                   using JupyterHub 2.0's paginated user list
                                   API. Default: user the server-side default
                                   configured page size. (default 0)
  --concurrency                    Limit the number of concurrent requests made
                                   to the Hub.  Deleting a lot of users at the
                                   same time can slow down the Hub, so limit
                                   the number of API requests we have
                                   outstanding at any given time. (default 10)
  --cull-admin-users               Whether admin users should be culled (only
                                   if --cull-users=true). (default True)
  --cull-every                     The interval (in seconds) for checking for
                                   idle servers to cull. (default 0)
  --cull-default-servers           Whether default servers should be culled (only
                                   if --cull-default-servers=true). (default True)
  --cull-named-servers             Whether named servers should be culled (only
                                   if --cull-named-servers=true). (default True)
  --cull-users                     Cull users in addition to servers.  This is
                                   for use in temporary-user cases such as
                                   tmpnb. (default False)
  --internal-certs-location        The location of generated internal-ssl
                                   certificates (only needed with --ssl-
                                   enabled=true). (default internal-ssl)
  --max-age                        The maximum age (in seconds) of servers that
                                   should be culled even if they are active.
                                   (default 0)
  --remove-named-servers           Remove named servers in addition to stopping
                                   them.  This is useful for a BinderHub that
                                   uses authentication and named servers.
                                   (default False)
  --ssl-enabled                    Whether the Jupyter API endpoint has TLS
                                   enabled. (default False)
  --timeout                        The idle timeout (in seconds). (default 600)
  --url                            The JupyterHub API URL.

注意事项

  1. JupyterHub 关于用户服务器 last_activity 的数据不会以高频率更新,因此清除超时应该大于单用户 websocket ping 间隔(默认:30 秒)的总和

    • JupyterHub.last_activity_interval(默认:5 分钟)
    • 如果您想使用 --cull-users 并为用户服务器和用户使用不同的清除间隔,您必须启动两个空闲清除器服务。这是因为两者都通过 --timeout--max-age 配置。要这样做,请配置此服务以不同的配置启动两次,其中一个有 --cull-users 选项。
  2. 默认情况下,jupyterhub-idle-cullers 的 HTTP 请求在 60 秒后超时。这可以通过设置 JUPYTERHUB_REQUEST_TIMEOUT 环境变量来更改。

  3. 它的工作方式

使用

JupyterHub 的 REST API 用于获取有关活动信息,如果空闲清除器服务根据配置认为服务器应该停止或删除,它也通过 JupyterHub 的 REST API 来停止或删除。

深入了解

jupyterhub-idle-culler 依赖于通过 JUPYTERHUB_API_TOKEN 提供的权限,该令牌由 JupyterHub 自动为 由 JupyterHub 启动的管理服务 设置。

jupyterhub-idle-culler 通过 JupyterHub 的 /users REST API 列出可用用户及其服务器的报告 last_activity,并根据这些信息做出决策。可以通过 /users/{name}/server 来停止用户的默认服务器,通过 /users/{name}/servers/{server_name} 来停止和可选地删除命名服务器,并且可以通过 /users/{name} 来可选地删除用户。

JupyterHub 会定期通过 update_last_activity 函数 更新用户服务器的报告 last_activity,该函数依赖于两个信息来源。

  1. 代理的路由数据

    JupyterHub 的可配置代理类是一个 JupyterHub 请求将网络流量路由到用户服务器接口。通过此接口,如果代理类提供信息,JupyterHub 可以了解网络活动,具体通过 get_all_routes 函数。

    https://jupyter-z2jh.pythonlang.cn 中使用的 configurable-http-proxy 提供有关网络路由活动的信息,但 traefik-proxyhttps://jupyter-tljh.pythonlang.cn目前还没有

  2. 用户服务器的活动报告

    update_last_activity 函数还读取 JupyterHub 的数据库,该数据库保存有关服务器 last_activity 的状态。每当服务器通知 JupyterHub 关于活动时,这些数据库记录就会更新,这是它们必须做的。

    在 JupyterHub 4 之前,服务器通过 jupyterhub-singleuser 脚本通知 JupyterHub 关于活动,该脚本通过安装 jupyterhub(或 conda-forge 上的 jupyterhub-singleuser)提供。在 JupyterHub 4+ 和 jupyter_server 2+ 中,可以使用 jupyter_server 服务器扩展来代替。

    jupyterhub-singleuser 脚本启动一个修改后的服务器应用程序,通过 notify_activity 函数来保持 JupyterHub 更新服务器活动。

    notify_activity 函数反过来利用服务器应用程序的 last_activity 函数(分别在 NotebookAppServerApp 中查看实现)将 API 活动信息、内核活动、内核关闭和终端活动信息结合起来。这些活动还涵盖了通过 jupyter-server-proxy 运行的应用程序(如 RStudio)的活动。

以下是到目前为止所描述内容的总结

  1. jupyterhub-idle-culler 通过 JupyterHub 的 REST API 收集信息和执行操作。
  2. jupyterhub-idle-culler 根据由 JupyterHub 提供的信息做出决策,该信息收集用户服务器的活动报告,并轮询代理类以获取有关用户服务器网络活动的信息。

由于服务器的内核活动会影响服务器通知 JupyterHub 的活动,因此内核活动反过来也会影响 jupyterhub-idle-culler。因此,即使 jupyterhub-idle-culler 不参与其中,了解一种用于 淘汰空闲内核 的机制也可能是有意义的。

默认内核管理器 MappingKernelManager 可以配置为淘汰空闲内核。其配置在 ServerAppNotebookApp 的相应文档中记录,以下是相关的内核淘汰配置选项

  • MappingKernelManager.cull_busy

  • MappingKernelManager.cull_idle_timeout

  • MappingKernelManager.cull_interval

  • MappingKernelManager.cull_connected

    注意,对于具有与内核建立WebSocket连接的浏览器JupyterLab来说,理解cull_connected可能有些棘手。在经典Jupyter笔记本UI中,是否建立连接并不像现在这样明显。有关更多详细信息,请参阅此问题

    此外,MappingKernelManager的配置应在用户服务器本身上进行,例如通过在/etc/jupyter/usr/local/etc/jupyter中的jupyter_server_config.py文件进行,而不是在JupyterHub运行的地方。

最后,请注意,如果配置了ServerApp.shutdown_no_activity_timeout,Jupyter服务器可以在没有干预的情况下通过jupyterhub-idle-culler自行关闭。

注意事项

分页

JupyterHub 2.0在/users API端点中引入了分页。这种分页不能保证连续请求的一致快照,因此,在请求之间跨越页面边界的情况下,一个高度活跃的中心可能偶尔会错过分页用户。这预计将是一个不常发生的事件,并且在现实场景中只会导致服务器在被清除时延迟一个清除间隔,因此对JupyterHub的影响很小。

可以通过请求更大的页面大小来缓解这个问题,例如使用--api-page-size=200,但如果这给您带来了问题,请随时提出问题。

由以下机构支持

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面