尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Volcano Env Plugin 详解:为分布式训练 Pod 自动注入 VK_TASK_INDEX / VC_TASK_INDEX 环境变量

Volcano Env Plugin 详解:为分布式训练 Pod 自动注入 VK_TASK_INDEX / VC_TASK_INDEX 环境变量 Volcano Env Plugin 详解为分布式训练 Pod 自动注入 VK_TASK_INDEX / VC_TASK_INDEX 环境变量【免费下载链接】volcanoA Cloud Native Batch System (Project under CNCF)项目地址: https://gitcode.com/GitHub_Trending/vol/volcano本文基于 Volcano 官方用户指南 how_to_use_env_plugin.md系统讲解 Env Plugin 的注册方式、环境变量规则与真实调用链。读完之后你可以直接在 TensorFlow / MPI 等分布式作业中让每个 Pod 通过VK_TASK_INDEX和VC_TASK_INDEX环境变量感知自己在 Task 中的副本序号0 到 length-1并结合 env.go 等源码理解这一能力在 controller-manager 中的完整实现路径。一、Env Plugin 解决什么问题在分布式训练场景中同一个 Task 类型的多个副本 Pod 通常承担不同的角色切片。以文档给出的 TensorFlow 分布式 MNIST 为例作业由 1 个 ps 和 2 个 worker 组成每个 worker 负责一块原始数据切片。为了让每个 worker 知道自己该处理哪一块作业框架如 TensorFlow、MPI通常要求进程在启动时感知自己的序号index。Env Plugin 的设计目标就是在 Volcano Job 创建 Pod 时把这个序号以环境变量的形式自动注册进容器业务代码无需自行解析 Pod 名称或依赖额外的服务发现机制。核心规则来自官方文档环境变量 key 为VK_TASK_INDEX和VC_TASK_INDEX两者取值相同环境变量值是一个数字取值范围为0到length - 1其中length等于该 Task 的副本数replicas同时也是 Pod 在该 Task 内的下标注册 Env Plugin 时不需要任何参数值env: []即可。二、注册方式plugins: env: []Env Plugin 属于 Job 级别的插件通过 Job spec 的plugins字段声明。仓库示例 example/job-plugin.yaml 展示了多插件同时启用的写法apiVersion: batch.volcano.sh/v1alpha1 kind: Job metadata: name: test-job-plugin spec: minAvailable: 3 schedulerName: volcano policies: - event: PodEvicted action: RestartJob plugins: # 为每个容器追加 VK_TASK_INDEX 与 VC_TASK_INDEX 环境变量 env: [] # 提供 ssh 免密支持参数ssh-key-file-path默认 /root/.ssh ssh: [--ssh-key-file-path/home/user/.ssh] # 提供 hosts 文件挂载于 /etc/volcano/、headless service 等网络信息 svc: [--publish-not-ready-addressesfalse, --disable-network-policyfalse, --inject-hosts-envtrue] maxRetry: 5 queue: default tasks: - replicas: 3 name: default-nginx template: metadata: name: web spec: containers: - image: nginx imagePullPolicy: IfNotPresent name: nginx resources: requests: cpu: 1 restartPolicy: OnFailure注意两点env: []中的数组为空即可env 插件不支持也不消费任何参数从源码结构看Job 插件采用名称 - 构造器的注册表机制。factory.go 中通过RegisterPluginBuilder(env, env.New)把 env 插件注册进pluginBuilders与ssh、svc、tensorflow、mpi、pytorch、ray等插件并列。因此只要 controller-manager 启动env就是默认可用插件无需额外部署。三、完整实战示例TensorFlow 分布式 MNIST 使用任务序号以下是官方文档给出的完整可运行示例1 ps 2 worker的分布式 MNIST 作业。其核心思路是ps 与 worker 的 Pod 都从/etc/volcano/下读取由 svc 插件生成的 hosts 文件ps.host、worker.host再把自己的序号VK_TASK_INDEX拼装进 TensorFlow 的TF_CONFIG环境变量从而完成集群拓扑与自身角色的自描述apiVersion: batch.volcano.sh/v1alpha1 kind: Job metadata: name: tensorflow-dist-mnist spec: minAvailable: 3 schedulerName: volcano plugins: env: [] ## 注册 Env 插件注意数组中不需要任何值 svc: [] policies: - event: PodEvicted action: RestartJob queue: default tasks: - replicas: 1 name: ps template: spec: containers: - command: - sh - -c - | PS_HOSTcat /etc/volcano/ps.host | sed s/$/:2222/g | sed s/^//;s/$// | tr \n ,; WORKER_HOSTcat /etc/volcano/worker.host | sed s/$/:2222/g | sed s/^//;s/$// | tr \n ,; export TF_CONFIG{\cluster\:{\ps\:[${PS_HOST}],\worker\:[${WORKER_HOST}]},\task\:{\type\:\ps\,\index\:${VK_TASK_INDEX}},\environment\:\cloud\}; ## 从环境变量获取序号并写入 TF 作业配置 python /var/tf_dist_mnist/dist_mnist.py image: volcanosh/dist-mnist-tf-example:0.0.1 name: tensorflow ports: - containerPort: 2222 name: tfjob-port resources: {} restartPolicy: Never - replicas: 2 name: worker policies: - event: TaskCompleted action: CompleteJob template: spec: containers: - command: - sh - -c - | PS_HOSTcat /etc/volcano/ps.host | sed s/$/:2222/g | sed s/^//;s/$// | tr \n ,; WORKER_HOSTcat /etc/volcano/worker.host | sed s/$/:2222/g | sed s/^//;s/$// | tr \n ,; export TF_CONFIG{\cluster\:{\ps\:[${PS_HOST}],\worker\:[${WORKER_HOST}]},\task\:{\type\:\worker\,\index\:${VK_TASK_INDEX}},\environment\:\cloud\}; python /var/tf_dist_mnist/dist_mnist.py image: volcanosh/dist-mnist-tf-example:0.0.1 name: tensorflow ports: - containerPort: 2222 name: tf-job-port resources: {} restartPolicy: Never说明svc: []与env: []配合使用。env 只负责注入序号而/etc/volcano/ps.host、/etc/volcano/worker.host这些 hosts 文件由 svc 插件提供how_to_use_svc_plugin.md 有专门说明。仓库中 tf-dist-mnist-example.yaml 即为该示例的落地版本minAvailable: 3对应 ps(1) worker(2) 的总副本数保证所有 Pod 同时就绪才启动符合分布式训练的 gang 语义worker 的TaskCompleted - CompleteJob策略表示全部 worker 完成后整个作业结束。验证结果配置 env 插件后作业内所有 Pod 都会多出VK_TASK_INDEX与VC_TASK_INDEX两个环境变量。进入 Pod 执行env | grep TASK_INDEX可以看到ps 副本tensorflow-dist-mnist-ps-0[roottensorflow-dist-mnist-ps-0 /] env | grep TASK_INDEX VK_TASK_INDEX0 VC_TASK_INDEX0两个 worker 副本tensorflow-dist-mnist-worker-0与tensorflow-dist-mnist-worker-1分别得到0和1[roottensorflow-dist-mnist-worker-0 /] env | grep TASK_INDEX VK_TASK_INDEX0 VC_TASK_INDEX0[roottensorflow-dist-mnist-worker-1 /] env | grep TASK_INDEX VK_TASK_INDEX1 VC_TASK_INDEX1这与规则完全一致值为0到replicas - 1即该 Pod 在其 Task 内的下标。四、源码级解析序号从哪来、环境变量何时被注入4.1 序号的来源Pod 名称的最后一段Env Plugin 的OnPodCreate回调env.go 第 45-59 行是整个功能的核心func (ep *envPlugin) OnPodCreate(pod *v1.Pod, job *batch.Job) error { index : jobhelpers.GetPodIndexUnderTask(pod) // add VK_TASK_INDEX and VC_TASK_INDEX env to each container for i : range pod.Spec.Containers { pod.Spec.Containers[i].Env append(pod.Spec.Containers[i].Env, v1.EnvVar{Name: TaskVkIndex, Value: index}, v1.EnvVar{Name: TaskIndex, Value: index}) } // add VK_TASK_INDEX and VC_TASK_INDEX env to each init container for i : range pod.Spec.InitContainers { pod.Spec.InitContainers[i].Env append(pod.Spec.InitContainers[i].Env, v1.EnvVar{Name: TaskVkIndex, Value: index}, v1.EnvVar{Name: TaskIndex, Value: index}) } return nil }index由 helpers.go 中的GetPodIndexUnderTask计算func GetPodIndexUnderTask(pod *v1.Pod) string { num : strings.Split(pod.Name, -) if len(num) 3 { return num[len(num)-1] } return }Volcano Job controller 创建 Pod 时采用固定的命名格式PodNameFmt %s-%s-%djob 名-task 名-副本序号因此对 Pod 名称按-切分后取最后一段即得到该 Pod 在 Task 中的下标。这也解释了为什么示例中tensorflow-dist-mnist-worker-1拿到的值是1。两个关键实现细节值得注意init 容器同样会被注入。OnPodCreate同时遍历pod.Spec.Containers和pod.Spec.InitContainers这意味着即使你的序号逻辑写在 init 容器例如初始化阶段拉取分片配置里也能读到注入是 append 语义。环境变量是追加到容器现有 Env 列表之后的不会覆盖你自行定义的同名变量——从源码看若用户模板中已定义VC_TASK_INDEX会出现同名 EnvVar 并存的情况业务侧应避免自定义同名 key。4.2 调用链从spec.plugins到OnPodCreateenv 插件的触发链路清晰可查插件注册factory.go 在init()中执行RegisterPluginBuilder(env, env.New)将名称env与构造器env.New绑定Pod 创建钩子Job controller 在生成每个 Pod 后调用 job_controller_plugins.go 中的pluginOnPodCreate它遍历job.Spec.Plugins对每个插件名查找 builder并以pb(client, args).OnPodCreate(pod, job)执行作业生命周期标记env 插件的OnJobAdd/OnJobDelete会在job.Status.ControlledResources中写入/清理plugin-env标记用于记录该 Job 由哪些插件控制。单元测试 job_controller_plugins_test.go 中的TestPluginOnPodCreate覆盖了该钩子的执行路径。4.3 两个变量名为何并存变量名常量定义在 const.goconst ( // ConfigMapMountPath mount path ConfigMapMountPath /etc/volcano // TaskVkIndex used as key in container env TaskVkIndex VK_TASK_INDEX // TaskIndex is used as key in container env TaskIndex VC_TASK_INDEX )官方文档明确说明由于历史原因VK_TASK_INDEX与VC_TASK_INDEX两个环境变量同时存在且两者取值相同VK_TASK_INDEX将在后续版本中逐步弃用。新写的作业建议统一使用VC_TASK_INDEX而存量作业如 TensorFlow / MPI 示例脚本继续使用VK_TASK_INDEX仍完全兼容。e2e 测试 test/e2e/jobseq/tensorflow.go 中的 TF 作业脚本同样直接引用${VK_TASK_INDEX}构造TF_CONFIG可视为该变量在真实作业中的回归验证。五、注意事项与适用边界注册语法plugins下env: []必须留空数组填任何值都会被忽略env 插件的pluginArguments在OnPodCreate中并不被消费序号范围每个 Task 独立编号从0到该 Task 的 replicas - 1跨 Task 不连续例如上例中ps-0的序号是0worker-0/1的序号也是0/1业务需结合 Task 类型与序号共同定位身份变量弃用计划新脚本优先使用VC_TASK_INDEX与框架级插件的关系如果作业直接使用tensorflow/mpi/pytorch等分布式框架插件同样在 factory.go 中注册这些插件会注入各自的框架环境变量如TF_CONFIG等。Env Plugin 更通用适合任意需要副本序号自感知的作业类型可与框架插件独立叠加使用适用前提该能力由 controller-manager 提供的 Job 控制器实现要求集群已部署 Volcano 并使用batch.volcano.sh/v1alpha1的Job资源且schedulerName: volcano。六、延伸阅读插件机制总体设计docs/design/custom-plugin.md网络信息插件hosts 文件与 headless servicedocs/user-guide/how_to_use_svc_plugin.md作业策略PodEvicted / TaskCompleted 等事件动作docs/user-guide/how_to_use_job_policy.md可运行示例example/job-plugin.yaml、example/integrations/tensorflow/dist-mnist/tf-dist-mnist-example.yaml【免费下载链接】volcanoA Cloud Native Batch System (Project under CNCF)项目地址: https://gitcode.com/GitHub_Trending/vol/volcano创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表