mcpField
L
launch-nemo-rl

launch-nemo-rl

github.com/promptingcompany云与 DevOps039 次安装17 周前更新
代码仓库

关于 launch-nemo-rl

这是使用 `nrl-k8s` 在 Kubernetes 上启动、监控和排查 NeMo-RL 配方的操作指南,涵盖临时与长期运行的 Ray 集群流程,并强调操作共享集群前先核实状态。

主要功能

  1. 01使用 `nrl-k8s run` 提交配方
  2. 02选择临时或长期集群
  3. 03验证配方与基础设施配置
  4. 04查看集群、作业和 Pod 日志
  5. 05管理 Ray 集群与部署

适用场景

  1. 01启动一次性 NeMo-RL 训练
  2. 02迭代配方时复用集群
  3. 03检查作业进度并诊断故障

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/promptingcompany/nv-skills --skill launch-nemo-rl

安装后在 Claude Code 中输入/launch-nemo-rl确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

BENCHMARK.md
skill-card.md
skill.oms.sig
evals/
evals.json

详细介绍

launch-nemo-rl — 通过 nrl-k8s 在 Kubernetes 上运行 NeMo-RL 配方

这是 infra/nrl_k8s/ 下 nrl-k8s CLI 的操作指南。当用户要求在 Kubernetes 集群上启动 / 迭代 / 调试 NeMo-RL 配方时,请遵循本指南。操作前先确认当前状态(kubectl、git log、配方和基础设施文件)——集群由多人共用,错误操作的代价很高。

1. 一条命令,两种模式

只有一个顶层提交命令:nrl-k8s run。它有两种生命周期模式。

模式调用使用时机运行后集群?
临时(默认)nrl-k8s run一次性运行。KubeRay 会应用 RayJob、运行,然后拆除集群。适用于大多数运行。否(自动拆除)
长期运行nrl-k8s run --raycluster开发循环。复用匹配的运行中集群;若集群不存在,则应用配置;若配置有偏差,则发出警告并复用(传入 --recreate 可替换集群)。随后提交守护进程和训练任务。迭代时的首选方式。是

请先问:“运行后我还需要这个集群吗?”如果需要,请使用 --raycluster。否则请使用默认模式(临时模式)。

CLI 的其余命令用于观测和分阶段控制:

命令用途
nrl-k8s check验证配方和基础设施文件是否匹配;可选择写出完全解析后的清单(-o)。
nrl-k8s status查看各角色的 RayCluster 状态、头节点 Pod 阶段、工作节点 Pod 阶段和守护进程作业状态。
nrl-k8s cluster up/down/list/dashboard独立于运行管理 RayCluster(例如,使用 --dry-run 渲染清单)。
nrl-k8s job list/logs/stop查看已提交到某个角色集群的 Ray Job。
nrl-k8s logs查看某个角色的 Pod / 守护进程日志,无需提交 ID。

2. 配方与基础设施文件

每次启动都需要两个文件。请通过 --infra 传入基础设施文件,不要将其合并到内联配置中:

nrl-k8s run infra/nrl_k8s/examples/<recipe>.yaml \
  --infra infra/nrl_k8s/examples/<recipe>.<profile>.infra.yaml
  • 配方(例如 qwen3_30b_math_8n_4gpu.yaml)——NeMo-RL 配置:模型、GRPO/SFT 参数、cluster.{gpus_per_node,num_nodes}。使用 defaults: 继承自 examples/configs/recipes/llm/...。
  • 基础设施文件(例如 *.<profile>.infra.yaml)——K8s/Ray 配置:命名空间、镜像、服务账号、kuberay: 下的 RayCluster 规范、可选的 deployments:、submit.submitter、launch.{mode,codeSource,codePath,entrypoint}。成对文件的名称遵循 <recipe>.<profile>[.prod].infra.yaml 格式,其中 <profile> 表示硬件目标(例如 gb300)。

infra/nrl_k8s/examples/ 中提供了示例文件对——请阅读同一目录下的文件,了解目标配置的当前约定。

3. 长期运行模式标志

三个相互独立的维度。--mode 是一个宏,用于选择默认值;单个标志可覆盖这些默认值。

--mode interactive   → --submitter portForward  --code-source upload  (tails logs)
--mode batch         → --submitter exec         --code-source image   (returns after nohup)
  • 提交方式:portForward 使用 kubectl port-forward + Ray Job SDK(会获取一个由 dashboard 跟踪的 submission_id)。exec 使用 kubectl exec + head pod 上的 nohup(没有 submission_id;driver 在 dashboard 中显示为 type=DRIVER)。
  • 代码来源:upload 会从笔记本电脑暂存一个 working_dir(Ray 上限为 100 MiB)。image / lustre 需要代码位于 pod 的文件系统上,并与 --code-path 配合使用(通常为 /opt/nemo-rl);在标准基础设施示例中,该路径是共享文件系统 PVC 挂载的 subPath。
  • 等待方式:--wait 会持续跟踪日志,直到任务进入终止状态;--no-wait 会在 driver 运行后立即返回。

其他仅适用于长期运行模式的标志:

  • --replace — 提交新任务前,停止所有正在运行的训练任务 / 守护任务(为守护任务的 submissionIds 添加时间戳后缀,以便 Ray 接受重新提交)。
  • --recreate — 删除并重新应用实时 spec 与渲染后的清单不一致的 RayCluster(默认会发出警告并复用)。
  • --skip-daemons — 启动所有声明的集群,但只提交训练任务。适用于 gym / generation 已运行正常的分离式配置。

注意:在入口点会执行 cd /opt/nemo-rl(或其他镜像内 / Lustre 路径)并从该路径加载配置的基础设施中,--code-source upload 不会覆盖 pod 上的配置——上传的 working_dir 位于 /tmp/ray/...,但入口点会切换到其他路径。要实际测试本地配置更改,请将修改同步到挂载到 pod 的共享文件系统,或修改入口点中的 Hydra 覆盖项。

4. 临时模式标志(--rayjob)

设置 --rayjob 后,run 会进入 RayJob 代码路径。相关标志:

  • --rayjob-name NAME — RayJob 元数据名称(默认为训练集群名称)。
  • --shutdown / --no-shutdown — 默认值为 true:Ray Job 达到终止状态后,KubeRay 会删除 RayCluster。
  • --ttl SECONDS — 默认值为 3600s:运行结束后保留 RayJob 对象,以便事后查看日志。
  • --wait / --no-wait — 默认值为 wait:轮询 jobDeploymentStatus,直到状态为 Complete/Failed。--no-wait 会在应用 RayJob 后立即返回。
  • --timeout SECONDS — 默认值为 86400s(24h):限制 --wait 轮询的时长。
  • --dry-run — 渲染 RayJob 清单并打印;不应用该清单。

在 --rayjob 模式下,--replace / --recreate / --skip-daemons 会被静默忽略(生命周期由 KubeRay 管理)。

5. 在不触碰共享文件系统的情况下迭代配置

如果 pod 文件系统上的配置值不适合你的实验,请在入口点上使用 Hydra 覆盖项,而不是分叉配置。模式如下:

entrypoint: |
  set -eu
  cd /opt/nemo-rl
  RUN_ID="\${RAY_JOB_SUBMISSION_ID:-\${NRL_K8S_RUN_ID:-$(date -u +%Y%m%d-%H%M%S)}}"
  python -u examples/run_grpo.py \
    --config infra/nrl_k8s/examples/<recipe>.yaml \
    logger.wandb_enabled=true \
    logger.wandb.project=<project> \
    "logger.wandb.name=<run-name>-\${RUN_ID}"

使用反斜杠转义 ${…}。否则 OmegaConf 会将其解释为插值,并因 shell 风格的 ${VAR:-default} 而报错。RUN_ID 会依次解析为 RAY_JOB_SUBMISSION_ID(rayjob 模式下由 KubeRay 注入)→ NRL_K8S_RUN_ID(长期运行模式下由 CLI 注入)→ 本地时间戳,因此在两种路径下名称都具有唯一性。

6. 各配置的注意事项(硬件 + 调度器 + DRA)

每个 infra YAML 都定义了一种硬件/调度器配置。infra/nrl_k8s/examples/ 中的具体示例是其目标配置的权威参考——编写新文件前,请先查看相邻的 infra 文件。以下方面通常会有所不同:

  • 每个节点的 GPU 数量(例如 4 个或 8 个)——必须与配方中的 cluster.gpus_per_node 一致,否则工作器会一直处于 Pending 状态。
  • 节点选择器——头部 Pod 通常会调度到仅含 CPU 的节点池;GPU 工作器则通过 nvidia.com/gpu.product 或节点组标签进行匹配。
  • 调度器——KAI(schedulerName: kai-scheduler + kai.scheduler/queue 标签)结合拓扑注解(kai.scheduler/topology、kai.scheduler/topology-required-placement),可将工作器成组调度到同一集群中。若没有这些设置,Pod 可能会落到不同机架上,NVLink/RoCE 将无法跨机架连接。
  • DRA 声明——通过引用 ResourceClaimTemplate 的 resourceClaims 挂载 ComputeDomain + RoCE。当工作器 Pod 规格中包含 DRA 声明引用时,CLI 会自动创建/删除这些资源,无需手动设置。
  • 密钥——始终使用 secretKeyRef(wandb-api-key、镜像拉取密钥)。切勿直接嵌入。
  • 共享文件系统挂载——通常使用 Lustre PVC 挂载两次:一次挂载到代码路径(例如 /opt/nemo-rl,使用限定用户范围的 subPath),另一次挂载到工作区根目录(例如 /mnt/rl-workspace),用于存放数据集、HF 缓存和检查点。

应用 infra 前,请确认目标命名空间中已存在所需的前置资源:

kubectl get pvc <workspace-pvc>
kubectl get secret <wandb-secret> <image-pull-secret>
kubectl get sa <service-account>

7. 端到端工作流

7a. 全新的一次性运行(rayjob)
# From the NeMo-RL repo root:
nrl-k8s check <recipe> --infra <infra>                               # validate first
nrl-k8s run <recipe> --infra <infra> --rayjob --dry-run              # render RayJob manifest
nrl-k8s run <recipe> --infra <infra> --rayjob --no-wait              # apply, returns fast

监视状态并清理资源(即使笔记本电脑断开连接也能正常工作,因为生命周期由 KubeRay 管理):

kubectl get rayjob -n default <name> -w
kubectl get raycluster -n default                                    # empty = teardown succeeded
7b. 开发循环(长期运行)
nrl-k8s run <recipe> --infra <infra> --run-id $(date +%Y%m%d-%H%M%S)
# Edits in the recipe? Just re-run — reuses the live cluster.
# Pod spec changed? Add --recreate to delete + re-apply.
# Disagg recipe with gym/gen already healthy? --skip-daemons.
7c. 首次启动分离式部署
nrl-k8s run <recipe> --infra <disagg-infra> --mode batch --code-source image
7d. 仅限集群的生命周期管理
nrl-k8s cluster up   <recipe> --infra <infra> --target kuberay.training --wait
nrl-k8s cluster up   <recipe> --infra <infra> --target kuberay.training --dry-run   # render manifest
nrl-k8s cluster down <recipe> --infra <infra> --target kuberay.training --wait
nrl-k8s cluster down <recipe> --infra <infra>                                       # tear down all
nrl-k8s cluster list -n default
nrl-k8s cluster dashboard <cluster-name>                                  # port-forward + browser
7e. 部署(例如 nemo-skills sandbox)
# Bring up just the deployment
nrl-k8s cluster up <recipe> --infra <infra> --target deployments.nemo_skills
# Tear down just the deployment
nrl-k8s cluster down <recipe> --infra <infra> --target deployments.nemo_skills
# Tear down everything (RayClusters + Deployments)
nrl-k8s cluster down <recipe> --infra <infra>

infra YAML 中的 deployments: 部分声明了与 RayClusters 一同管理的 Kubernetes 部署。CLI 会从顶层 infra 键中修补镜像、imagePullSecrets 和 serviceAccountName(与 RayClusters 相同)。部署会与集群并行启动,不存在顺序依赖。

8. 监控运行

# Status
nrl-k8s status <recipe> --infra <infra>
kubectl get rayjob,raycluster -n default

# Follow the driver
nrl-k8s job list <recipe> --infra <infra> --role training
nrl-k8s job logs <run-id> <recipe> --infra <infra> --role training -f

如果 nrl-k8s job logs -f 子进程退出(kubectl port-forward 在空闲约 15 分钟后发生 i/o 超时),只需重新运行该命令。训练作业会继续运行。

若要通过 dashboard API 获取终止作业(SUCCEEDED/FAILED)或 RayJob 的驱动程序日志:

RC=$(kubectl get rayjob -n default <rayjob-name> -o jsonpath='{.status.rayClusterName}')
kubectl port-forward -n default svc/${RC}-head-svc 18266:8265 &
curl -s http://localhost:18266/api/jobs/                              # lists jobs, find submission_id
curl -s "http://localhost:18266/api/jobs/<submission_id>/logs"        # full driver log

type=DRIVER 且 submission_id=null 表示 exec-submitter 运行(dashboard 没有日志端点——请改用 nrl-k8s job logs)。type=SUBMISSION 表示已设置 submission_id,此时 /api/jobs/<id>/logs 可用。

Wandb URL 会在首次调用 wandb.init 时出现在驱动程序日志中;使用 grep -oE 'https://wandb\.ai/[A-Za-z0-9_./-]+' 搜索。

9. 停止任务

要停止的内容命令
一个训练运行nrl-k8s job stop <run-id> <recipe> --infra <infra> --role training
集群上所有正在运行的 Ray 作业(并提交新作业)nrl-k8s run <recipe> --infra <infra> --replace
长期运行的 RayClusternrl-k8s cluster down <recipe> --infra <infra> --target kuberay.training --wait
RayJob(临时)kubectl delete rayjob <name> -n default — 仅当 shutdownAfterJobFinishes 未生效时

删除共享 infra 前请先确认。对他人的集群执行 cluster down 代价很高。

10. 验证 RayJob 清理

使用 --shutdown(默认值)运行的 run --rayjob 完成后,KubeRay 应删除 RayCluster:

kubectl get rayjob   -n default <rayjob-name>                        # jobDeploymentStatus = Complete
kubectl get raycluster -n default | grep <rayjob-name>               # no output = torn down

RayJob 对象本身会保留 --ttl 秒(默认 3600 秒),以便你仍能获取日志。

11. 常见问题

  • OmegaConf 插值会处理配方/基础设施 YAML 中的 ${VAR}。使用 \${VAR} 转义 shell 变量,让 OmegaConf 将其原样传递给 pod shell。
  • Megatron 优化器配置不包含 foreach / fused。像 ~policy.optimizer.kwargs.foreach ~policy.optimizer.kwargs.fused 这样的覆盖(对 DTensor 配置有效)会导致 Megatron 配方出错。使用 Megatron 时请省略这些参数。
  • DTensor 与 Megatron——MoE 配方通常使用 megatron_cfg.enabled=true;请确保继承的默认配置中 dtensor_cfg.enabled=false。
  • 共享文件系统与 Git 版本不一致——codeSource: image|lustre 从 pod 文件系统读取代码。如果本地修改不在 pod 挂载的共享文件系统上,那么运行测试的是磁盘上的版本,而不是你的版本。可以通过辅助 pod 同步(通常会阻止执行 head pod 命令),或使用 Hydra 标志覆盖。
  • Ephemeral-storage 和 readinessProbe由 kuberay/CDI webhook 在应用 pod 时注入。请勿将它们添加到内联 RayCluster 规范中。
  • 节点污点因集群而异。在 worker 上设置 tolerations: [{operator: Exists}] 是一种稳妥的做法,建议保留。
  • Dashboard 空白页——Ray 2.52 默认将 dashboard 资源安装为符号链接;nrl-k8s cluster dashboard <name> 会自动重新安装 ray[default] --link-mode=copy 以修复此问题。也可以在镜像中设置 ENV UV_LINK_MODE=copy,从根本上避免此问题。
  • 自动化流程中通常会阻止 kubectl exec——可改用 kubectl get ... -o yaml、kubectl logs,以及 kubectl port-forward + Ray dashboard API。

12. 将运行标记为“完成”前的检查清单

报告启动成功之前,请确认:

  1. kubectl get rayjob/raycluster -n default 显示预期对象。
  2. nrl-k8s job list(或 curl /api/jobs/)显示任务处于 RUNNING / SUCCEEDED 状态。
  3. 驱动程序日志中包含 wandb.ai/<project>/runs/<id>(如果启用了 wandb)——请将 URL 分享给用户。
  4. 至少出现一行 Processed prompts: 100%(确认生成流程已正确接通)。
  5. 仅适用于 --rayjob 模式:在 jobDeploymentStatus=Complete 后,确认 kubectl get raycluster | grep <name> 无输出(表示已成功清理)。

13. 开发 pod

nrl-k8s dev 会在集群上管理一个轻量级 CPU pod,用于同步代码、调试,以及在集群内运行 kubectl / nrl-k8s。

# One-time: set up secrets (HF token, wandb, SSH key, rclone)
nrl-k8s dev setup-secrets --ssh-key ~/.ssh/id_rsa --add-rclone

# Create pod and exec in (idempotent — reuses existing pod)
nrl-k8s dev connect

# Switch image (must stop first — image change is warned but not auto-applied)
nrl-k8s dev stop
nrl-k8s dev connect --image nvcr.io/nvidian/nemo-rl:v0.7.0

# Tear down
nrl-k8s dev stop

开发 pod:

  • 在仅有 CPU 的节点上运行(与 GPU 节点设置反亲和性)
  • 将共享的 rl-workspace PVC 挂载到 /mnt/rl-workspace
  • 将 USER 环境变量设为 nrl-k8s 用户名(这样即使以 root 身份运行,$USER 和 getpass.getuser() 也能正常工作)
  • 首次启动时安装 kubectl、rclone(如果已配置)
  • 通过 envFrom 从按用户配置的 K8s Secret 注入 SSH 密钥和令牌

pod 的 default 服务账号需要在命名空间中绑定 edit RoleBinding,才能在其中使用 kubectl。dev connect 会检查这一设置;如果缺失,则会打印所需的 YAML。

14. 仓库中的文件位置

  • CLI 代码:infra/nrl_k8s/src/nrl_k8s/(cli.py、orchestrate.py、manifest.py、rayjob.py、k8s.py、submitters/、schema.py)。
  • 测试:infra/nrl_k8s/tests/unit/——在 infra/nrl_k8s/ 中运行 uv run --extra test pytest -x -q。
  • 配方和基础设施示例:infra/nrl_k8s/examples/。
  • 此工具封装的基础配方:examples/configs/recipes/llm/… 和 examples/nemo_gym/…。

评论

支持 Markdown