任务流编排
平台有很多封装好的模板,比如数据导入、数据预处理、各种机器学习算法。可以将需要的模板按照计划执行的顺序拖拽(长按左侧任务模板拖拽,到指定位置松开)到面板中,按顺序连接起来。
每个任务模板的字段含义与使用方法,请参考 05-任务模板 段中对应模板的说明。

点击"运行",可验证任务流的执行顺序是否与编排的、期望的顺序一致。

首页展示
如果想在首页展示编排好的任务流,可以在"模型训练"-"任务流"-"更多"-"修改"中,找到扩展参数,填写如:
{
"demo": "true",
"img": "/static/assets/images/pipeline/yolo.jpg"
}
设置 demo 为 true 则可在首页(示例 pipeline 列表)展示,必须同时配 img 参数,配一张图片才可以。
实现说明:该参数保存在 pipeline 的
parameter字段,首页示例列表通过筛选"demo": "true"取出(myapp/views/view_pipeline.py:1521-1524的/demo/list/接口)。标记为demo的示例 pipeline 不允许直接修改,需复制后编辑(view_pipeline.py:1395-1396)。

任务配置
模板拖拽到面板区后,就形成了任务节点。点击任务节点,可以对任务进行配置,具体的配置方法和每个模板的设计有关,需要参照对应模板的使用说明(见 05-任务模板)。

任务还支持配置跳过、重试等,方便在执行过程中可根据情况调整适应。

CPU、GPU 申请
任务的配置支持 CPU、GPU 配置,可以配置任务需要的内存资源、CPU、GPU 资源等。任务运行时,会自动根据申请的资源及资源状况进行分配。
GPU 支持多种卡型,比如填写 1(V100) 表示申请 1 张 V100 的 GPU 卡。平台目前支持不同 GPU 卡型(如 T4/V100/A100 等),还支持国产 GPU,如海光的 DCU、华为的 NPU。
任务对 CPU/GPU 等资源的占用,支持独占 GPU、共享 GPU 和 VGPU 等占用方式,以满足不同任务对资源需求的场景。如 1、2 表示独占;0.1(T4) 表示 VGPU;-1 表示共享。

单任务运行、调试
单个任务节点可以独立进行调试。点击 Debug 是进入命令行进行调试,点击 Run 是直接运行模板的 py 文件,log 可以查看调试日志,clear 清除调试任务。

通过 notebook 我们可以进行代码的编辑,通过镜像调试,我们可以构建自己的镜像,然后就可以编排 pipeline 了。pipeline 运行前需要独立运行调试单个 task,所以平台添加了单 task 独立调试的功能。

每个 task 都可以独立 debug 和独立运行,这样就不用每次都运行整体 pipeline 才能进行调试。对于分布式任务的 task,平台在模板中借用 stern 实现了多个容器 log 聚合查看,这样就不用每个 worker 的日志都单独去看了。

单个任务为分布式任务时:
往往某个任务需要是分布式任务,需要启动分布式任务。云原生分布式任务需要 k8s 对应的 operator。分布式算法模板的实现方法,主要在模板中实现 launcher,创建对应分布式任务的 job yaml,提交到 k8s,对应的 job operator 创建每个 worker 的 pod 和 service,然后运行业务代码。launcher 端启动 stern 组件,监听该分布式任务所有 pod 的日志并输出,这样就可以在当前任务中查看到所有 worker 的日志。

每个任务启动后都可以看到相应的资源情况,这样可以边调试边配置资源的申请量,在 GPU 上也可以及时知道是否还有优化的空间、目前任务的主要瓶颈在哪里,更加直观地确定优化方向。

自定义镜像调试
有一个比较特殊的模板,是模板分类"基础命令"下面的"自定义镜像"模板。其他任务节点的调试都是为了调试模板对应的 py 文件,而自定义镜像是为了提供一个可视化面板,可以调试用户封装的镜像,避免有部分用户不熟悉镜像调试。
任务其他参数配置
如果想修改其他任务配置,比如任务挂载、启动命令、启动目录,可以按照图中的方法修改:



任务流中监听端口
部分特殊的模板需要在运行期间监听端口,比如 spark 任务提交,任务作为 spark driver 端需要监听端口。需要在此类任务的任务模板的扩展中添加扩展参数:HostNetwork=True。

则任务运行时会自动占用指派的端口,端口会以环境变量 PORT1、PORT2 的形式告诉代码,代码自行决定如何使用。

任务流配置
任务流也可以进行配置,主要是配置定时调度、项目组、任务流运行状态的监控及报警等。

- 调度类型(schedule_type):触发任务流运行的方式,
crontab为定时触发,once为手动触发。设置为定时触发的任务,也可以同时被手动触发,相互不影响。默认once。 - 调度周期(cron_time):定时触发任务的定时周期,格式
* * * * *表示 minute hour day month week。 - 监控状态(alert_status):当任务流达到哪些状态时会触发报警推送消息。可选状态:Created、Pending、Running、Succeeded、Failed、Unknown、Waiting、Terminated。
- 报警人(alert_user):达到想要监控的状态时,发送消息给哪些用户。
- 补录起点(cronjob_start_time):对于定时任务,每个定时周期触发时间点都需要设置启动任务,这个定时周期最开始计算的时间起点。默认设置为定时周期或修改定时周期的时间点。
- 过往依赖(depends_on_past):定时任务每次实例运行时是否检查上一次的任务流是否完成,若完成才可以调度新一轮周期的任务流实例。默认
True。 - 最大激活运行数(max_active_runs):同时可以运行的任务流实例数目。默认
1。 - 任务并行数(parallelism):同一个任务流实例中,同时可以运行的任务数目。默认
3。 - 全局环境变量(global_env):为任务流中每个任务都会添加的环境变量,每行一个,支持
datetime/creator/runner/uuid/pipeline_id等模板变量,例如USERNAME={{creator}}。
字段默认值与说明来源:
myapp/views/view_pipeline.py:1107-1214。另有expired_limit(过期保留数,定时调度最新实例限制数目,0 表示不限制,默认 1)和priority(优先级,high/low,资源不足时低优先级会主动让出资源)。
另有一个值得一提的,就是任务流的补录配置,可以设置任务流回溯到哪个时间节点开始,定时补录数据。比如要计算过去 2 个月内、每一天往前 360 天的用户行为数据,就可以通过这个功能来实现。
日志查看
可以查看任务实例的在线日志、离线日志、资源使用等。在线日志保留到任务结束,任务结束后的离线日志保留一个月。

任务流变量输入输出
文件中转(推荐)
在前一个任务中将输出文件存储到分布式存储,在后续任务中读取这个分布式存储文件,实现任务间内容的传递。
配置变量传递(不推荐)
在上一个任务中将短文本内容直接输出到容器的
/output文件内,在下一个任务的参数中直接把这个文件的内容当成字符串配置为参数。读取方法为{{$task_name.output}}。比如:


全局变量
往往我们想要在一次任务流运行实例的过程中,每个任务的中间数据总是在同一个目录下,但每次任务流实例又是不同的目录。这时往往需要一个全局变量:在每次运行时不一样,在同一次任务流实例的不同任务间又相同。这时可以使用全局变量。
可以在 pipeline 中定义全局变量,在任务参数中引用这个变量。

在任务中可以直接引用这里定义的变量,引用方式 {{YYYYMMDD}}。

模板变量
在任务参数配置中,还可以以模板变量的形式 {{}} 使用下列 Python 变量(渲染逻辑见 myapp/views/view_pipeline.py:427-436):
creator = pipeline.created_by.username 字符串:pipeline 的创建者
datetime = datetime 包
runner = g.user.username 字符串:实例的运行者
uuid = uuid 包
pipeline_id = pipeline.id 字符串
pipeline_name = pipeline.name 字符串:pipeline 的名称
cluster_name = pipeline.project.cluster['NAME'] 字符串:当前所属 k8s 集群
run_id = pipeline.run_id 字符串:本次运行实例的 run_id
execution_date = eta.strftime('%Y-%m-%d %H:%M:%S') 字符串:实例的周期时间
说明:
run_id为代码中实际可用、原文档未列出的模板变量(view_pipeline.py:432)。
使用示例:
{{uuid.uuid4().hex[:4]}}
{{datetime.datetime.now().strftime("%Y%m%d-%H%M%S.%f")}}
{{pipeline_id}}
{{pipeline_name}}
{{cluster_name}}
{{runner}}
{{execution_date}}
系统环境变量
平台会自动将任务流/任务的信息以环境变量的形式传递给任务(来源:myapp/views/view_pipeline.py:518-530):
KFJ_TASK_ID 任务的 id
KFJ_TASK_NAME 任务的名称
KFJ_TASK_NODE_SELECTOR 任务的机器选择器
KFJ_TASK_VOLUME_MOUNT 任务的挂载
KFJ_TASK_IMAGES 任务使用的镜像
KFJ_TASK_RESOURCE_CPU 任务占用的 cpu 资源
KFJ_TASK_RESOURCE_MEMORY 任务占用的内存
KFJ_TASK_RESOURCE_GPU 任务占用的 gpu 资源
KFJ_TASK_RESOURCE_RDMA 任务占用的 rdma 资源
KFJ_TASK_PROJECT_NAME 任务所属的项目组名称
GPU_RESOURCE_NAME 任务占用的 gpu 所对应的 k8s 资源名
RDMA_RESOURCE_NAME 任务占用的 rdma 所对应的 k8s 资源名
USERNAME 用户名(pipeline 创建者)
workflow(任务流调度实例)
通过 pipeline 的"调度实例"按钮,可以查看历史调度实例的启动时间、耗时、运行状态等。

再点击调度实例后面的"日志"链接,可以查看任务流的 workflow。

点击 workflow 中的单个任务节点,还可以查看任务的在线日志、可视化结果、pod 信息等。

定时调度
点击任务流名称旁边的锯齿状按钮,可调出任务流配置界面,通过设置调度类型和调度周期配置任务流的定时调度。
- 调度类型:
once表示仅运行一次,crontab表示周期运行,crontab 配置保存约 5 分钟后才生效; - 调度周期:周期任务的时间设定,
* * * * *表示 minute hour day month week; - 过往依赖:是否依赖上一次运行的该任务流结果(只在定时调度有效);
- 有效实例数目:定时调度最新实例限制数目,0 表示不限制。
注意:实际生效时间约 5 分钟——后端定时器
task.make_timerun_config按crontab(minute='*/5')(myapp/config.py:698)每 5 分钟扫描一次,每次向后展开到now+300s(myapp/tasks/schedules.py:521)。配置界面字段提示仍写作"保存一个小时后才生效"(myapp/views/view_pipeline.py:1199),属过时文案,以实际调度为准。

定时调度的记录,可以点击"定时记录"按钮查看,定时调度记录将如下图所示。

结果可视化
构建任务模板时,在代码中按照规范格式在容器 /metric.json 中输出可视化结果(包括文字、图片和 echart 源码),即可在 web 界面上可视化展示。
实现说明:平台在 workflow 中为任务节点声明了名为
metric的可选 artifact,路径为/metric.json(myapp/views/view_pipeline.py:288/777/849)。
/metric.json 文件格式为:
[
{
"metric_type":"image",
"describe":"指标描述",
"image":"图片地址"
},
{
"metric_type":"text",
"describe":"指标描述",
"text":"文本内容"
},
{
"metric_type":"html",
"describe":"指标描述",
"html":"html源码内容"
},
{
"metric_type":"iframe",
"describe":"指标描述",
"url":"链接的地址"
},
{
"metric_type":"table",
"describe":"指标描述",
"file_path":"csv文件地址"
},
{
"metric_type":"echart-xx", # 其中 xx 可以为 line,bar,pie,scatter,radar,candlestick,heatmap,parallel,tree,sunburst;其中 tree、sunburst 数据为 json,其他类型数据为 csv
"describe":"指标描述",
"file_path":"csv或者json数据文件地址" # 详细配置方法参考 05-任务模板 中的 py_echart 数据格式说明
},
{
...或者是 echart 的 option 源码
}
]

通过以上设置,在运行该模板时,就可以在对应的任务节点中查看结果图。

pipeline 导入导出
选中需要导出的任务流,点击批量导出,可将任务流导出为 json 文件(接口 /pipeline_modelview/api/download/,view_pipeline.py:1926)。


如果平台需要重新部署,或者需要将 pipeline 迁移到新部署的集群,将导出的 json 文件再导入新的平台即可(导入接口 /pipeline_modelview/api/upload/,view_pipeline.py:1897;可通过 /pipeline_modelview/api/download_template/ 下载模板)。
导出导入 json 格式说明(注意 tasks 中字段名为 job_templete,与代码模板一致,见 view_pipeline.py:2104):
{
"pipeline英文名": {
"pipeline": {
"name": "pipeline英文名",
"describe": "pipeline描述",
"project": "public",
"parameter": {},
"dag_json": {
"任务1英文名": {
"upstream": []
},
"任务2英文名": {
"upstream": ["任务1英文名"]
}
},
"global_env": "AA=aa",
"expand": [
{
"id": "任务1英文名",
"type": "dataSet",
"position": {
"x": 任务1_x坐标,
"y": 任务1_y坐标
},
"data": {
"info": {
"describe": "任务1描述"
},
"name": "任务1英文名",
"label": "任务1中文名"
}
},
{
"id": "任务2英文名",
"type": "dataSet",
"position": {
"x": 任务2_x坐标,
"y": 任务2_y坐标
},
"data": {
"info": {
"describe": "任务2描述"
},
"name": "任务2英文名",
"label": "任务2中文名"
}
},
{
"source": "任务1",
"arrowHeadType": "arrow",
"target": "任务2",
"id": "任务1英文名-任务2英文名"
}
]
},
"tasks": [
{
"job_templete": "任务1模板名",
"name": "任务1英文名",
"label": "任务1中文名",
"volume_mount": "kubeflow-user-workspace(pvc):/mnt",
"resource_memory": "2G",
"resource_cpu": "2",
"resource_gpu": "0",
"resource_rdma": "0",
"args": {
"images": "任务1对应的每个参数取值",
"workdir": "任务1对应的每个参数取值",
"command": "任务1对应的每个参数取值"
}
},
{
"job_templete": "任务2模板名",
"name": "任务2英文名",
"label": "任务2中文名",
"volume_mount": "kubeflow-user-workspace(pvc):/mnt",
"resource_memory": "2G",
"resource_cpu": "2",
"resource_gpu": "0",
"resource_rdma": "0",
"args": {
"images": "任务2对应的每个参数取值",
"workdir": "任务2对应的每个参数取值",
"command": "任务2对应的每个参数取值"
}
}
]
}
}