Argo-Workflow后端扩展,用于Jupyter-Scheduler。
项目描述
argo-jupyter-scheduler
目录
Argo-Jupyter-Scheduler
提交长时间运行的notebook,无需保持JupyterLab服务器运行。并且可以将notebook提交到指定的时间表。
安装
pip install argo-jupyter-scheduler
这是什么?
Argo-Jupyter-Scheduler是JupyterLab扩展Jupyter-Scheduler的插件。
这意味着什么?
这意味着这是一个安装在JupyterLab基本映像中的应用程序,并在JupyterLab中作为扩展运行。具体来说,您将在JupyterLab启动器的标签页底部看到此图标
并且您将在Jupyter Notebook的工具栏上看到此图标
这也意味着,作为一个实验室扩展,此应用程序在每个用户的单独JupyterLab服务器上运行。您提交的笔记本记录仅对您个人有效。没有中央Jupyter-Scheduler。
然而,我们不是使用基础Jupyter-Scheduler,而是使用Argo-Jupyter-Scheduler。
为什么?
如果您想要按计划运行Jupyter Notebook,您需要确保笔记本将在您指定的时刻执行。Jupyter-Scheduler的基本限制是,当您的JupyterLab服务器不运行时,Jupyter-Scheduler也不会运行。那么,您已安排的笔记本将不会运行。现在想立即运行的笔记本怎么办?如果JupyterLab服务器关闭,那么笔记本运行的状态将如何记录?
解决方案是Argo-Jupyter-Scheduler:Jupyter-Scheduler前端加上Argo-Workflows后端。
可选功能
发送到Slack
Argo-Jupyter-Scheduler允许将已执行笔记本的HTML输出发送到Slack频道。
- 请参阅Slack API文档了解如何创建一个以
xoxb
开头的bot令牌。 - 邀请您的bot加入一个用于发送输出的Slack频道。
- 当安排笔记本(如上所述)时
- 选择已安装
papermill
的conda环境 - 添加以下
参数
- 名称:
SLACK_TOKEN
,值:xoxb-
- 名称:
SLACK_CHANNEL
,值:<Slack频道名称>
(不要以#
开头,如scheduled-jobs
)。
- 名称:
- 选择已安装
创建作业
Slack输出
深入了解
在Jupyter-Scheduler实验室扩展中,您可以创建两个东西:一个作业
和一个作业定义
。
作业
作业
或笔记本作业是指您提交笔记本以运行时。
在Argo-Jupyter-Scheduler中,这个作业
转换为Argo-Workflows中的工作流
。因此,当您创建一个作业
时,您的笔记本作业将创建一个工作流,无论您的JupyterLab服务器是否运行,该工作流都将运行。
目前,提交作业需要权限,由
argo-server-sso
客户端的Keycloak角色管理。如果您的用户具有argo-admin
或argo-developer
角色,则允许他们创建和提交作业(以及作业定义)。
我们还依赖Nebari Workflow Controller来确保用户的主目录和conda-store环境被挂载到工作流中。这使我们能够确保
- 用户主目录中的文件可以被笔记本作业使用
- 笔记本的输出可以本地保存
- 当使用的conda环境更新时,笔记本作业也将更新(对计划作业有帮助)
- 提交笔记本作业的节点选择器和镜像与工作流使用的是相同的
作业定义
作业定义
只是创建在指定计划上运行的作业的一种方法。
在Argo-Jupyter-Scheduler中,作业定义
转换为Argo-Workflows中的cron工作流
。因此,当您创建一个作业定义
时,您创建了一个cron工作流
,然后该工作流创建了一个在计划时运行的工作流。
作业
对应于工作流
,就像作业定义
对应于cron工作流
一样。
内部结构
Jupyter-Scheduler创建并使用一个scheduler.sqlite
数据库来管理和跟踪作业和作业定义。如果您能确保这个数据库可访问并且可以在作业或作业定义的状态改变时更新,那么您就可以确保从JupyterLab看到的视图是准确的。
默认情况下,此数据库位于
~/.local/share/jupyter/scheduler.sqlite
,但这是一个可以修改的traitlet。由于我们有权访问此数据库,我们可以直接从工作流本身更新数据库。
为了完成这项任务,工作流分为两个步骤进行。首先,工作流运行notebook,使用papermill
和指定的conda环境。其次,根据notebook运行的成败,更新数据库状态。
当创建作业定义时,会创建相应的cron工作流。为了确保数据库得到正确更新,cron工作流创建的工作流包含以下三个步骤:首先,在数据库中创建一个状态为进行中
的作业记录。其次,再次使用papermill
和指定的conda环境运行notebook。最后,更新新创建的作业记录,以notebook运行的状态。
输出文件
除了用于创建输出notebook的papermill
外,还使用jupyter nbconvert
生成HTML输出。为了通过Web UI下载这些输出文件,重要的是它们要符合Jupyter-Scheduler预期的格式,这通过在创建输出文件时在Argo-Jupyter-Scheduler内部重复使用create_output_filename
来实现。
预期的输出文件名包括与作业开始时间匹配的时间戳。对于cron作业,这有点棘手,因为开始时间是在运行create-job-id
时设置的。所有工作流步骤都在独立的容器中运行,create-job-id
容器在创建输出文件的papermill
步骤之后运行。
由于papermill
容器需要访问包含papermill
和jupyter
命令的文件系统挂载点以及访问环境变量,因此其定义与容器不同。因此,一旦定义了papermill
容器,其中执行的命令就不能更改。
这也意味着papermill
容器无法访问作业开始时间,因此无法创建具有期望时间戳的文件名。为了解决这个问题,papermill
步骤始终以相同的默认文件名创建输出文件,并且有一个额外的rename-files
步骤在create-job-id
之后运行,以确保时间戳与作业开始时间匹配。为了在容器之间传递开始时间值,使用SQLite数据库。
最后,由于create-job-id
每次运行都会创建一个新的作业,因此这个作业也将有一个新的ID。作业ID很重要,因为它是预期由Jupyter-Scheduler在作业暂存目录中找到的目录的名称。但是,输出文件是在创建输出文件的papermill
步骤中创建的,其ID是工作流在调度时定义的作业ID,而不是在create-job-id
中创建的当前作业ID。为了指向正确的磁盘上的位置,创建了一个指向暂存作业目录的符号链接。这也在rename-files
步骤中完成,通过在SQLite数据库中查找作业ID来实现。
对于非cron作业,没有create-job-id
步骤。其余的工作流步骤相同,但不需要进行数据库查找和创建符号链接。这是因为开始时间立即可用,作业ID与作业暂存区匹配。
工作流程步骤
以下是工作流步骤的概述
main
运行papermill
和jupyter nbconvert
以创建输出文件create-job-id
创建一个可以在没有JupyterLab的情况下运行的新的作业(仅限于cron作业)rename-files
更新输出文件的时间戳并在作业暂存目录之间添加符号链接send-to-slack
将HTML输出发送到Slack频道(仅在通过参数SLACK_TOKEN
和SLACK_CHANNEL
提供时,在安排作业时提供)failure
或success
将状态设置为Web UI中的“失败”或“完成”
这些步骤在单独的容器中按顺序执行。如果某个步骤失败,则在最后调用failure
步骤。否则,调用success
步骤。
其他想法
目前,Argo-Jupyter-Scheduler 与 Nebari(通过 Nebari-Workflow-Controller)紧密耦合,这使得它对其他项目不太适用。这并不一定是必要的。通过利用 Traitlets,我们可以包括其他修改运行工作流程 pod 规范的方法,使其能够被其他项目使用。如果您对这个项目感兴趣,并希望看到它的扩展,请随时提交问题来讨论您的想法。谢谢 :)
已知问题
Jupyter-Scheduler 的所有核心功能都已映射到 Argo-Jupyter-Scheduler 上。不幸的是,目前存在 更新作业定义
和 暂停
/恢复
作业定义的限制。尽管 暂停
可以正常工作,但 恢复
失败,原因与 更新作业定义
相同,这是由于上游 Nebari-Workflow-Controller(参见 已知限制)的限制,它无法重新提交工作流程/定时工作流程;更多详细信息请参阅 此问题。
许可
argo-jupyter-scheduler
在 MIT 许可证的条款下分发。
项目详情
下载文件
下载您平台的文件。如果您不确定选择哪个,请了解有关 安装包 的更多信息。
源分布
构建分布
哈希值 为 argo_jupyter_scheduler-2024.6.1-py3-none-any.whl
算法 | 哈希摘要 | |
---|---|---|
SHA256 | edfb368f8ba11f92d6eb4aa455f0b60428cf38cdd902b892a5abccf491ab6904 |
|
MD5 | 2c08ba5558d05c4f7772010a0e8b8f30 |
|
BLAKE2b-256 | 2c8a0a2cc01c0221af737ebce538dcfbff9398dbc77421d909f7e45b812c7a8a |