在 SkyPilot 上运行 verl 强化学习训练:Kubernetes 与多云 GPU 集群部署实战指南
在 SkyPilot 上运行 verl 强化学习训练Kubernetes 与多云 GPU 集群部署实战指南【免费下载链接】verlverl/HybridFlow: A Flexible and Efficient RL Post-Training Framework项目地址: https://gitcode.com/GitHub_Trending/ve/verlverlHybridFlow是一个灵活高效的 RL 后训练Post-Training框架。当训练规模超出单机、需要调度多节点 GPU 资源时verl 官方在examples/tutorial/skypilot/目录下提供了基于 SkyPilot 的分布式训练方案让你可以在 Kubernetes 集群或 AWS/GCP/Azure 等云平台上直接启动 PPO 与 GRPO 强化学习训练任务。读完本文你将掌握 SkyPilot 的安装配置、verl 官方 PPO/GRPO 启动配置task YAML的完整结构、Ray 分布式集群的自动拉起方式以及任务监控与回收的常用命令。一、为什么选择 SkyPilot 运行 verlverl 的分布式训练依赖 Ray 作为底层调度器从 verl/trainer/main_ppo.py 可以看到训练入口通过verl.trainer.main_ppo启动。在裸机上跑多节点训练需要手动配置 Ray head/worker、同步代码与数据集、打通 SSH 与端口运维成本高。SkyPilot 将这一过程抽象为声明式任务 YAML基础设施无关同一份配置可以指定infra: k8s、infra: aws、infra: gcp、infra: azureSkyPilot 负责在对应平台上申请带 GPU 的节点自动编排YAML 中的setup阶段自动克隆并安装 verl、下载数据集run阶段自动在多节点上启动 Ray 集群并执行训练命令任务生命周期管理一条sky launch命令即可创建集群并运行任务sky status/sky logs/sky down完成状态查看、日志追踪与资源回收。从当前仓库的 examples/tutorial/skypilot/verl-ppo.yaml 与 examples/tutorial/skypilot/verl-grpo.yaml 两份配置可以看出verl 官方的 SkyPilot 方案以共享镜像 节点内 Ray 自组织为设计核心所有节点使用同一 Docker 镜像run阶段依据 SkyPilot 注入的环境变量SKYPILOT_NODE_RANK、SKYPILOT_NODE_IPS、SKYPILOT_NUM_NODES自行区分 head 与 worker 角色无需额外编排工具。二、SkyPilot 安装与平台配置Step 1按目标平台安装 SkyPilot在任意一台具备云端凭据的机器如本地开发机或 CI 机器上执行根据你的目标平台选择对应的 extras# For Kubernetes only pip install skypilot[kubernetes] # For AWS pip install skypilot[aws] # For Google Cloud Platform pip install skypilot[gcp] # For Azure pip install skypilot[azure] # For multiple platforms pip install skypilot[kubernetes,aws,gcp,azure]说明只针对单一平台时安装对应 extras 即可避免拉入不需要的云 SDK 依赖同时使用多个平台例如 Kubernetes 做日常开发、AWS 做大规模扩展时推荐安装组合 extrasKubernetes 场景下SkyPilot 通过 kubeconfig 与目标集群交互需要保证执行sky launch的机器可以访问目标集群的 API Server。Step 2配置你的平台各平台的凭据与配置方式请参照 SkyPilot 官方安装文档https://docs.skypilot.co/en/latest/getting-started/installation.html核心要求是AWS配置好~/.aws/credentialsAccess Key / Secret Key或使用 IAM 角色GCP配置gcloud登录与应用默认凭据Azure配置az login凭据Kubernetes确保kubectl可用且当前 context 指向目标集群同时集群需有足够的 GPU 资源如 H100与持久化存储配额。Step 3设置环境变量verl 实验跟踪使用 Weights Biases模型可能来自 Hugging Face因此需要导出相应的密钥# For Weights Biases tracking export WANDB_API_KEYyour-wandb-api-key # For gated Hugging Face models (if needed) export HF_TOKENyour-huggingface-token这些环境变量会通过sky launch --secret传递到远端任务中详见下文Launch Command Options。三、官方示例在 GPU 集群上运行 PPO 与 GRPO所有命令均在仓库根目录下执行。两个官方示例的对应配置与参考实现如下任务配置文件算法数据集模型节点/加速卡PPOverl-ppo.yamlPPOalgorithm.adv_estimatorgaeGSM8KQwen2.5-0.5B-Instruct2 节点 × H100GRPOverl-grpo.yamlGRPOalgorithm.adv_estimatorgrpoMATHQwen2.5-7B-Instruct2 节点内存优化配置PPO 训练GSM8K Qwen2.5-0.5Bsky launch -c verl-ppo examples/tutorial/skypilot/verl-ppo.yaml \ --secret WANDB_API_KEY -y该任务基于 examples/ppo_trainer/ 目录下的官方示例改写使用 PPO 算法在 GSM8K 数据集上训练 Qwen2.5-0.5B-Instruct横跨 2 个节点、每个节点 1 张 H100。对应底层训练入口与 examples/ppo_trainer/README.md 中描述的 Actor-Critic GAE Clipped Surrogate Objective 结构一致需要同时加载 actor 与 critic 两份模型示例中均使用 Qwen2.5-0.5B-Instruct并通过algorithm.kl_ctrl.kl_coef0.001做 KL 散度约束防止策略偏离参考策略。GRPO 训练MATH Qwen2.5-7Bsky launch -c verl-grpo examples/tutorial/skypilot/verl-grpo.yaml \ --secret WANDB_API_KEY -y该任务基于 examples/grpo_trainer/ 目录下的示例改写使用 GRPOGroup Relative Policy Optimization通过algorithm.adv_estimatorgrpo切换在 MATH 数据集上训练 Qwen2.5-7B-Instruct采用针对 2 节点的内存优化配置FSDP 参数/优化器卸载、梯度检查点、chunked prefill 等详见下文配置逐项解析。GRPO 不需要 critic 模型因此该配置中没有critic.*参数组整体显存压力低于等规模的 PPO。Agent Loop 与工具调用训练需要特别说明的是SkyPilot 启动配置目前仅覆盖 PPO 与 GRPO。对于 Agent Loop智能体循环与工具调用Tool-Use训练官方建议先使用 examples/tutorial/agent_loop_get_started/agent_loop_tutorial.ipynb 教程在本地验证模型、工具与沙箱sandbox配置的正确性再自行适配为集群任务。当前仓库尚未为这类工作流提供预置的 SkyPilot 任务配置需要你根据该 notebook 的验证结果自行编写任务 YAML。四、任务配置逐项解析verl-ppo.yaml / verl-grpo.yaml两份 YAML 结构相同这里以 verl-ppo.yaml 为主线逐段拆解。4.1 resources基础设施与算力声明resources: infra: k8s accelerators: H100:1 memory: 128 image_id: docker:verlai/verl:base-verl0.5-cu126-cudnn9.8-torch2.7.0-fa2.7.4 ports: 8265字段含义可选项/说明infra目标基础设施k8s默认、aws、gcp、azure等按你的平台修改accelerators每节点加速卡规格H100:1表示每个节点 1 张 H100可改为A100:8、H100:8等memory每节点内存下限128表示至少 128GBSkyPilot 会据此选择实例规格image_id节点使用的 Docker 镜像verl 官方镜像CUDA 12.6 cuDNN 9.8 PyTorch 2.7.0 FlashAttention 2.7.4对应 verl 0.5 基线ports需要暴露的端口8265为 Ray Dashboard 端口用于训练过程可视化4.2 节点数与密钥num_nodes: 2 secrets: WANDB_API_KEY:num_nodes: 2申请 2 个 GPU 节点组成训练集群secrets声明任务运行时需要的密钥--secret WANDB_API_KEY会把本地环境变量注入远端任务。如需使用 Hugging Face 上的 gated 模型需要授权把HF_TOKEN加入secrets段并追加--secret HF_TOKEN即可。4.3 setup环境准备克隆代码、安装 verl、下载数据集setup: | rm -rf verl git clone https://github.com/verl-project/verl.git cd verl pip3 install -v -e .[vllm] pip3 install flashinfer-python # Download GSM8K dataset - alternative approach echo Downloading GSM8K dataset... mkdir -p ~/data/gsm8k # Check if the script exists and use absolute path if [ -f $(pwd)/examples/data_preprocess/gsm8k.py ]; then python3 $(pwd)/examples/data_preprocess/gsm8k.py --local_dir ~/data/gsm8k else echo Warning: gsm8k.py script not found, skipping dataset download # You might want to download the dataset manually or use a different approach fi echo GSM8K dataset download completedsetup阶段在每个节点上执行SkyPilot 会保证所有节点并行完成环境准备后再进入run。关键动作从源码安装 verlgit clonepip3 install -e .[vllm]可编辑安装附带 vLLM 推理后端依赖。注意这里克隆的是上游 verl 仓库在实际使用中你可以将 URL 替换为内部镜像地址以保证网络可达与代码版本可控安装 flashinfervLLM rollout 的注意力加速依赖下载数据集调用仓库中的 examples/data_preprocess/gsm8k.py 生成 parquet 格式数据集。该脚本从 Hugging Face 加载openai/gsm8k为每条样本拼接指令提示词Lets think step by step and output the final answer after ####.抽取####后的最终答案作为reward_model.ground_truth并输出train.parquet/test.parquet到--local_dir指定的目录。PPO 示例用了带存在性检查的写法GRPO 示例verl-grpo.yaml则直接调用 examples/data_preprocess/math_dataset.py 从DigitalLearningGmbH/MATH-lighteval加载 MATH 数据集同样产出train.parquet/test.parquet附带train_example.json/test_example.json便于人工检查数据格式。4.4 runRay 集群自组织与训练启动run阶段是任务的核心其设计模式是按节点角色分叉HEAD_IP$(echo $SKYPILOT_NODE_IPS | head -n1) NUM_NODES$SKYPILOT_NUM_NODES if [ $SKYPILOT_NODE_RANK 0 ]; then # Head node starts Ray Head echo Starting Ray head node... ps aux | grep ray | grep 6379 /dev/null || ray start --head --disable-usage-stats \ --port6379 \ --dashboard-host0.0.0.0 \ --dashboard-port8265 # Wait for all worker nodes to join the cluster retry_count0 max_retries30 while [ $retry_count -lt $max_retries ]; do connected_nodes$(ray status 2/dev/null | grep -c node_ || echo 0) echo Connected nodes: $connected_nodes/$NUM_NODES (attempt $((retry_count1))/$max_retries) if [ $connected_nodes -ge $NUM_NODES ]; then echo All nodes connected to Ray cluster break fi retry_count$((retry_count1)) sleep 10 done python3 -m verl.trainer.main_ppo PPO 参数 else # Wait for Ray Head to start sleep 15 # Worker node starts Ray Worker echo Starting Ray worker node... ps aux | grep ray | grep $HEAD_IP:6379 /dev/null || ray start --address $HEAD_IP:6379 --disable-usage-stats sleep 10 fi这里的核心是 SkyPilot 自动注入的 4 个环境变量从源码结构看这是 SkyPilot 的约定接口两份配置均直接使用环境变量含义用法SKYPILOT_NODE_RANK当前节点序号0 为 head判断启动 Ray head 还是 workerSKYPILOT_NODE_IPS所有节点 IP 列表换行分隔head -n1取首个 IP 作为 Ray head 地址SKYPILOT_NUM_NODES节点总数用于等待所有节点加入 Ray 集群SKYPILOT_NUM_GPUS_PER_NODE每节点 GPU 数GRPO 配置使用传递给trainer.n_gpus_per_node启动逻辑要点head 节点rank 0先ray start --head启动 Ray 主节点dashboard 端口 8265与resources.ports对应然后以最多 30 次 × 10 秒的轮询等待所有节点加入通过ray status中node_行数判断全部就绪后再启动verl.trainer.main_ppo训练worker 节点rank ! 0等待 15 秒确保 head 先启动然后ray start --address $HEAD_IP:6379加入集群ps aux | grep ray | grep ...的幂等判断保证脚本在节点重启后不会重复启动 Ray 进程。4.5 PPO 训练参数解析PPO 配置对应 verl/trainer/main_ppo.py 的 Hydra 参数体系核心参数如下python3 -m verl.trainer.main_ppo \ data.train_files$HOME/data/gsm8k/train.parquet \ data.val_files$HOME/data/gsm8k/test.parquet \ data.train_batch_size256 \ data.max_prompt_length512 \ data.max_response_length256 \ actor_rollout_ref.model.pathQwen/Qwen2.5-0.5B-Instruct \ actor_rollout_ref.actor.optim.lr1e-6 \ actor_rollout_ref.actor.ppo_mini_batch_size64 \ actor_rollout_ref.actor.ppo_micro_batch_size_per_gpu4 \ actor_rollout_ref.rollout.log_prob_micro_batch_size_per_gpu8 \ actor_rollout_ref.rollout.tensor_model_parallel_size1 \ actor_rollout_ref.rollout.namevllm \ actor_rollout_ref.rollout.gpu_memory_utilization0.4 \ actor_rollout_ref.ref.log_prob_micro_batch_size_per_gpu4 \ critic.optim.lr1e-5 \ critic.model.pathQwen/Qwen2.5-0.5B-Instruct \ critic.ppo_micro_batch_size_per_gpu4 \ algorithm.kl_ctrl.kl_coef0.001 \ trainer.logger[console,wandb] \ trainer.val_before_trainFalse \ trainer.default_hdfs_dirnull \ trainer.n_gpus_per_node1 \ trainer.nnodes2 \ trainer.save_freq20 \ trainer.test_freq20 \ trainer.total_epochs2 \ trainer.project_nameverl_examples \ trainer.experiment_nameexperiment_name_gsm8k参数组参数含义备注datatrain_batch_size256全局 prompt 批大小一次采样生成的轨迹数为train_batch_size × rollout.nn1时即 256 条轨迹datamax_prompt_length512/max_response_length256prompt / 生成序列的最大 token 数超长样本会被过滤或截断actor_rollout_ref.modelpathQwen/Qwen2.5-0.5B-Instructactor策略模型与 critic 共用同一模型作为初始化actor_rollout_ref.actoroptim.lr1e-6actor 学习率PPO 中通常远小于预训练 lractor_rollout_ref.actorppo_mini_batch_size64每条采样轨迹集切分的 PPO 更新 mini-batch全局影响更新步数与稳定性actor_rollout_ref.actorppo_micro_batch_size_per_gpu4单次前向/反向的最大样本数用于规避 GPU OOM不改变算法收敛行为actor_rollout_ref.rolloutnamevllmrollout 推理后端可切换sglang、trtllm等actor_rollout_ref.rollouttensor_model_parallel_size1rollout 张量并行度0.5B 模型单卡即可actor_rollout_ref.rolloutgpu_memory_utilization0.4vLLM 引擎允许使用的显存比例需为 actor/critic 训练预留显存故取 0.4criticmodel.path/optim.lr1e-5critic价值模型及其学习率PPO 特有组件GRPO 无此参数组algorithm.kl_ctrlkl_coef0.001奖励中 KL 惩罚系数初始值控制策略与参考策略的偏离程度trainerlogger[console,wandb]日志输出到控制台与 WB需配合--secret WANDB_API_KEYtrainern_gpus_per_node1/nnodes2每个训练节点的 GPU 数与节点数与 SkyPilot 资源配置一致trainersave_freq20/test_freq20每 20 步保存 checkpoint 与评估trainertotal_epochs2数据遍历轮数小模型快速验证配置trainerproject_name/experiment_nameWB 项目与实验名便于多实验对比这些参数的语义与 examples/ppo_trainer/README.md 的说明一致所有含micro_batch_size的配置只影响每次前向/反向的最大样本数防止 OOM不应改变算法收敛行为ppo_mini_batch_size是跨所有 worker 的全局量。官方参考性能verl v0.2 基线显示同一 Qwen2.5-0.5B-Instruct 在 GSM8K 上从预训练模型的 36.4 分经 PPO 后可提升至 56.7 分可作为结果正确性的参考区间具体数值会随版本与配置浮动。4.6 GRPO 训练参数解析内存优化要点GRPO 配置verl-grpo.yaml针对 7B 模型做了系统性内存优化与 PPO 配置的关键差异python3 -m verl.trainer.main_ppo \ algorithm.adv_estimatorgrpo \ data.train_files$HOME/data/math/train.parquet \ data.val_files$HOME/data/math/test.parquet \ data.train_batch_size32 \ data.max_prompt_length256 \ data.max_response_length256 \ data.filter_overlong_promptsTrue \ data.truncationerror \ actor_rollout_ref.model.pathQwen/Qwen2.5-7B-Instruct \ actor_rollout_ref.actor.optim.lr1e-6 \ actor_rollout_ref.model.use_remove_paddingTrue \ actor_rollout_ref.actor.ppo_mini_batch_size16 \ actor_rollout_ref.actor.ppo_micro_batch_size_per_gpu4 \ actor_rollout_ref.actor.ppo_epochs1 \ actor_rollout_ref.actor.use_kl_lossFalse \ actor_rollout_ref.actor.entropy_coeff0 \ actor_rollout_ref.model.enable_gradient_checkpointingTrue \ actor_rollout_ref.actor.fsdp_config.param_offloadTrue \ actor_rollout_ref.actor.fsdp_config.optimizer_offloadTrue \ actor_rollout_ref.rollout.log_prob_micro_batch_size_per_gpu16 \ actor_rollout_ref.rollout.tensor_model_parallel_size1 \ actor_rollout_ref.rollout.namevllm \ actor_rollout_ref.rollout.gpu_memory_utilization0.4 \ actor_rollout_ref.rollout.n1 \ actor_rollout_ref.rollout.enable_chunked_prefillTrue \ actor_rollout_ref.rollout.max_num_batched_tokens2048 \ actor_rollout_ref.ref.log_prob_micro_batch_size_per_gpu16 \ actor_rollout_ref.ref.fsdp_config.param_offloadTrue \ algorithm.use_kl_in_rewardFalse \ trainer.critic_warmup0 \ trainer.logger[console,wandb] \ trainer.project_nameverl_math_grpo_demo \ trainer.experiment_nameqwen25_7b_grpo \ trainer.n_gpus_per_node$NUM_GPUS_PER_NODE \ trainer.nnodes$NUM_NODES \ trainer.save_freq-1 \ trainer.test_freq-1 \ trainer.total_epochs1与 PPO 配置的核心差异及其动机差异点PPOGRPO动机优势估计器默认gaeverl/trainer/config/ppo_trainer.yaml 中adv_estimator: gaealgorithm.adv_estimatorgrpoGRPO 用组内相对奖励估计优势无需 critic 模型显著省显存critic完整critic.*参数组无 critic仅保留trainer.critic_warmup0GRPO 是无 critic算法与 examples/ppo_trainer/README.md 中 GRPO 不需要 critic 的说明一致FSDP 卸载默认不卸载param_offloadTrueoptimizer_offloadTrueactor 与 ref 均开启7B 模型参数/优化器状态卸载到 CPU 内存换取 GPU 显存梯度默认enable_gradient_checkpointingTrue以少量计算换显存推理默认rollout.enable_chunked_prefillTruemax_num_batched_tokens2048分块 prefill 平滑长 prompt 的显存尖峰序列填充默认model.use_remove_paddingTrue去掉 padding 减少无效计算与显存KL 控制kl_ctrl.kl_coef0.001奖励内惩罚use_kl_lossFalseuse_kl_in_rewardFalse、entropy_coeff0该示例完全关闭 KL 与熵正则关注纯 RL 信号保存/评估save_freq20/test_freq20save_freq-1/test_freq-1演示任务关闭周期性保存与评估按需调整动态节点数硬编码n_gpus_per_node1、nnodes2$NUM_GPUS_PER_NODE/$NUM_NODES由 SkyPilot 自动注入节点/GPU 规模变化无需改脚本值得注意的是 GRPO 示例还设置了data.filter_overlong_promptsTrue与data.truncationerror即超长 prompt 直接报错而不是静默截断这避免了截断导致的奖励信号错位与 examples/grpo_trainer/run_qwen3_8b_fsdp.sh 等官方规范脚本的做法一致该脚本同样使用algorithm.adv_estimatorgrpo、algorithm.use_kl_in_rewardFalse、data.truncationerror并支持 FSDP 参数卸载等内存优化开关。五、Launch Command Options启动命令选项选项含义示例-c name集群名用于后续管理该任务日志、SSH、销毁-c verl-ppo--secret KEY传递密钥可多次使用密钥值来自本地同名环境变量--secret WANDB_API_KEY --secret HF_TOKEN-y跳过确认提示便于脚本化/CI 使用追加在命令末尾使用 gated Hugging Face 模型时完整的启动命令形如sky launch -c verl-grpo examples/tutorial/skypilot/verl-grpo.yaml \ --secret WANDB_API_KEY --secret HF_TOKEN -y六、监控你的训练任务SkyPilot 为运行中的集群提供了一套完整的生命周期管理命令# 查看集群状态列出所有集群及其运行状态 sky status # 查看指定任务的日志实时流式输出训练日志 sky logs verl-ppo # 查看 PPO 任务的日志 # SSH 登录 head 节点手动排查环境问题 ssh verl-ppo # 获取 Ray Dashboard 访问地址8265 端口已通过 resources.ports 暴露 sky status --endpoint 8265 verl-ppo # 训练结束后回收集群资源销毁节点避免持续计费 sky down verl-ppo实践建议训练过程中用sky logs verl-ppo观察 WB 与 console 输出确认data.train_batch_size的采样、PPO/GRPO 更新循环是否正常推进用sky status --endpoint 8265 verl-ppo获取 Ray Dashboard URL在浏览器中查看各节点的 GPU 利用率、任务调度与对象存储状态任务异常时先ssh verl-ppo进入 head 节点执行ray status与ray summary检查节点连通性与资源占用训练完成或确认失败后务必sky down cluster释放 GPU 资源避免云平台持续计费。七、扩展与适配指南更换模型与数据集修改actor_rollout_ref.model.path与critic.model.path、data.train_files/data.val_files并在setup中更换对应的数据预处理脚本仓库 examples/data_preprocess/ 下已有 GSM8K、MATH、OpenR1、Geo3K、AIME 等多套预处理实现更换推理后端将actor_rollout_ref.rollout.name从vllm改为sglang等并相应调整pip3 install -e .[vllm]为对应的 extras需确保 Docker 镜像中包含对应后端依赖扩大规模修改num_nodes与accelerators如H100:8同时同步trainer.nnodes/trainer.n_gpus_per_nodeGRPO 配置已自动使用$SKYPILOT_NUM_NODES/$SKYPILOT_NUM_GPUS_PER_NODE无需手动改切换云平台将infra: k8s改为infra: aws/infra: gcp/infra: azure并确保本地已配置对应平台凭据多节点 GPU 数量一致性SkyPilot 会按accelerators规格为每个节点分配相同数量的 GPU保证 Ray 集群的 GPU 拓扑均匀这是 verl 多节点训练正确性的前提。八、小结通过 SkyPilotverl 的 PPO 与 GRPO 训练任务被封装为一份可移植的声明式 YAMLresources声明算力与镜像setup完成代码安装与数据准备run借助SKYPILOT_*环境变量在节点间自组织 Ray 集群并启动verl.trainer.main_ppo。这套方案让开发者可以聚焦于训练参数本身而把节点申请、环境同步、Ray 编排等繁琐的集群运维交给 SkyPilot 处理。对于需要 Agent Loop / 工具调用的训练场景官方建议先通过 Agent Loop 教程 在本地验证配置再参照 PPO/GRPO 配置的模式自行编写 SkyPilot 任务。【免费下载链接】verlverl/HybridFlow: A Flexible and Efficient RL Post-Training Framework项目地址: https://gitcode.com/GitHub_Trending/ve/verl创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考