
用 Argo Workflow 编排 Volcano MPI 作业在 Kubernetes 上跑通 MPI Hello World 全流程指南【免费下载链接】volcanoA Cloud Native Batch System (Project under CNCF)项目地址: https://gitcode.com/GitHub_Trending/vol/volcano本指南完整讲解如何在 Kubernetes 集群中以Argo Workflow 的 resource 模板Resource Template创建并托管Volcano Jobbatch.volcano.sh/v1alpha1从而让 Argo 的 DAG/Step 流程控制能力与 Volcano 的批量调度能力gang scheduling、任务间依赖、ssh/svc 插件协同工作。文中以仓库 example/integrations/argo/mpi 中的hello-world.yaml为例带你完成从安装 Argo、准备 RBAC、提交工作流、观察日志到清理环境的完整实操并逐段剖析 MPI master/worker 的启动时序、kubectl wait等待机制与日志跟随技巧读完即可在你的集群中复现同样的 MPI 作业编排。一、为什么要在 Argo Workflow 里运行 Volcano JobVolcano 提供的是批量作业调度能力gang scheduling、队列、任务间依赖等而 Argo Workflow 提供的是工作流编排能力步骤、DAG、参数化。二者互补Argo 负责按什么顺序、在什么依赖关系下运行哪些作业Volcano 负责每个作业如何被调度、资源如何被抢占与回收。Argo 的resource 模板允许用户对任意 Kubernetes 资源包括 CRD执行 create / apply / delete / patch 等操作因此可以天然地把 Volcano Job 作为 Argo 工作流的一个步骤来管理。仓库中 example/integrations/argo/README.md 的说明指出通过这一机制可以将 Volcano Job 集成进 Argo Workflow并借用 Argo 为 Volcano 增加作业依赖管理和 DAG 流程控制能力。除了本文主角 MPI 示例仓库还提供了另外两种编排范式的完整清单example/integrations/argo/10-job-step.yaml使用 Argo 的Steps模板顺序编排多个 Volcano Jobstep 之间串行同一 step 内可并行多个任务。example/integrations/argo/20-job-DAG.yaml使用 Argo 的DAG模板表达作业依赖图如 B、C 依赖 AD 依赖 B 与 C。MPI 场景之所以特殊是因为 MPI 作业需要一个 master 节点通过 ssh 拉起多个 worker 节点协同计算这正好同时用到了 Volcano 的 gang scheduling 与 Argo 的 DAG 并行任务提交作业 跟随日志并行执行。二、快速开始安装 Argo 并准备 RBAC2.1 安装 Argo Workflows若你尚未安装 Argo Workflows可以使用官方 Quick Start 方式安装kubectl create namespace argo kubectl apply -n argo -f https://github.com/argoproj/argo-workflows/releases/download/v3.7.10/quick-start-minimal.yaml该版本号与仓库示例保持一致Argo Workflows v3.7.10注意以下步骤可能与 Argo Workflows 4.0 不兼容见文末注意事项。2.2 准备 RBAC让 Argo 能管理 Volcano Job 与 PodArgo 的 resource 模板在执行时相当于代表工作流绑定的 ServiceAccount 去操作目标资源因此必须为该 ServiceAccount 授予对应资源的读写权限。仓库提供的 example/integrations/argo/mpi/rbac.yaml 定义了最小权限集本示例基于 Argo 官方 workflow-rbac 文档改编apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: argo-workflowtaskresults-role namespace: argo rules: - apiGroups: [argoproj.io] resources: [workflowtaskresults] verbs: [create, patch, get, list, watch] - apiGroups: [batch.volcano.sh] resources: [jobs] verbs: [create, get, list, watch, delete] - apiGroups: [] resources: [pods,pods/log] verbs: [get,list,watch] --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: argo-workflowtaskresults-binding namespace: argo subjects: - kind: ServiceAccount name: argo namespace: argo roleRef: kind: Role name: argo-workflowtaskresults-role apiGroup: rbac.authorization.k8s.io要点说明batch.volcano.sh组下的jobsArgo 需要 create / get / list / watch / delete Volcano JobCRD这是 resource 模板能否创建并轮询作业状态的关键pods与pods/log本示例的跟随 master 日志任务与 master 的 InitContainer 需要通过kubectl查询 Pod 状态、读取日志因此需要 pods 的 get / list / watch 以及 pods/log 的读取权限argoproj.io组下的workflowtaskresultsArgo 用于保存工作流任务结果属于 Argo 自身运行所需若你的 Volcano Job 运行在其它 namespace请将 Role / RoleBinding 相应调整或改用 ClusterRole / ClusterRoleBinding对应 example/integrations/argo/README.md 中提到的必要时可手动创建 clusterrole 与 clusterrolebinding。安装kubectl apply -f rbac.yaml三、提交 MPI Hello World 工作流3.1 创建 WorkflowTemplate 并提交仓库的 example/integrations/argo/mpi/hello-world.yaml 定义的是一个名为volcano-mpi-hello的WorkflowTemplate而不是直接实例化的 Workflow。创建模板后使用argo submit --from workflowtemplate/...实例化并提交kubectl apply -f hello-world.yaml WF_NAMEvolcano-mpi-hello-$(date %s) argo submit --from workflowtemplate/volcano-mpi-hello -n argo --name $WF_NAME argo watch $WF_NAME -n argoargo watch会实时跟踪工作流直至结束终端中即可看到两个 DAG 任务submit-job与follow-logs的状态流转。3.2 参数化说明WorkflowTemplate 在spec.arguments.parameters中声明了一个参数arguments: parameters: - name: job-name value: mpi-hello-jobjob-name同时被用于Volcano Job 的metadata.name后续kubectl查询 Pod 时使用的标签选择器volcano.sh/job-name{{workflow.parameters.job-name}}。这意味着你可以在提交时用-p job-namemy-custom-name覆盖作业名多个 MPI 作业即可在同一个 namespace 内并行运行而互不干扰。四、剖析 hello-world.yamlWorkflowTemplate 内部结构hello-world.yaml的整体结构是一个包含 3 个模板的 WorkflowTemplate入口mainDAG、follow-master-logs日志跟随容器与submit-volcano-jobresource 模板创建 Volcano Job。下面逐层拆解。4.1 入口模板DAG 并行编排spec: serviceAccountName: argo entrypoint: main templates: - name: main dag: tasks: - name: submit-job template: submit-volcano-job - name: follow-logs template: follow-master-logs入口模板是一个 DAG其中包含两个互相之间没有依赖的任务submit-job调用 resource 模板创建 Volcano Job并等待其状态变为Completed/Failedfollow-logs与submit-job并行运行负责在 MPI master Pod 就绪后持续流式输出其日志。这正是本示例的核心设计之一submit-job负责等作业跑完follow-logs负责实时展示日志二者并行使得用户既能拿到最终结果又能实时看到 MPI 进程的输出否则资源模板等待期间日志不可见。4.2 resource 模板以 Argo 管理 Volcano Job 生命周期- name: submit-volcano-job resource: action: create setOwnerReference: true successCondition: status.state.phase Completed failureCondition: status.state.phase Failed manifest: | apiVersion: batch.volcano.sh/v1alpha1 kind: Job ...关键字段action: create对下面manifest中的资源执行 create也支持 apply / delete / patchsetOwnerReference: true自动为创建的 Volcano Job 设置 owner reference 指向当前 Workflow从而让作业随工作流生命周期被清理对应 example/integrations/argo/README.md 中为确保 Argo 能管理其创建的资源需添加 ownerReferences的说明若手动声明写法为ownerReferences: [{apiVersion: argoproj.io/v1alpha1, blockOwnerDeletion: true, kind: Workflow, name: {{workflow.name}}, uid: {{workflow.uid}}}]successCondition/failureConditionArgo 会通过kubectl get -o json -w轮询资源状态并按 Kubernetes 标签选择语法对任意字段求值。此处对应 Volcano Job 状态中的status.state.phase Completed作业所有任务均已完成成功 Failed作业重试达到上限后失败两者可根据实际业务场景调整。4.3 Volcano Job 主体MPI master / worker 拓扑被 Argo 托管的 Volcano Job 本体batch.volcano.sh/v1alpha1的Job如下spec: minAvailable: 3 schedulerName: volcano plugins: ssh: [] svc: [] tasks: - name: mpimaster replicas: 1 policies: - event: TaskCompleted action: CompleteJob template: spec: serviceAccountName: argo initContainers: - name: wait-for-workers image: mcr.microsoft.com/oss/kubernetes/kubectl:v1.26.3 command: [/bin/bash, -c, kubectl wait pod -l volcano.sh/job-name{{workflow.parameters.job-name}},volcano.sh/task-specmpiworker --forconditionReady --timeout600s] containers: - name: mpimaster image: volcanosh/example-mpi:0.0.3 ... - name: mpiworker replicas: 2 template: spec: containers: - name: mpiworker image: volcanosh/example-mpi:0.0.3 ...逐一解读minAvailable: 31 个 mpimaster 2 个 mpiworker。这是 gang scheduling 的最小可用成员数只有 3 个任务都有资源可调度时才会被整体拉起参见 docs/min-avaiable-member-resource.md 与 docs/gang-aware-eviction-design.md 的相关设计说明schedulerName: volcano明确让 Volcano 调度器接管该作业的 Pod 调度plugins: {ssh: [], svc: []}启用 Volcano 的ssh 插件在/etc/volcano下生成各任务间 ssh 所需的 host 文件如mpiworker.host与svc 插件为每个任务创建 headless Service使 Pod 能以pod.task-index.job形式互相发现对应日志中mpi-hello-job-mpiworker-0.mpi-hello-job这样的 DNS 名。原生 MPI 示例见 example/integrations/mpi/mpi-example.yaml其 master 命令与 hello-world.yaml 一脉相承MPI_HOSTcat /etc/volcano/mpiworker.host | tr \n ,; mkdir -p /var/run/sshd; /usr/sbin/sshd; mpiexec --allow-run-as-root --host ${MPI_HOST} -np 2 mpi_hello_world;master 的policiesevent: TaskCompletedaction: CompleteJob——master 任务完成后即宣告整个 Job 完成status.state.phase Completed这正是 resource 模板 successCondition 得以满足的信号master 的 InitContainerwait-for-workers由于 master 要通过 ssh 连接 worker必须先等 2 个 worker Pod 的 22 端口就绪readinessProbe为 TCP 探测 22 端口。InitContainer 使用kubectl wait pod -l volcano.sh/job-name...,volcano.sh/task-specmpiworker --forconditionReady --timeout600s等待这要求 InitContainer 具备查询 Pod 的 RBAC 权限即前文 rbac.yaml 中 pods get/list/watch 的来源resources.requests/limits中nvidia.com/gpu: 0、rdma/ib: 0预留的扩展资源位。仓库注释说明可将这些值从 0 调大以消耗节点上的 NIC 或 GPU如配合 SR-IOV device plugin从而把 MPI 计算固定到特定节点当一个节点上的全部 NIC / GPU 都被本作业消耗后其它 Pod 将无法再调度到该节点适用于独占 RDMA / GPU 卡的 MPI 集群场景worker 的readinessProbeTCP 探测 22 端口initialDelaySeconds: 5、periodSeconds: 10、failureThreshold: 5用于向kubectl wait --forconditionReady暴露就绪状态。4.4 可选的 dependsOn 编排master 任务的模板中有一段被注释掉的配置# Optional: use dependsOn to start master after workers exist. # If dependsOn is enabled in this example, set minAvailable to 2 # (worker replica count). Also bear in mind that master is then # not gang-scheduled together with workers. # dependsOn: # name: # - mpiworker若启用dependsOn: mpiworkermaster 将在 worker 之后才被创建此时minAvailable应改为 2即只对 worker 做 gang 调度master 不再与 worker 一起被 gang 调度失去了整体性保证。默认不启用时master 与 worker 作为一个整体被 gang 调度通过 InitContainer kubectl wait实现先等 worker 就绪、再启动 ssh 计算的时序这是本示例推荐的做法。五、日志跟随机制与预期输出5.1 follow-master-logs 任务的实现- name: follow-master-logs serviceAccountName: argo activeDeadlineSeconds: 300 container: image: mcr.microsoft.com/oss/kubernetes/kubectl:v1.26.3 command: [bash, -c] args: - | NS$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace) echo Waiting for MPI master pod... POD until [ -n $POD ]; do POD$(kubectl get pods -n $NS \ -l volcano.sh/job-name{{workflow.parameters.job-name}},volcano.sh/task-specmpimaster \ -o jsonpath{.items[0].metadata.name} 2/dev/null) sleep 2 done echo Found pod $POD while true; do PHASE$(kubectl get pod $POD -n $NS -o jsonpath{.status.phase} 2/dev/null) if [[ $PHASE Running || $PHASE Succeeded || $PHASE Failed ]]; then break; fi sleep 2 done echo Streaming logs... kubectl logs -f -n $NS -c mpimaster $POD || true该任务共分三步轮询查找 master Pod通过标签选择器volcano.sh/job-name作业名volcano.sh/task-specmpimaster等待 master Pod 出现每 2 秒一次等待 Pod 进入终态或运行态直到 phase 为 Running / Succeeded / Failed流式输出日志kubectl logs -f跟随 master 容器容器名mpimaster输出|| true保证日志流中断不至于令任务失败。activeDeadlineSeconds: 300为其设置了 5 分钟的执行上限。这套kubectl wait 轮询 日志跟随的思路来源于 Azure 面向 Kubernetes 上 MPI/HPC 的实践NDM v4 A100 部署指南仓库将其引入 Argo 模板。5.2 预期输出follow-master-logs任务的预期输出如下Waiting for MPI master pod... Found pod mpi-hello-job-mpimaster-0 Waiting for pod to start or finish... Pod phase: Running Streaming logs... Running MPI hello world... Warning: Permanently added mpi-hello-job-mpiworker-0.mpi-hello-job (ED25519) to the list of known hosts. Warning: Permanently added mpi-hello-job-mpiworker-1.mpi-hello-job (ED25519) to the list of known hosts. Hello world from processor mpi-hello-job-mpiworker-0, rank 0 out of 2 processors Hello world from processor mpi-hello-job-mpiworker-1, rank 1 out of 2 processors可以看到日志中出现两个 worker 的 DNS 名mpi-hello-job-mpiworker-0.mpi-hello-job/mpi-hello-job-mpiworker-1.mpi-hello-job印证了 svc 插件生成的 headless Service 命名规则两条 Hello world 表明mpiexec -np 2确实通过 ssh 在两个 worker 上启动了 2 个 MPI rank当 master 完成输出后TaskCompleted策略将 Job 置为 Completedsubmit-job的 successCondition 随即满足整个 Workflow 以成功收尾。六、清理环境运行完成后按以下顺序清理资源argo delete $WF_NAME -n argo kubectl delete -f hello-world.yaml kubectl delete -f rbac.yaml由于setOwnerReference: true的存在Volcano Job 会随工作流删除而被级联清理argo delete删除工作流实例随后删除 WorkflowTemplate 与 RBAC。七、进阶用 Steps 与 DAG 编排多个 Volcano Job理解 MPI 单作业流程后可进一步查看仓库中另外两个完整示例将 Volcano Job 接入更复杂的流水线Steps 顺序编排example/integrations/argo/10-job-step.yaml 定义了volcano-step-job流程第一步hello-1执行完毕后第二步并行运行hello-2a、hello-2b每个步骤都是一个独立的 Volcano JobgenerateName: step-job-task-通过ownerReferences绑定工作流生命周期DAG 依赖编排example/integrations/argo/20-job-DAG.yaml 定义了volcano-dag-job任务 B、C 依赖 A任务 D 依赖 B 与 C即先 A 后 B/C最后 D的分阶段批量作业依赖图。两个示例的 Volcano Job 均带有policies: - event: PodEvicted action: RestartJob maxRetry: 1 queue: default plugins: ssh: [] env: [] svc: []这些字段展示了 Volcano Job 面向长时/容错场景的常用配置Pod 被驱逐时重启作业、失败重试上限、使用default队列以及同时启用 ssh / env / svc 插件。若作业为长期运行型如 nginxexample/integrations/argo/README.md 特别提醒必须为模板设置activeDeadlineSeconds否则 Workflow 将因资源模板一直等待而无法进入下一步。八、注意事项与适用前提根据仓库 example/integrations/argo/mpi/README.md 的 Notes使用本方案时有以下几点限制Argo 版本兼容性上述步骤基于 Argo Workflows v3.7.10 编写可能与Argo Workflows 4.0不兼容resource 模板的字段语义可能变化请以实际版本文档为准RBAC 要求InitContainer 使用kubectl wait查询 worker Pod 状态因此必须为其授予额外的 Pod 查询权限即rbac.yaml中 pods get/list/watch否则等待会失败资源独占将hello-world.yaml中的nvidia.com/gpu或rdma/ib请求从 0 调大可消耗节点上的 NIC / GPU当节点资源被本作业完全占用后其它 Pod 将无法调度到该节点请谨慎规划资源配额适用前提本示例需要集群中已安装 Volcano 调度器schedulerName: volcano依赖其工作且 Argo 与示例资源位于argonamespaceWorkflowTemplate.metadata.namespace、RoleBinding 均指向argo若部署到其它 namespace 需同步调整。九、进一步阅读原生非 ArgoVolcano MPI 作业示例example/integrations/mpi/mpi-example.yamlhello-world.yaml 中 master/worker 语法即改编自此处Argo 集成 Volcano Job 总览RBAC 与 ownerReferences 详解example/integrations/argo/README.mdSteps / DAG 编排完整清单example/integrations/argo/10-job-step.yaml、example/integrations/argo/20-job-DAG.yamlVolcano 作业 API 与任务依赖设计docs/job-api.md、docs/task-order.md、docs/gang-aware-eviction-design.md最小可用成员资源minAvailable设计docs/min-avaiable-member-resource.md。通过本指南你已经掌握了一条完整可运行的Argo 提交 → Volcano 调度 → MPI 计算 → 日志回流链路既能用 Argo 的 DAG/Steps 表达批量作业的依赖与并发又能享受 Volcano 对 MPI 这类多角色作业的 gang 调度、ssh/svc 插件与任务策略带来的开箱即用能力。【免费下载链接】volcanoA Cloud Native Batch System (Project under CNCF)项目地址: https://gitcode.com/GitHub_Trending/vol/volcano创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考