> ## Documentation Index
> Fetch the complete documentation index at: https://starforge.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# kuberay 后端

> K8s + KubeRay：operator、RBAC、作业包分发、GPU 调度

生产推荐形态：每个训练作业一个临时 RayCluster（RayJob），终态即销毁，资源回收由 K8s 保证。

## 前置

1. Kubernetes 集群（GPU 节点装好 device plugin）；
2. [KubeRay operator](https://github.com/ray-project/kuberay)（helm 安装，v1.4+）；
3. 对象存储（**必需**：作业包经预签名 URL 分发进容器）；
4. GPU 节点按卡型打标签：`kubectl label node <n> starforge/gpu-series=h200`。

## 配置

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
FORGE_DEFAULT_FLEET_KIND=kuberay
FORGE_IMAGE_NEMO_RL=registry.internal/starforge/nemo-rl:v0.7.0
FORGE_NEMO_RL_DIR=/opt/nemo-rl
FORGE_K8S_API_SERVER=https://<apiserver>:6443
FORGE_K8S_TOKEN=<ServiceAccount token>        # 需 RayJob/Pod CRUD 权限
FORGE_K8S_NAMESPACE=starforge
FORGE_K8S_GPU_NODE_LABEL=starforge/gpu-series  # 卡型标签键（容量统计与 nodeSelector 同源）
FORGE_K8S_SHM_SIZE=64Gi                       # Ray object store 走 /dev/shm
FORGE_STORAGE_ROOT=/starforge                  # 唯一存储根
FORGE_K8S_STORAGE_PVC=starforge-storage        # 存储根对应的 RWX PVC
FORGE_K8S_STORAGE_SHARED=true                  # PVC 是 RWO 时设 false：多机作业会被明确拒绝
# FORGE_K8S_CORPUS_PVC=starforge-corpus        # 可选：只读语料 PVC
# FORGE_K8S_STORAGE_MOUNT=/storage             # 仅当 Pod 内无法挂在 FORGE_STORAGE_ROOT 时
FORGE_KUBERAY_RAY_VERSION=2.55.1              # 集群 operator 兼容的 Ray 版本
FORGE_KUBERAY_TTL_SECONDS=600                 # 主动清理失败时的 K8s GC 兜底
FORGE_KUBERAY_PRERUNNING_DEADLINE_S=1800      # 起不来（镜像/调度）多久判失败
FORGE_S3_ENDPOINT=…                           # 对象存储（作业包分发必需）
FORGE_S3_BUCKET=starforge
FORGE_S3_ACCESS_KEY=…                         # Secret
FORGE_S3_SECRET_KEY=…                         # Secret
```

## 语义要点

<AccordionGroup>
  <Accordion title="Job Capsule 分发" icon="package">
    Console 把用户代码、权威 JobSpec、manifest 与 `runner.pex` 组装成内容寻址 Capsule 并上传对象存储。HTTPS 归档走 Ray `runtimeEnvYAML.working_dir`；仅 HTTP 的对象存储由每个 Ray Pod 的 init container 先校验 transport SHA-256，再以相同 `file://` 路径交给 runtime-env agent。训练镜像无需平台 bootstrap 包。
  </Accordion>

  <Accordion title="RayJob 形态" icon="boxes">
    head = 主池 machine zero；多池作业每池一个 worker group（nodeSelector 按卡型、Ray 自定义资源 pin）。`shutdownAfterJobFinishes=true` + `backoffLimit=0`：训练不盲目重试。终态日志归档后平台立即删除 RayJob；TTL 是异常兜底。
  </Accordion>

  <Accordion title="容量与调度" icon="cpu">
    集群容量从节点 `nvidia.com/gpu` 容量 + 卡型标签实时统计；不可调度节点计入 blocked。页面显示的分卡型容量与调度器实际可落的节点**同源**。
  </Accordion>

  <Accordion title="卡在 Pending 的排查" icon="search">
    真正原因只在 K8s Event 里（拉镜像失败 / 无满足 nodeSelector 的节点 / GPU 不足）——作业详情的事件视图直接展示；超过 preRunning 期限自动判失败，不会无限占队列。
  </Accordion>

  <Accordion title="无 GPU 集群（仅测试）" icon="flask-conical">
    `FORGE_K8S_GPU_PASSTHROUGH=0`：Pod 不请求 `nvidia.com/gpu`，Ray 逻辑资源照常。kind/CI 跑闭环用，生产保持默认。
  </Accordion>
</AccordionGroup>

## Playground

支持：独立 vLLM Pod（非 RayJob），经 K8s API 代理访问，TTL 到期回收。

## 快速验证

```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
bash scripts/e2e/setup-kind.sh              # 本地 kind + operator（开发验证）
uv run python scripts/e2e/kuberay_loop.py   # 全链路闭环
```
