RayCluster 配置#
本指南涵盖了在 Kubernetes 上配置 Ray 集群的关键方面。
介绍#
在 Kubernetes 上部署 Ray 遵循 operator 模式。关键角色是
要部署一个 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
# Keep this preStop hook in each Ray container config.
lifecycle:
preStop:
exec:
command: ["/bin/sh","-c","ray stop"]
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 集群由
一个 主节点 ,负责为 Ray 集群托管全局控制进程。主节点也可以运行 Ray 任务和角色。
任意数量的 工作节点,它们运行 Ray 任务和角色。工作节点以相同配置的 工作组 形式出现。对于每个工作组,我们必须指定 副本,即我们希望该组拥有的节点数量。
头节点的配置在 headGroupSpec
下指定,而工作节点的配置在 workerGroupSpecs
下指定。可能存在多个工作组,每个组都有自己的配置。workerGroupSpec
的 replicas
字段指定了该组在集群中保持的工作节点数量。每个 workerGroupSpec
还有可选的 minReplicas
和 maxReplicas
字段;如果你想启用 自动扩展,这些字段很重要。
Pod 模板#
headGroupSpec
或 workerGroupSpec
的大部分配置都在 template
字段中。template
是一个 Kubernetes Pod 模板,它决定了该组中 Pod 的配置。以下是 Pod template
中需要注意的一些子字段:
容器#
Ray pod 模板至少指定一个容器,即运行 Ray 进程的容器。Ray pod 模板还可以指定额外的边车容器,用于诸如 日志处理 等目的。然而,KubeRay 操作符假设容器列表中的第一个容器是主 Ray 容器。因此,确保在主 Ray 容器之后指定任何边车容器。换句话说,Ray 容器应该是 containers
列表中的第一个。
资源#
为每个组规范指定容器CPU和内存的请求和限制非常重要。对于GPU工作负载,您可能还希望指定GPU限制。例如,如果使用Nvidia GPU设备插件并且希望指定一个可以访问2个GPU的pod,请设置nvidia.com/gpu:2
。有关GPU支持的更多详细信息,请参阅本指南。
理想情况下,每个 Ray pod 的大小应占据其被调度的 Kubernetes 节点的全部资源。换句话说,最好在每个 Kubernetes 节点上运行一个大型 Ray pod。通常,使用少量大型 Ray pod 比使用许多小型 pod 更高效。少量大型 Ray pod 的模式具有以下优点:
更高效地利用每个 Ray pod 的共享内存对象存储
减少 Ray pod 之间的通信开销
减少了每个pod的Ray控制结构(如Raylets)的冗余
在 Ray 容器配置中指定的 CPU、GPU 和内存 限制 将自动通告给 Ray。这些值将用作 Ray 头节点或工作组中 Ray pod 的逻辑资源容量。请注意,CPU 数量在传递给 Ray 之前会向上取整为最接近的整数。通告给 Ray 的资源容量可以在 Ray 启动参数 中被覆盖。
另一方面,Ray 会忽略 CPU、GPU 和内存的 请求。因此,最好在可能的情况下 将资源请求设置为等于资源限制。
nodeSelector 和 tolerations#
您可以通过设置 pod 规范的 nodeSelector
和 tolerations
字段来控制工作组 Ray pod 的调度。具体来说,这些字段决定了 pod 可以在哪些 Kubernetes 节点上调度。有关 Pod-to-Node 分配的更多信息,请参阅 Kubernetes 文档。
图像#
在 RayCluster
CR 中指定的 Ray 容器镜像应与 CR 的 spec.rayVersion
具有相同的 Ray 版本。如果您使用的是 nightly 或开发版的 Ray 镜像,您可以在 spec.rayVersion
下指定 Ray 的最新发布版本。
对于 Apple M1 或 M2 MacBook,请参阅 为 Apple M1 或 M2 MacBook 使用基于 ARM 的 Docker 镜像 以指定正确的镜像。
你必须为每个可能运行任务或角色的 Ray 节点安装代码依赖项。实现此配置的最简单方法是使用相同的 Ray 镜像作为 Ray 头节点和所有工作组。无论如何,请确保您的 CR 中的所有 Ray 镜像都具有相同的 Ray 版本和 Python 版本。要跨集群分发自定义代码依赖项,可以使用其中一个 官方 Ray 镜像 作为基础构建自定义容器镜像。请参阅 此指南 以了解更多关于官方 Ray 镜像的信息。对于面向迭代和开发的动态依赖项管理,你也可以使用 运行时环境。
对于 kuberay-operator
版本 1.1.0 及更高版本,Ray 容器镜像中必须安装 wget
。
metadata.name 和 metadata.generateName#
KubeRay 操作员将忽略用户设置的 metadata.name
和 metadata.generateName
的值。KubeRay 操作员将自动生成一个 generateName
以避免名称冲突。更多详情请参见 KubeRay issue #587。
Ray 启动参数#
每个组规范中的 rayStartParams
字段是一个字符串到字符串的映射,表示传递给 Ray 容器的 ray start
入口点的参数。有关参数的完整列表,请参阅 ray start 的文档。我们特别注意以下参数:
仪表盘-主机#
在大多数使用场景中,此字段应设置为“0.0.0.0”以用于 Ray 头节点。这是为了将 Ray 仪表板暴露在 Ray 集群外部所必需的。(未来的版本可能会默认设置此参数。)
num-cpus#
这个可选字段告诉 Ray 调度器和自动缩放器 Ray pod 有多少个 CPU 可用。CPU 数量可以从组规范的 pod template
中指定的 Kubernetes 资源限制中自动检测。然而,有时覆盖这个自动检测的值是有用的。例如,为 Ray 头 pod 设置 num-cpus:"0"
将防止 Ray 工作负载在头节点上调度具有非零 CPU 要求的任务。请注意,所有 Ray 启动参数的值,包括 num-cpus
,必须作为 字符串 提供。
num-gpus#
此字段指定 Ray 容器可用的 GPU 数量。在未来的 KubeRay 版本中,GPU 数量将从 Ray 容器资源限制中自动检测。请注意,所有 Ray 启动参数的值,包括 num-gpus
,必须以 字符串 形式提供。
内存#
Ray 可用的内存会自动从 Kubernetes 资源限制中检测。如果需要,您可以通过在 rayStartParams.memory
下设置所需的内存值(以字节为单位)来覆盖此自动检测的值。请注意,所有 Ray 启动参数的值,包括 memory
,必须作为 字符串 提供。
资源#
此字段可用于为 Ray pod 指定自定义资源容量。这些资源容量将被通告给 Ray 调度器和 Ray 自动缩放器。例如,以下注释将标记一个 Ray pod 具有 1 单位的 Custom1
容量和 5 单位的 Custom2
容量。
rayStartParams:
resources: '"{\"Custom1\": 1, \"Custom2\": 5}"'
然后,您可以使用 @ray.remote(resources={"Custom2": 1})
等注解来注解任务和参与者。Ray 调度器和自动扩展器将采取适当的行动来调度此类任务。
注意用于表示资源字符串的格式。特别是,注意反斜杠作为字符串中的实际字符存在。如果你在编程时指定一个 RayCluster
,你可能需要 转义反斜杠 以确保它们作为字符串的一部分被处理。
字段 rayStartParams.resources
仅应用于自定义资源。键 CPU
、GPU
和 memory
是被禁止的。如果需要为这些资源字段指定覆盖值,请使用 Ray 启动参数 num-cpus
、num-gpus
或 memory
。
服务和网络#
Ray 头部服务。#
KubeRay 操作符会自动配置一个 Kubernetes 服务,该服务暴露 Ray 头节点 Pod 的多个服务的默认端口,包括
Ray 客户端(默认端口 10001)
Ray 仪表盘(默认端口 8265)
Ray GCS 服务器(默认端口 6379)
Ray Serve (默认端口 8000)
Ray Prometheus 指标(默认端口 8080)
配置的 Kubernetes 服务的名称是 RayCluster 的名称 metadata.name
,后面加上后缀 head-svc
raycluster-example-head-svc
kube-dns
) 允许我们使用名称 raycluster-example-head-svc
ray.init("ray://raycluster-example-head-svc:10001")
Ray Client 服务器可以通过另一个命名空间中的 pod 访问。
ray.init("ray://raycluster-example-head-svc.default.svc.cluster.local:10001")
(这假设Ray集群被部署到默认的Kubernetes命名空间。如果Ray集群被部署在非默认命名空间中,请使用该命名空间代替default
。)
ServiceType, Ingresses#
Ray Client 和其他服务可以通过端口转发或入口暴露在 Kubernetes 集群外部。访问 Ray head 服务的最简单方式是使用端口转发。
在集群外部暴露头部的服务可能需要使用类型为 LoadBalancer 或 NodePort 的服务。将 headGroupSpec.serviceType
设置为适合您应用的类型。
您可能希望设置一个入口以将 Ray 头节点的服务暴露到集群外部。详情请参阅 [KubeRay 文档][IngressDoc]。
指定非默认端口。#
如果你想覆盖 Ray 头服务暴露的端口,可以通过在 headGroupSpec
下指定 Ray 头容器的 ports
列表来实现。以下是 Ray 头服务的非默认端口列表的示例。
ports:
- containerPort: 6380
name: gcs
- containerPort: 8266
name: dashboard
- containerPort: 10002
name: client
如果指定了头容器的 ports
列表,Ray 头服务将精确地暴露列表中的端口。在上面的例子中,头服务将只暴露三个端口;特别是不会暴露 Ray Serve 的端口。
为了让 Ray 头节点实际使用端口列表中指定的非默认端口,您还必须指定相关的 rayStartParams
。对于上述示例,
rayStartParams:
port: "6380"
dashboard-port: "8266"
ray-client-server-port: "10002"
...
Pod 和容器生命周期:preStopHook#
建议每个 Ray 容器的配置都包含以下阻塞块:
lifecycle:
preStop:
exec:
command: ["/bin/sh","-c","ray stop"]
为了确保优雅终止,在 Ray pod 终止之前会执行 ray stop
。