2. Ray核心概念与KubeRay映射
Ray 的编程模型与运行时对象,最终都要落到 Kubernetes 的 Pod、Service、CRD 上。理解 KubeRay 的关键,不是记住两套名词,而是建立一张“概念—资源—运行形态”的对应表:当你在 Ray 代码里写 @ray.remote、调用 .remote()、创建 Actor 时,集群里究竟多了什么、跑在哪里、状态由谁维护。本节围绕这张映射关系展开,并给出可观察、可验证的判断依据。
一、Ray 集群:从逻辑集群到 RayCluster CR
Ray 集群在逻辑上由 Head 节点和若干 Worker 节点组成,它们通过 GCS(Global Control Store)与 Raylet 协同。在 KubeRay 中,一个 Ray 集群对应一个 RayCluster 自定义资源(CR)。这个 CR 的 spec 描述期望形态:headGroupSpec 定义 Head 的 Pod 模板与副本数(通常为 1),workerGroupSpecs 是一个数组,每个元素是一个 Worker 组,包含 groupName、replicas、minReplicas、maxReplicas 以及 Pod 模板。
KubeRay Operator 监听 RayCluster,把它翻译成 Kubernetes 原生对象:Head 组生成一个 Head Pod 和一个名为 <cluster>-head-svc 的 Service;每个 Worker 组生成一个由 ReplicaSet 管理的 Pod 集合。因此“Ray 集群”在 K8s 里不是一台机器,而是一组带标签的 Pod 加一个稳定入口。判断集群是否就绪,可以看 kubectl get raycluster 的 state 字段是否为 ready,以及 Head Pod 是否 Running。
二、Head 节点:控制面与入口
Head 节点承担 GCS、Dashboard、Autoscaler 以及驱动进程的入口角色。在 KubeRay 中,它对应 headGroupSpec 生成的单个 Pod,容器内启动 ray start --head。Head Pod 暴露若干端口:6379 是 GCS/Redis 端口,8265 是 Dashboard,10001 是 Client Server。KubeRay 通过 Head Service 把这些端口稳定暴露,Worker 和其他客户端都通过该 Service 的 DNS 名连接。
需要注意:Head 节点默认也参与调度,但生产上通常给它加 ray.io/node-type=head 的污点或资源限制,避免业务 Task 挤占控制面。判断 Head 是否健康,可查看日志中是否出现 Ray runtime started,以及 Dashboard 能否在 8265 端口打开。
三、Worker 节点:计算资源的载体
Worker 节点是真正执行 Task 和 Actor 的地方。KubeRay 中每个 workerGroupSpec 对应一类 Worker,例如 CPU 组和 GPU 组可以分开定义,使用不同的 resources、nodeSelector 和镜像。Worker Pod 启动时执行 ray start --address=<head-svc>:6379,向 Head 注册并汇报自身资源。
Worker 组的 replicas 决定当前 Pod 数,minReplicas/maxReplicas 供 Autoscaler 伸缩。当 Ray 提交的任务超过现有资源时,Autoscaler 会调整 ReplicaSet 的副本数,K8s 随之创建新 Pod。观察伸缩是否生效,可对比 kubectl get pods -l ray.io/cluster=<name> 的数量与 Ray Dashboard 中 “Cluster” 页显示的节点数是否一致。
四、Task、Actor 与 Object Store 的落点
Task 是无状态远程函数调用,Actor 是有状态远程类实例。二者在 KubeRay 中都不直接对应某个 K8s 对象,而是由 Raylet 调度到某个 Worker Pod 的进程内执行。Object Store 是每个节点本地的共享内存对象存储,用于存放 Task 返回值、ray.put 的对象以及 Actor 间传递的数据。它对应的是 Pod 内的共享内存区域,因此 workerGroupSpec 中常通过 resources.limits 与 /dev/shm 的 emptyDir 配置来保证容量。
一个常见的坑是:Object Store 默认使用 /dev/shm,而容器默认只有 64MiB,稍大的对象就会溢出到磁盘甚至 OOM。KubeRay 示例中通常挂载 medium: Memory 的 emptyDir 到 /dev/shm,并设置 sizeLimit。判断是否命中该问题,可看 Worker 日志中的 Object store 相关告警,或观察 ray.get 是否异常缓慢。
五、映射关系速查与验证
把上面的对应关系整理成一张可核对的表,便于在排障时快速定位“Ray 层的问题”还是“K8s 层的问题”。
| Ray 概念 | KubeRay 资源 | 运行形态 | 验证方式 |
|---|---|---|---|
| Ray 集群 | RayCluster CR | 一组 Pod + Service | kubectl get raycluster 状态为 ready |
| Head 节点 | headGroupSpec → Head Pod | 单 Pod,含 GCS/Dashboard | 日志出现 Ray runtime started |
| Worker 节点 | workerGroupSpecs → ReplicaSet | 多 Pod,按组分类 | Pod 数与 Dashboard 节点数一致 |
| Task | 无独立资源 | Worker Pod 内进程 | Dashboard Jobs 页查看任务状态 |
| Actor | 无独立资源 | Worker Pod 内常驻进程 | Dashboard Actors 页查看存活 |
| Object Store | Pod 内 /dev/shm | 共享内存 emptyDir | 检查 sizeLimit 与 OOM 日志 |
workerGroupSpec 中显式挂载 emptyDir: {medium: Memory, sizeLimit: 2Gi} 到 /dev/shm,并让 resources.limits.memory 大于该值,避免 Object Store 与业务内存互相挤压。最后强调一个判断原则:Ray 层的报错(如 ObjectLostError、Actor 重启)往往根因在 K8s 层(Pod 被驱逐、节点资源不足、/dev/shm 过小)。排障时先看 kubectl describe pod 的 Events 与 kubectl get events,再回到 Ray Dashboard 看对象与 Actor 状态,两层对照才能快速收敛。掌握这张映射表,后续配置 Autoscaler、GCS 高可用、多组异构 Worker 时,就能清楚每一步改动落在哪个 K8s 对象上。