3. KubeRay CRD体系解析
KubeRay 把 Ray 的运行时形态抽象成一组 Kubernetes 自定义资源(CRD)。理解这套 CRD,本质上是在理解“谁负责创建 Ray 集群、谁负责提交作业、谁负责对外提供在线服务”这三个问题的边界。KubeRay 最常用的三个 CRD 是 RayCluster、RayJob 和 RayService,它们并非互相替代,而是覆盖了从“长期存在的算力底座”到“一次性批处理”再到“在线推理服务”的连续场景。
一、三个 CRD 的职责边界
RayCluster 是最基础的资源,它描述一个 Ray 集群的期望状态:Head 节点如何部署、Worker Group 有哪些、每组副本数与资源规格如何。它只负责“把集群拉起来并维持住”,不关心你在集群上跑什么。因此它适合作为共享算力池,被多个作业或服务复用。
RayJob 在 RayCluster 之上增加了“作业”语义。它既可以引用一个已存在的 RayCluster,也可以自己内嵌一个集群模板,由控制器按需创建集群、提交 entrypoint、等待结束,再根据 shutdownAfterJobFinishes 决定是否回收集群。它解决的是“提交一次、跑完即止”的批处理需求。
RayService 则面向在线服务。它同时管理一个 RayCluster 和一个 Serve 应用配置,通过 serveConfigV2 声明推理图(deployment、application),并借助零停机升级机制在旧集群与新集群之间切换流量。它适合模型推理、在线特征服务等需要长期可用、可滚动升级的场景。
二、字段结构的关键差异
三个 CRD 的字段设计直接反映了它们的定位。RayCluster 的核心是 spec.headGroupSpec 与 spec.workerGroupSpecs,前者定义 Head Pod 的模板、容器镜像、资源请求,后者是一个数组,每个元素包含 groupName、replicas、minReplicas、maxReplicas 和 template。当开启自动伸缩时,minReplicas 与 maxReplicas 才生效,控制器会依据 Ray 的 autoscaler 指标调整副本数。
RayJob 的关键字段是 entrypoint、runtimeEnvYAML、jobId、submissionMode 以及 shutdownAfterJobFinishes。submissionMode 可取 K8sJobMode 或 HTTPMode:前者把提交动作封装成 Kubernetes Job,适合与 K8s 原生调度配合;后者由 Operator 直接通过 Ray Dashboard 的 HTTP 接口提交,链路更短。若 shutdownAfterJobFinishes 为 true 且未引用外部集群,作业结束后 Operator 会删除自动创建的 RayCluster,避免资源空转。
RayService 的字段分为两半:rayClusterConfig 描述集群模板,serveConfigV2 描述 Serve 应用。后者是一段 YAML 字符串,内部包含 applications 列表,每个应用有 name、import_path、route_prefix 和 deployments。upgradeStrategy 控制升级行为,常用 type: NewCluster 配合 maxSurge,先拉起新集群、待其健康后再切流量、最后回收旧集群,从而实现零停机。
三、生命周期与状态机
RayCluster 的状态字段 status.state 会经历 Ready、NotReady 等阶段,并附带 head 与 workers 的就绪信息。它没有“完成”概念,除非被删除或缩容到零。
RayJob 的状态更丰富:status.jobStatus 会从 Pending 进入 Running,最终落到 Succeeded 或 Failed;同时 status.jobDeploymentStatus 记录集群准备与提交阶段。排查时先看 jobDeploymentStatus 是否卡在 WaitingForCluster,再看 jobStatus 是否已进入 Running,能快速区分“集群没起来”和“作业本身失败”。
RayService 的状态包含 activeServiceStatus 与 pendingServiceStatus,分别对应当前承载流量的集群和正在升级的新集群。当新集群的 Serve 应用健康后,二者角色互换,旧集群被清理。观察 status.conditions 中的 Ready 与 UpgradeInProgress,可以判断服务是否处于可用状态。
四、选型建议与常见误区
选型可以遵循一条简单原则:需要长期复用、多个作业共享同一套算力,选 RayCluster;一次提交、跑完即止、希望自动回收,选 RayJob;需要对外暴露 HTTP 接口、要求滚动升级不中断,选 RayService。
常见误区有两个。其一,用 RayJob 内嵌集群模板跑长周期服务,作业结束后集群被回收,服务随之中断;正确做法是改用 RayService 或让 RayJob 引用一个常驻的 RayCluster。其二,把 RayService 当成普通 Deployment 使用,忽略 serveConfigV2 中 route_prefix 与 deployments 的对应关系,导致请求 404。建议在提交前用 kubectl get rayservice -o yaml 核对 activeServiceStatus 中的路由与副本数,确认与预期一致后再接入流量。
RayJob 时,可先设置 shutdownAfterJobFinishes: false 保留集群,待确认作业逻辑无误后再改为 true 启用自动回收,避免反复重建集群带来的等待。