Prerequisites
- A Kubernetes cluster (GPU nodes with the device plugin installed);
- KubeRay operator (installed via helm, v1.4+);
- Object storage (required: job packages are distributed into containers via presigned URLs);
- GPU nodes labeled by series:
kubectl label node <n> starforge/gpu-series=h200.
Configuration
Key semantics
Job Capsule distribution
Job Capsule distribution
The console assembles user code, the authoritative JobSpec, manifest, and
runner.pex into a content-addressed Capsule and uploads it to object storage. HTTPS archives use Ray’s runtimeEnvYAML.working_dir; for HTTP-only storage, an init container in every Ray Pod verifies the transport SHA-256 and exposes the same file:// path to the runtime-env agent. Training images need no platform bootstrap package.RayJob shape
RayJob shape
head = machine zero of the primary pool; multi-pool jobs get one worker group per pool (nodeSelector by series, pinned via Ray custom resources).
shutdownAfterJobFinishes=true + backoffLimit=0: training never retries blindly. The platform deletes the RayJob immediately after archiving terminal logs; TTL is only a failure fallback.Capacity and scheduling
Capacity and scheduling
Cluster capacity is computed live from node
nvidia.com/gpu capacity plus series labels; unschedulable nodes count as blocked. The per-series capacity shown in the UI and the nodes the scheduler can actually land on come from the same source.Troubleshooting jobs stuck in Pending
Troubleshooting jobs stuck in Pending
The real cause only lives in K8s Events (image pull failure / no node satisfying the nodeSelector / not enough GPUs) — the job detail’s event view surfaces them directly. Jobs exceeding the preRunning deadline are failed automatically, so they never occupy the queue indefinitely.
GPU-less clusters (testing only)
GPU-less clusters (testing only)
FORGE_K8S_GPU_PASSTHROUGH=0: Pods don’t request nvidia.com/gpu, while Ray logical resources work as usual. For running the closed loop on kind/CI; production keeps the default.