RayCluster 配置#
本指南涵盖了在 Kubernetes 上配置 Ray 集群的关键方面。
简介#
Ray 在 Kubernetes 上的部署遵循Operator 模式。关键组成部分是:
一个名为
RayCluster的自定义资源,用于描述 Ray 集群的期望状态。一个名为 KubeRay Operator 的自定义控制器,它负责管理 Ray Pod,以匹配
RayCluster的 spec。
要部署 Ray 集群,需要创建一个 RayCluster 自定义资源 (CR)。
kubectl apply -f raycluster.yaml
本指南涵盖了 RayCluster CR 配置的突出特性。
作为参考,这里是 RayCluster CR 的 YAML 格式的精简示例。
apiVersion: ray.io/v1alpha1
kind: RayCluster
metadata:
name: raycluster-complete
spec:
rayVersion: "2.3.0"
enableInTreeAutoscaling: true
autoscalerOptions:
...
headGroupSpec:
serviceType: ClusterIP # Options are ClusterIP, NodePort, and LoadBalancer
rayStartParams:
dashboard-host: "0.0.0.0"
...
template: # Pod template
metadata: # Pod metadata
spec: # Pod spec
containers:
- name: ray-head
image: rayproject/ray-ml:2.3.0
resources:
limits:
cpu: 14
memory: 54Gi
requests:
cpu: 14
memory: 54Gi
ports: # Optional service port overrides
- containerPort: 6379
name: gcs
- containerPort: 8265
name: dashboard
- containerPort: 10001
name: client
- containerPort: 8000
name: serve
...
workerGroupSpecs:
- groupName: small-group
replicas: 1
minReplicas: 1
maxReplicas: 5
rayStartParams:
...
template: # Pod template
spec:
...
# Another workerGroup
- groupName: medium-group
...
# Yet another workerGroup, with access to special hardware perhaps.
- groupName: gpu-group
...
本指南的其余部分将讨论 RayCluster CR 的配置字段。另请参阅关于使用 KubeRay 配置 Ray 自动缩放的指南。
Ray 版本#
字段 rayVersion 指定了 Ray 集群使用的 Ray 版本。 rayVersion 用于填充某些配置字段的默认值。RayCluster CR 中指定的 Ray 容器镜像应与 CR 的 rayVersion 具有相同的 Ray 版本。如果您使用的是 nightly 或开发版 Ray 镜像,可以将 rayVersion 设置为 Ray 的最新发布版本。
Pod 配置:headGroupSpec 和 workerGroupSpecs#
从宏观角度来看,RayCluster 是 Kubernetes Pod 的集合,类似于 Kubernetes Deployment 或 StatefulSet。与 Kubernetes 内置资源一样,关键的配置项是:
Pod 规范
缩放信息(期望的 Pod 数量)
Deployment 和 RayCluster 之间的主要区别在于,RayCluster 是专门为运行 Ray 应用程序而设计的。Ray 集群包含:
一个 **head Pod**,负责 Ray 集群的全局控制进程。Head Pod 也可以运行 Ray 任务和 Actor。
任意数量的 **worker Pod**,用于运行 Ray 任务和 Actor。Worker 以**工作组**的形式出现,每个工作组包含配置相同的 Pod。对于每个工作组,我们必须指定 **replicas**,即该工作组期望的 Pod 数量。
Head Pod 的配置在 headGroupSpec 下指定,而 Worker Pod 的配置在 workerGroupSpecs 下指定。可以有多个工作组,每个工作组都有自己的配置。 workerGroupSpec 的 replicas 字段指定了集群中该工作组的 Worker Pod 数量。每个 workerGroupSpec 还有可选的 minReplicas 和 maxReplicas 字段;如果您希望启用自动缩放,则这些字段很重要。
Pod 模板#
headGroupSpec 或 workerGroupSpec 的大部分配置都在 template 字段中。 template 是一个 Kubernetes Pod 模板,它决定了该组 Pod 的配置。以下是一些需要注意的 Pod template 的子字段:
容器#
Ray Pod 模板至少指定一个容器,即运行 Ray 进程的容器。Ray Pod 模板也可以指定额外的 sidecar 容器,用于日志处理等目的。但是,KubeRay Operator 假定 containers 列表中的第一个容器是主要的 Ray 容器。因此,请确保将任何 sidecar 容器指定在主 Ray 容器**之后**。换句话说,Ray 容器应该是 containers 列表中的**第一个**。
资源#
为每个组配置指定容器的 CPU 和内存资源非常重要。由于 CPU 是可压缩资源,您可能希望仅设置 CPU 请求而不设置限制,以保证您的工作负载有最低数量的 CPU,但允许它们利用未使用的 CPU 并且在超出其请求的 CPU 时不会被节流。
对于 GPU 工作负载,您可能还希望指定 GPU 限制。例如,如果您正在使用 NVIDIA GPU 设备插件并且希望指定一个访问 2 个 GPU 的 Pod,请将 nvidia.com/gpu: 2 设置为 2。有关 GPU 支持的更多详细信息,请参阅本指南。
KubeRay 会自动配置 Ray 以使用 Ray 容器配置中的 CPU、内存和 GPU **限制**。这些值是 head 或 worker 组的 Ray Pod 的逻辑资源容量。从 KubeRay 1.3.0 开始,如果限制不存在,KubeRay 会使用 CPU 请求。KubeRay 将 CPU 数量向上舍入到最接近的整数。您可以使用Ray Start Parameters覆盖这些资源容量。KubeRay 会忽略内存和 GPU **请求**。因此,如果可能,请**将内存和 GPU 资源请求设置为等于其限制**。
理想情况下,每个 Ray Pod 的大小都应能占据整个 Kubernetes 节点。换句话说,最好是每个 Kubernetes 节点运行一个大型 Ray Pod。总的来说,使用几个大型 Ray Pod 比使用许多小型 Ray Pod 更有效。较少的大型 Ray Pod 的模式具有以下优点:
更有效地利用每个 Ray Pod 的共享内存对象存储
减少 Ray Pod 之间的通信开销
减少每个 Pod 的 Ray 控制结构(如 Raylets)的冗余
nodeSelector 和 tolerations#
您可以通过设置 Pod spec 的 nodeSelector 和 tolerations 字段来控制 Worker 组 Ray Pod 的调度。具体来说,这些字段决定了 Pod 可以在哪些 Kubernetes 节点上调度。有关 Pod 到节点的分配的更多信息,请参阅Kubernetes 文档。
镜像#
RayCluster CR 中指定的 Ray 容器镜像应与 CR 的 spec.rayVersion 具有相同的 Ray 版本。如果您使用的是 nightly 或开发版 Ray 镜像,可以在 spec.rayVersion 下指定 Ray 的最新发布版本。
对于 Apple M1 或 M2 MacBook,请参阅为 Apple M1 或 M2 MacBook 使用基于 ARM 的 Docker 镜像来指定正确的镜像。
您必须在可能运行该任务或 Actor 的每个 Ray 节点上安装给定 Ray 任务或 Actor 所需的代码依赖项。实现此配置的最简单方法是为 Ray Head 和所有 Worker 组使用相同的 Ray 镜像。无论如何,请确保您的 CR 中的所有 Ray 镜像都具有相同的 Ray 版本和 Python 版本。要将自定义代码依赖项分发到您的集群中,您可以使用官方 Ray 镜像之一作为基础来构建自定义容器镜像。要了解有关官方 Ray 镜像的更多信息,请参阅本指南。对于针对迭代和开发的动态依赖项管理,您还可以使用Runtime Environments。
对于 kuberay-operator 版本 1.1.0 及更高版本,Ray 容器镜像必须安装 wget。
metadata.name 和 metadata.generateName#
KubeRay Operator 将忽略用户设置的 metadata.name 和 metadata.generateName 的值。KubeRay Operator 将自动生成一个 generateName 来避免名称冲突。有关更多详细信息,请参阅KubeRay issue #587。
Ray Start Parameters#
每个组 spec 的 rayStartParams 字段是传递给 Ray 容器 ray start 入口点的参数的字符串到字符串映射。有关参数的完整列表,请参阅ray start文档。KubeRay 中 1.4.0 版本之前的 RayCluster Kubernetes 自定义资源自定义资源定义 (CRD) 要求存在此字段,但其值可以为空映射。从 KubeRay 1.4.0 开始,rayStartParams 是可选的。
请注意以下参数:
dashboard-host#
对于大多数用例,此字段对于 Ray Head Pod 应设置为“0.0.0.0”。这对于在 Ray 集群外部公开 Ray Dashboard 是必需的。(未来版本可能会默认设置此参数。)
num-cpus#
此可选字段告诉 Ray 调度器和自动缩放器该 Ray Pod 可用的 CPU 数量。CPU 数量可以从组 spec 的 Pod template 中指定的 Kubernetes 资源限制自动检测。但是,有时覆盖此自动检测值很有用。例如,为 Ray Head Pod 设置 num-cpus:"0" 将阻止具有非零 CPU 要求的 Ray 工作负载调度到 Head 上。请注意,所有 Ray 启动参数(包括 num-cpus)的值都必须作为**字符串**提供。
num-gpus#
此字段指定了 Ray 容器可用的 GPU 数量。在未来的 KubeRay 版本中,GPU 数量将从 Ray 容器资源限制中自动检测。请注意,所有 Ray 启动参数(包括 num-gpus)的值都必须作为**字符串**提供。
memory#
Ray 可用的内存是从 Kubernetes 资源限制中自动检测的。如果需要,您可以通过在 rayStartParams.memory 下设置所需的内存值(以字节为单位)来覆盖此自动检测值。请注意,所有 Ray 启动参数(包括 memory)的值都必须作为**字符串**提供。
resources#
此字段可用于指定 Ray Pod 的自定义资源容量。这些资源容量将广告给 Ray 调度器和 Ray 自动缩放器。例如,以下注解将标记一个 Ray Pod,使其具有 1 个单位的 Custom1 容量和 5 个单位的 Custom2 容量。
rayStartParams:
resources: '"{\"Custom1\": 1, \"Custom2\": 5}"'
然后,您可以使用类似 @ray.remote(resources={"Custom2": 1}) 的注解来标记任务和 Actor。Ray 调度器和自动缩放器将采取适当的措施来调度这些任务。
请注意用于表示资源字符串的格式。特别是,请注意反斜杠作为字符串中的实际字符存在。如果您以编程方式指定 RayCluster,您可能需要转义反斜杠以确保它们作为字符串的一部分进行处理。
字段 rayStartParams.resources 仅应用于自定义资源。禁止使用键 CPU、GPU 和 memory。如果您需要为这些资源字段指定覆盖,请使用 Ray 启动参数 num-cpus、num-gpus 或 memory。
服务和网络#
Ray Head 服务。#
KubeRay Operator 会自动配置一个 Kubernetes Service,暴露 Ray Head Pod 的多个服务的默认端口,包括:
Ray Client (默认端口 10001)
Ray Dashboard (默认端口 8265)
Ray GCS 服务器 (默认端口 6379)
Ray Serve (默认端口 8000)
Ray Prometheus 指标 (默认端口 8080)
配置的 Kubernetes Service 的名称是 RayCluster 的名称 metadata.name 加上后缀:head-svcraycluster-example-head-svckube-dns) 允许我们使用名称来寻址 Ray Head 的服务:raycluster-example-head-svc
ray.init("ray://raycluster-example-head-svc:10001")
从另一个 Namespace 中的 Pod 可以使用以下方式访问 Ray Client 服务器:
ray.init("ray://raycluster-example-head-svc.default.svc.cluster.local:10001")
(这假设 Ray 集群已部署到默认的 Kubernetes Namespace。如果 Ray 集群部署在非默认 Namespace 中,请在 default 的位置使用该 Namespace。)
指定非默认端口。#
如果您希望覆盖 Ray Head Service 公开的端口,可以通过在 headGroupSpec 下指定 Ray Head 容器的 ports 列表来实现。以下是一个 Ray Head Service 的非默认端口列表示例:
ports:
- containerPort: 6380
name: gcs
- containerPort: 8266
name: dashboard
- containerPort: 10002
name: client
如果指定了 Head 容器的 ports 列表,Ray Head Service 将仅公开列表中的端口。在上面的示例中,Head Service 将仅公开三个端口;特别是,不会为 Ray Serve 公开端口。
要使 Ray Head 实际使用端口列表中指定的非默认端口,您还必须指定相关的 rayStartParams。对于上面的示例:
rayStartParams:
port: "6380"
dashboard-port: "8266"
ray-client-server-port: "10002"
...