在ACK上使用VeRL框架进行Agentic强化学习训练

更新时间:
复制为 MD 格式

本文介绍如何在容器服务 Kubernetes 版ACK)集群中,基于 VeRL 框架和 Harbor-framework 沙箱完成 Agentic RL 端到端训练,包括部署 RayCluster、准备 SWE-bench 数据集、配置训练参数等。

背景信息

什么是 Agentic RL

Agentic RL 通过强化学习训练自主智能体,使其在多轮交互中完成复杂任务。相比传统 RLHF,Agentic RL 的交互轨迹更长、动作空间更复杂、奖励信号更稀疏。

维度

传统 RLHF

Agentic RL

交互模式

单轮生成

多轮交互(思考、行动、观察)

动作粒度

Token 级别

分层动作(思考、工具调用、响应)

轨迹长度

短(单次响应)

长(多轮对话,10~100 轮)

奖励密度

稠密(每轮打分)

稀疏(任务结束时反馈)

环境复杂度

文本输入输出

沙箱、数据库、外部系统

典型应用

对话质量优化

代码修复、数据分析、自动化任务

准备工作

  • 已创建包含 GPU 节点的 ACK Pro 集群。具体操作,请参见为集群添加GPU节点

    • GPU 节点规格要求:本方案的训练镜像基于 CUDA 11.8+ 编译,仅支持 Compute Capability 8.0 及以上的 GPU 架构。本方案配置以下实例规格:

      实例规格族

      GPU 型号

      GPU 显存

      Compute Capability

      ecs.gn7i(推荐)

      NVIDIA A10

      24 GB

      8.6

      ecs.gn7e

      NVIDIA A100

      80 GB

      8.0

      ecs.ebmgn7

      NVIDIA A100

      80 GB

      8.0

      本方案以单节点 8 卡 GPU 为例。可根据准备的训练数据调整合适的资源。

    • 不兼容的实例规格:ecs.gn5(P100, Compute Capability 6.0)、ecs.gn6v/ecs.gn6e(V100, Compute Capability 7.0)等旧架构 GPU 实例不支持本方案的训练镜像,启动训练时会报错 CUDA error: no kernel image is available for execution on the device

  • 已安装 KubeRay Operator

  • 集群 Pod 已具备公网访问能力。训练过程中需要从 GitHub 下载代码仓库来构建 SWE-bench 沙箱镜像,请确认 VPC 已配置 NAT 网关并添加 SNAT 规则。具体操作,请参见配置 SNAT 实现访问公网

    重要

    地域选择建议:中国内地地域(如杭州、上海、北京)可能无法访问 GitHub 和 HuggingFace,导致数据集下载失败或镜像构建超时。建议在中国香港或海外地域创建集群。

  • GPU 节点的系统内存(RAM)不低于 60 GiB(即 RayCluster Pod 的 memory requests 不低于 55 Gi)。Qwen2.5-7B 启用 FSDP 参数和优化器 offload 后,模型权重会从 GPU 显存卸载到系统内存,实测约需 20~25 GiB RAM。

方案概述

整体架构

本方案涉及以下核心组件:

  • VeRL:开源 LLM 强化学习训练框架,支持多轮对话、工具使用等场景的 RL 训练。

  • SWE-bench:评估 AI 系统解决真实 GitHub Issue 能力的基准测试。AI 系统需阅读 Issue 描述、生成代码修复(Patch),并通过项目测试套件验证。

  • Harbor-framework:提供沙箱执行环境和 Agent 编排能力的框架,支持在 Kubernetes 中创建隔离的执行环境。

VeRL 内置的 AgentLoop(如 SingleTurnAgentLoop、ToolAgentLoop)不支持分布式运行、Token 级数据捕获、第三方 Agent 集成和沙箱隔离。本方案通过 RemoteAgentLoop + Harbor-framework 解决上述问题:

  • 隔离执行:Agent 在沙箱中运行,避免污染训练环境,支持执行不受信任的代码。

  • Token 级追踪:ProxyServer 捕获所有 LLM 调用的 token_ids 和 logprobs,提供 RL 训练所需的完整数据。

  • 大规模并行:支持在 K8s 集群中同时运行数千个 trial,加速训练收敛。

整体架构如下图所示:系统包含 VeRL Ray 集群(含 RemoteAgentLoop、vLLM Rollout 推理服务和 ProxyServerActor)和 Agent 执行环境(Harbor-framework 沙箱)两部分。

image

系统支持两种运行模式,本案例只涉及本地模式:将 REMOTE_AGENT_USE_LOCAL_TRIAL 设为 true。RemoteAgentLoop 直接在 K8s 集群中创建 Sandbox Pod 并运行 Agent,无需额外的 Harbor Server。适用于单集群训练场景。

Agent 发出的 LLM 请求通过 ProxyServer 转发至 vLLM 推理服务。ProxyServer 同时透明记录 Token 级数据(token_ids、logprobs)供 RL 训练使用。

训练流水线

端到端的 Agentic RL 训练共分为五个阶段:

image
  1. 数据准备:加载 SWE-bench Verified 数据集(500 个 Issue),按 400/100 划分训练集和验证集。

  2. Rollout 采样:RemoteAgentLoop 将任务提交到 Harbor-framework 沙箱。SWE-agent 在隔离环境中读取 Issue、生成 Patch、运行测试。ProxyServer 同步记录所有 LLM 调用的 completion_token_idscompletion_logprobs

  3. 奖励计算:基于任务执行结果计算奖励信号:测试通过奖励 +1.0,测试失败奖励 0.0。可选附加奖励:Patch 行数少(+0.1)、测试通过速度快(+0.05)。

  4. PPO/GRPO 策略更新:使用 GRPO 算法(组内相对策略优化)进行策略更新,计算 Advantage 和 PPO Clip Loss,执行反向传播更新模型参数。

  5. 评估与迭代:每 100 步在验证集上评估 Issue 解决率,保存模型 Checkpoint,持续迭代直至收敛。

操作步骤

步骤一:准备模型和数据集 PVC

为模型文件和数据集分别创建持久化存储卷(PVC)。本文后续步骤默认使用 verl-models(挂载到 /var/model)和 verl-dataset(挂载到 /var/model-dataset),请按实际情况替换。

  1. 选择 PVC 存储类型。

    根据使用场景选择 OSS 存储卷或云盘存储卷:

    存储类型

    适用场景

    注意事项

    OSS 存储卷

    多可用区集群或多节点共享读取

    不受可用区和云盘类型限制

    云盘存储卷

    单节点高性能读写

    • 须与 GPU 节点在同一可用区,否则无法挂载。

    • 受 ECS 实例类型支持的云盘类型限制。例如,ecs.gn5 系列不支持 ESSD 云盘(cloud_essd),仅支持 SSD 云盘(cloud_ssd)和高效云盘(cloud_efficiency)。请在实例规格族页面确认您的 GPU 实例类型支持的云盘类型。

  2. 规划 PVC 容量。

    • 模型 PVC:建议预留 50 GiB 以上(Qwen2.5-7B 约需 15 GiB)。

    • 数据集 PVC:建议预留 100 GiB 以上。

  3. 创建 verl-modelsverl-dataset 两个 PVC。

    根据选择的存储类型,参考以下文档创建 PVC:

  4. 验证 PVC 已就绪。

    kubectl get pvc verl-models verl-dataset

    预期输出中 STATUS 列均为 Bound 表示 PVC 创建成功,可继续下一步。

    NAME           STATUS   VOLUME                                     CAPACITY   ACCESS MODES   AGE
    verl-models    Bound    pvc-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx   50Gi       RWX            1m
    verl-dataset   Bound    pvc-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx   100Gi      RWX            1m

步骤二:部署 RayCluster

在 ACK 集群中创建包含 VeRL 框架的 Ray 集群。

  1. 获取集群KubeConfig并通过kubectl工具连接集群或在 ACK 控制台上点击通过 Workbench 管理集群

  2. 创建rbac.yaml文件。

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: rayclustertest
      namespace: default
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: rayclustertest
      namespace: default
    rules:
    - apiGroups: [""]
      resources: ["pods"]
      verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
    - apiGroups: ["batch"]
      resources: ["jobs"]
      verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
    - apiGroups: ["apps.kruise.io"]
      resources: ["sandboxes", "sandboxsets", "sandboxclaims"]
      verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: rayclustertest
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: rayclustertest
    subjects:
      - kind: ServiceAccount
        name: rayclustertest
        namespace: default
  3. 执行以下命令应用配置。

    kubectl apply -f rbac.yaml
  4. 创建raycluster.yaml文件。

    apiVersion: ray.io/v1
    kind: RayCluster
    metadata:
      name: raycluster-verl
      namespace: default
    spec:
      headGroupSpec:
        rayStartParams:
          dashboard-host: 0.0.0.0
        serviceType: ClusterIP
        template:
          spec:
            serviceAccountName: rayclustertest
            imagePullSecrets:
            - name: acr-registry
            containers:
            - name: ray-head
              image: <替换成您的verl镜像>
              imagePullPolicy: IfNotPresent
              env:
              - name: RAY_GRAFANA_HOST
                value: DISABLED
              resources:
                limits:
                  cpu: "50"
                  memory: 200Gi
                  nvidia.com/gpu: "8"
                requests:
                  cpu: "50"
                  memory: 200Gi
                  nvidia.com/gpu: "8"
              securityContext:
                runAsUser: 0
              # 将/var/model和/var/model-dataset替换为实际路径
              volumeMounts:
              - mountPath: /var/model
                name: model
              - mountPath: /var/model-dataset
                name: model-dataset
            # 将verl-modelsverl-dataset替换为实际PVC名称
            volumes:
            - name: model
              persistentVolumeClaim:
                claimName: verl-models
            - name: model-dataset
              persistentVolumeClaim:
                claimName: verl-dataset

    根据实际环境修改以下参数:

    • image:VeRL 训练镜像地址。您可以基于 VeRL 开源仓库 自行构建镜像,或使用团队提供的预构建镜像。镜像地址中的区域标识(如 ap-southeast-1)需与集群所在区域一致。如需自行构建镜像,可参考以下 Dockerfile:

      FROM verlai/verl:vllm017.latest
      
      WORKDIR /home/verl
      ENV PYTHONPATH="/home/verl:$PYTHONPATH"
      
      COPY . .
      
      RUN git clone https://github.com/alibaba/harbor.git
      RUN git clone https://github.com/alibaba/verl-recipe.git
      
      ENV VERSION=v0.20.2
      RUN curl -L "https://github.com/google/go-containerregistry/releases/download/${VERSION}/go-containerregistry_Linux_x86_64.tar.gz" -o crane.tar.gz \
          && tar -xzf crane.tar.gz && mv crane /usr/local/bin/
      
      ENV BUILDKIT_VERSION=v0.13.2
      RUN curl -sL "https://github.com/moby/buildkit/releases/download/${BUILDKIT_VERSION}/buildkit-${BUILDKIT_VERSION}.linux-amd64.tar.gz" \
          | tar -xz -C /usr/local bin/buildctl
      
      RUN pip install kubernetes oauthlib
      RUN pip install -e /home/verl/harbor
      
      RUN apt update && apt install -y openssh-server vim
      RUN apt remove python3-blinker -y; pip install -U "ray[data,train,tune,serve]"; pip install -e .
    • imagePullSecrets:如使用私有镜像仓库,需提前创建包含仓库凭证的 Secret,并替换 acr-registry 为实际的 Secret 名称。创建 Secret 示例:kubectl create secret docker-registry acr-registry --docker-server=<仓库地址> --docker-username=<用户名> --docker-password=<密码>。如使用公开镜像,可删除 imagePullSecrets 配置。

    • claimName:模型和数据集的 PVC 名称,替换为您实际创建的 PVC 名称。模型 PVC 挂载到 /var/model,数据集 PVC 挂载到 /var/model-dataset,后续步骤中的路径均基于此挂载配置。

    • resources:根据 GPU 节点的实际规格调整 CPU、内存和 GPU 数量。本示例使用 8 卡 GPU 节点的配置,如果您的节点 GPU 数量不同,请参见下方的资源适配说明。

    如果您的 GPU 节点规格与示例不同(例如单节点仅有 1~2 张 GPU),除了调整 RayCluster 的 resources 配置外,还需要同步调整步骤四中的以下训练参数:

    • trainer.n_gpus_per_node:修改为实际每节点 GPU 数量。

    • actor_rollout_ref.rollout.tensor_model_parallel_size:不能超过 GPU 数量,单卡环境设为 1。

    • actor_rollout_ref.actor.ulysses_sequence_parallel_size:不能超过 GPU 数量,单卡环境设为 1。

    • actor_rollout_ref.rollout.gpu_memory_utilization:GPU 数量较少时适当降低此值(如 0.4~0.6),避免显存不足。

    • actor_rollout_ref.rollout.ndata.max_prompt_lengthdata.max_response_length:GPU 资源较少时适当降低,以减少显存占用。

  5. 执行以下命令应用配置。

    kubectl apply -f raycluster.yaml
  6. 验证 RayCluster 部署状态。

    kubectl get rayclusters

    预期输出如下,STATUSready 表示部署成功。

    NAME              DESIRED WORKERS   AVAILABLE WORKERS   CPUS   MEMORY   GPUS   STATUS   AGE
    raycluster-verl                                         50     200Gi    8      ready    44s
  7. 确认 Ray Head Pod 已就绪。

    kubectl get pods -l ray.io/node-type=head

    预期 STATUSRunning。Pod 长时间停留在 ContainerCreating 时,请执行 kubectl describe pod <pod-name> 查看事件详情。常见原因包括 PVC 挂载失败或镜像拉取失败,请参见常见问题

步骤三:准备数据集

使用 Harbor-framework 下载 SWE-bench 数据集。以下命令均在 Ray Head Pod 内执行。

  1. 进入 Ray Head Pod。

    kubectl exec -it $(kubectl get pods -l ray.io/node-type=head -o name) -- bash
  2. 安装依赖并下载数据集。

    harbor datasets download swebench-verified --export
  3. 验证数据集完整性。

    ls swebench-verified/ | wc -l

    预期输出为 500(SWE-bench Verified 数据集的 Issue 总数)。数量不足时,请重新执行上一步的下载命令。

  4. 通过 ModelScope 下载基础模型。本示例使用 Qwen2.5-7B-Instruct(约 15 GiB)。替换/var/model/Qwen2.5-7B-Instruct为实际PVC verl-models的挂载目录。

    pip install modelscope
    modelscope download --model Qwen/Qwen2.5-7B-Instruct --local_dir /var/model/Qwen2.5-7B-Instruct

    下载完成后验证模型文件。

    ls /var/model/Qwen2.5-7B-Instruct/config.json && echo "Model downloaded successfully"
    说明

    下载时间取决于网络环境,通常 10~30 分钟。使用其他模型时,请替换模型名称和路径,并同步修改训练命令中的 actor_rollout_ref.model.path 参数。

关于自定义数据集的构建方法,请参见 Harbor-framework 数据集构建文档

步骤四:部署 BuildKit 服务(可选)

SWE-bench 训练需为每个 Instance 构建独立的 Docker 镜像。训练代码会自动检查 {registry}/swe-bench/{instance_id}:latest 是否存在:

  • 如果镜像已存在,直接使用。

  • 如果镜像不存在,系统使用指定的 BuildKit 地址自动构建并推送镜像。

在集群中自建 BuildKit 服务可保证镜像构建的稳定性和速度。部署方式如下:

  1. 创建 buildkit.yaml 文件。

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: buildkitd
      namespace: default
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: buildkitd
      template:
        metadata:
          labels:
            app: buildkitd
        spec:
          containers:
          - name: buildkitd
            image: moby/buildkit:latest
            args:
            - --addr
            - tcp://0.0.0.0:1234
            securityContext:
              privileged: true
            ports:
            - containerPort: 1234
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: buildkitd
      namespace: default
    spec:
      selector:
        app: buildkitd
      ports:
      - port: 1234
        targetPort: 1234
  2. 执行以下命令应用配置。

    kubectl apply -f buildkit.yaml
  3. 验证 BuildKit 服务状态。

    kubectl get pods -l app=buildkitd

    预期输出中 Pod 状态为 Running

  4. 验证 BuildKit 服务端口可达。

    kubectl run buildkit-test --rm -it --restart=Never --image=busybox -- nc -zv buildkitd 1234

    预期输出包含 opensucceeded,表示端口连通正常。连接失败时,请检查 Service 配置及 Pod 运行状态。

步骤五:配置并启动训练

本步骤通过 RemoteAgentLoop 启动训练。RemoteAgentLoop 提供统一的 AgentLoop 接口,兼容多种 Agent,无需修改 Agent 源码即可接入 RL 训练流程。

  1. 进入 Ray Head Pod。

    kubectl exec -it $(kubectl get pods -l ray.io/node-type=head -o name) -- bash
  2. 修改训练脚本 recipe/agentic/agentic-qwen2.5-7b.sh 中的关键参数。

    • actor_rollout_ref.model.path:替换为您的模型在 PVC 中的实际路径。

    • trainer.n_gpus_per_node:替换为实际每节点 GPU 数量(如单卡设为 1)。

    • actor_rollout_ref.rollout.tensor_model_parallel_size:不能超过 GPU 数量,单卡环境设为 1。

    • actor_rollout_ref.actor.ulysses_sequence_parallel_size:不能超过 GPU 数量,单卡环境设为 1。

    • actor_rollout_ref.rollout.gpu_memory_utilization:GPU 数量较少时降低至 0.4~0.6,避免显存不足。

    • actor_rollout_ref.rollout.n:SandboxSet 的 REPLICAS 数量等于训练脚本中 actor_rollout_ref.rollout.n 的取值。例如设置为 4 时,每个 Issue 并行运行 4 条采样轨迹。GPU 资源较少时降低此值(如设为 1)。

    • actor_rollout_ref.actor.ppo_max_token_len_per_gpuactor_rollout_ref.ref.log_prob_max_token_len_per_gpu:GPU 显存不足时降低此值。

    • trainer.default_local_dir:模型 Checkpoint 保存路径,确保有足够的磁盘空间。

    更多参数说明,请参见Agentic Recipe

  3. 启动训练。

    bash recipe/agentic/agentic-qwen2.5-7b.sh
  4. 训练启动后,在另一个终端中执行以下命令快速检查训练状态。

    kubectl logs $(kubectl get pods -l ray.io/node-type=head -o name) --tail=20

    训练正常启动时,日志会出现模型加载和数据集加载信息。出现报错时,请参见常见问题排查。更多验证方式(Sandbox 状态、Ray Dashboard、训练日志监控)请参见结果验证

结果验证

训练启动后,通过以下方式验证训练是否正常运行。

查看 Sandbox 资源状态

系统自动为每个 SWE-bench Instance 创建 SandboxSet 和 Sandbox 资源。

kubectl get sandboxsets

预期输出:

NAME                    REPLICAS   AVAILABLE   AGE
astropy-astropy-12907   1          1           54s
astropy-astropy-13033   1          1           53s
astropy-astropy-13236   1          1           54s
astropy-astropy-13398   1          1           53s
astropy-astropy-13453   1          1           53s
kubectl get sandboxes

预期输出:

NAME                          STATUS    AGE
astropy-astropy-12907-dkrd9   Running   60s
astropy-astropy-12907-gczlt   Running   62s
astropy-astropy-12907-lgx6m   Running   62s
astropy-astropy-13033-2fvtq   Running   60s
astropy-astropy-13033-8mt4z   Running   61s
astropy-astropy-13033-t8lqs   Running   61s

每个 SandboxSet 管理一组 Sandbox 实例,每个 Sandbox 对应一个独立的 Agent 执行环境。

监控训练状态

通过 Ray Dashboard 监控各 Worker 的状态和 GPU 利用率。

kubectl port-forward svc/raycluster-verl-head-svc 8265:8265

在浏览器中访问 http://localhost:8265 查看 Ray Dashboard。在 Dashboard 中可以观察到:

  • 各 Worker 节点的资源使用情况。

  • Rollout 任务的执行进度。

  • GPU 显存和利用率。

查看训练日志

在 Ray Head Pod 中查看训练日志,确认 Rollout、奖励计算和策略更新正常执行。

kubectl logs $(kubectl get pods -l ray.io/node-type=head -o name) --tail=100

每轮 Rollout 完成后,日志会输出奖励统计信息(平均奖励、最高奖励、解决率等)。如果日志中持续出现 reward > 0 的记录,说明模型正在学习解决 Issue。

异常日志特征:如果日志中出现以下关键词,说明训练存在问题需要排查:

  • CUDA out of memory:显存不足,参见训练 OOM(显存不足)

  • ConnectionRefusedTimeoutError:Agent 无法连接 ProxyServer,检查 LOCAL_IP 配置。

  • FileNotFoundError:模型或数据集路径配置错误,检查 PVC 挂载路径和训练命令中的路径参数。

  • 所有 Rollout 的 reward 持续为 0.0:检查 Harbor 沙箱环境变量配置和 Sandbox Pod 是否正常运行。

验证镜像自动构建

对于尚未构建的 SWE-bench Instance,系统会自动调用 BuildKit 构建对应的 Docker 镜像并推送到指定 Registry。查看构建任务状态:

kubectl get jobs -l type=image-build

后续训练步骤可直接复用已构建的镜像。

常见问题

PVC 挂载失败(InvalidInstanceType.NotSupportDiskCategory)

现象:Pod 停留在 ContainerCreating 状态,kubectl describe pod 显示 FailedAttachVolume 错误,提示 InvalidInstanceType.NotSupportDiskCategory

原因:GPU 节点的 ECS 实例类型不支持 PVC 对应的云盘类型。例如,ecs.gn5 系列不支持 ESSD 云盘。

解决方案:将云盘类型替换为与 GPU 实例兼容的类型,重新创建 PV 和 PVC。例如,ecs.gn5 系列可将云盘类型从 cloud_essd 改为 cloud_ssd

PVC 挂载失败(ResourcesNotInSameZone)

现象:Pod 停留在 ContainerCreating 状态,kubectl describe pod 显示 ResourcesNotInSameZone 错误。

原因:云盘与 GPU 节点不在同一可用区。

解决方案:执行 kubectl get nodes -o custom-columns='NAME:.metadata.name,ZONE:.metadata.labels.topology\.kubernetes\.io/zone' 确认节点可用区,然后在相同可用区重新创建云盘。

Sandbox Pod 启动失败

现象kubectl get sandboxes 显示 Pod 状态为 PendingImagePullBackOff

排查步骤

  1. 检查镜像是否存在。确认 {registry}/swe-bench/{instance_id}:latest 已推送到镜像仓库。

    kubectl describe pod <sandbox-pod-name>
  2. 检查 imagePullSecret 是否正确配置。

    kubectl get secret acr-registry -o yaml
  3. 如果镜像未构建,检查 BuildKit 服务是否正常运行。

Agent 无法连接 ProxyServer

现象:训练日志中出现连接超时错误。

排查步骤

  1. 确认 LOCAL_IP 设置正确,Agent 所在的 Sandbox Pod 能访问该 IP。

    kubectl exec <sandbox-pod> -- curl http://<LOCAL_IP>:<proxy_port>/health
  2. 检查网络策略是否允许 Sandbox Pod 访问 Ray Head 节点。

训练 OOM(显存不足)

现象:训练过程中出现 CUDA out of memory 错误。

解决方案

  • 降低 ppo_max_token_len_per_gpu(默认 12288)。

  • 开启参数和优化器 offload(fsdp_config.param_offload=truefsdp_config.optimizer_offload=true)。

  • 降低 rollout.n 的值,减少并行采样轨迹数。

  • 增大 Pod 的 memory 资源请求。启用 FSDP offload 后模型权重会卸载到系统内存,Qwen2.5-7B 约需 20~25 GiB RAM,建议 Pod 内存设为 55 Gi 或以上。

CUDA 架构不兼容(no kernel image)

现象:训练启动时报错 CUDA error: no kernel image is available for execution on the device

原因:GPU 的 Compute Capability 低于镜像中 PyTorch 编译的最低支持版本。典型场景为使用 P100(sm_60)或 V100(sm_70)等旧架构 GPU。

解决方案:更换为 Compute Capability 8.0 及以上的 GPU 节点(如 ecs.gn7i 系列 A10、ecs.gn7e 系列 A100)。支持的实例规格请参见前提条件。

数据集下载失败或镜像构建超时

现象:执行 harbor datasets download 长时间无响应、git clone 超时、或 BuildKit 构建 SWE-bench 镜像时下载依赖失败。

原因

  • Pod 无法访问公网:集群 VPC 未配置 NAT 网关或 SNAT 规则。

  • 集群位于中国内地地域:GitHub 和 HuggingFace 在部分地域无法正常访问。

解决方案

  • 确认 VPC 已配置 NAT 网关和 SNAT 规则。可在 Pod 内执行 curl -I https://github.com 验证网络连通性。

  • 中国内地地域无法通过代理访问 GitHub 时,建议迁移到中国香港或海外地域。

  • pip 安装超时时,可使用阿里云镜像源加速:pip install <package> -i https://mirrors.aliyun.com/pypi/simple/

RayCluster Pod 镜像拉取失败(ImagePullBackOff)

现象:RayCluster Pod 状态为 ImagePullBackOffErrImagePullkubectl describe pod 显示 401 Unauthorizedmanifest unknown

排查步骤

  1. 确认已创建 imagePullSecret 且凭证正确:kubectl get secret <secret-name> -o jsonpath='{.data.\.dockerconfigjson}' | base64 -d

  2. 确认 RayCluster YAML 中 imagePullSecrets 的 name 与 Secret 名称一致。

  3. 确认镜像地址中的区域标识与 Secret 中的 docker-server 区域一致。例如,镜像为 registry-ap-southeast-1.ack.aliyuncs.com/...,Secret 的 docker-server 也应为 registry-ap-southeast-1.ack.aliyuncs.com

Pod 无法调度(Insufficient cpu/memory)

现象:Pod 长时间处于 Pending 状态,kubectl describe pod 显示 Insufficient cpuInsufficient memory

原因:RayCluster YAML 中的资源请求超过了节点可分配(Allocatable)资源。节点总资源中有一部分被系统组件(kubelet、OS 等)占用,因此 Allocatable 通常小于总资源。

解决方案

  1. 查看节点可分配资源:kubectl describe node <node-name> | grep -A 6 Allocatable

  2. 调整 RayCluster YAML 中的 resources.requests,确保不超过节点 Allocatable 值。例如,8 vCPU 节点的可分配 CPU 通常约为 7.9,CPU 请求应设为 7 或更低。

后续步骤

  • 调整 GRPO 超参数(如 clip_ratio_lowclip_ratio_high、学习率等)以优化训练效果。

  • 扩展到多节点训练,修改 trainer.nnodes 和 RayCluster 的 Worker 节点数。

  • 将训练好的模型部署为推理服务,请参见部署单机LLM推理服务