(高级) 在没有 KubeRay 的情况下部署一个静态 Ray 集群#
这种 Ray 的部署方法不再需要使用自定义资源定义(CRD)。相比之下,CRD 是使用 KubeRay 的前提条件。其关键组件之一,KubeRay 操作员,通过监视 Kubernetes 事件(创建/删除/更新)来管理 Ray 集群资源。虽然 KubeRay 操作员可以在单个命名空间内运行,但 CRD 的使用具有集群范围的影响。如果部署 KubeRay 所需的 Kubernetes 管理员权限不可用,本文档介绍了一种在不使用 KubeRay 的情况下将静态 Ray 集群部署到 Kubernetes 的方法。但需要注意的是,这种部署方法缺乏 KubeRay 提供的内置自动扩展功能。
准备#
安装最新的 Ray 版本#
此步骤对于使用 Ray 作业提交 与远程集群交互是必要的。
! pip install -U "ray[default]"
更多详情请参见 安装。
安装 kubectl#
要与 Kubernetes 交互,我们将使用 kubectl。安装说明可以在 Kubernetes 文档 中找到。
访问 Kubernetes 集群#
我们将需要访问一个 Kubernetes 集群。有两种选择:
! kind create cluster
要执行本指南中的示例,请确保您的 Kubernetes 集群(或本地 Kind 集群)能够处理额外的 3 个 CPU 和 3Gi 内存的资源请求。此外,请确保您的 Kubernetes 集群和 Kubectl 至少是 1.19 版本。
部署一个用于容错的 Redis#
请注意,Kubernetes 部署配置文件 中有一个部分用于在 Kubernetes 上部署 Redis,以便 Ray 头节点可以通过 GCS 元数据进行写入。如果 Redis 已经在 Kubernetes 上部署,则可以省略此部分。
部署一个静态 Ray 集群#
在本节中,我们将在 default
命名空间中部署一个静态 Ray 集群,而不使用 KubeRay。要使用另一个命名空间,请在您的 kubectl 命令中指定命名空间:
kubectl -n <你的命名空间> ...
# Deploy a sample Ray Cluster from the Ray repo:
! kubectl apply -f https://raw.githubusercontent.com/ray-project/ray/master/doc/source/cluster/kubernetes/configs/static-ray-cluster.with-fault-tolerance.yaml
# Note that the Ray cluster has fault tolerance enabled by default using the external Redis.
# Please set the Redis IP address in the config.
# The password is currently set as '' for the external Redis.
# Please download the config file and substitute the real password for the empty string if the external Redis has a password.
一旦Ray集群部署完成,您可以通过运行命令来查看头节点和工作节点的pod。
! kubectl get pods
# NAME READY STATUS RESTARTS AGE
# deployment-ray-head-xxxxx 1/1 Running 0 XXs
# deployment-ray-worker-xxxxx 1/1 Running 0 XXs
# deployment-ray-worker-xxxxx 1/1 Running 0 XXs
等待 pod 达到 Running
状态。这可能需要几分钟 – 大部分时间用于下载 Ray 镜像。在另一个 shell 中,您可能希望使用以下命令实时观察 pod 的状态:
# If you're on MacOS, first `brew install watch`.
# Run in a separate shell:
! watch -n 1 kubectl get pod
如果你的 Pod 卡在 Pending
状态,你可以通过 kubectl describe pod deployment-ray-head-xxxx-xxxxx
检查错误,并确保你的 Docker 资源限制设置得足够高。
请注意,在生产环境中,您可能希望使用更大的 Ray pod。实际上,将每个 Ray pod 的大小调整为占用整个 Kubernetes 节点是有优势的。有关更多详细信息,请参阅 配置指南。
为静态 Ray 集群部署网络策略#
如果你的 Kubernetes 对 pod 有默认拒绝的网络策略,你需要手动创建一个网络策略,以允许 Ray 集群中的头节点和工作节点之间的双向通信,如 端口配置文档 中所述。
# Create a sample network policy for the static Ray cluster from the Ray repo:
! kubectl apply -f https://raw.githubusercontent.com/ray-project/ray/master/doc/source/cluster/kubernetes/configs/static-ray-cluster-networkpolicy.yaml
一旦网络策略被部署,你可以通过运行以下命令来查看静态 Ray 集群的网络策略
! kubectl get networkpolicies
# NAME POD-SELECTOR AGE
# ray-head-egress app=ray-cluster-head XXs
# ray-head-ingress app=ray-cluster-head XXs
# ray-worker-egress app=ray-cluster-worker XXs
# ray-worker-ingress app=ray-cluster-worker XXs
外部 Redis 集成以实现容错#
Ray 默认使用一个称为全局控制存储(GCS)的内部键值存储。GCS 运行在头节点上并存储集群元数据。这种方法的一个缺点是,如果头节点崩溃,元数据会丢失。Ray 也可以将这些元数据写入外部的 Redis 以提高可靠性和高可用性。通过这种设置,静态 Ray 集群可以在头节点崩溃后恢复,并在不丢失与工作节点连接的情况下容忍 GCS 故障。
要使用此功能,我们需要在 Kubernetes 部署配置文件 的 Ray 头节点部分中传入 RAY_REDIS_ADDRESS
环境变量和 --redis-password
。
在静态 Ray 集群上运行应用程序#
在本节中,我们将与刚刚部署的静态 Ray 集群进行交互。
使用 kubectl exec 访问集群#
与使用 KubeRay 部署的 Ray 集群相同,我们可以直接进入头节点并运行 Ray 程序。
首先,运行以下命令以获取头部Pod:
! kubectl get pods --selector=app=ray-cluster-head
# NAME READY STATUS RESTARTS AGE
# deployment-ray-head-xxxxx 1/1 Running 0 XXs
我们现在可以在之前识别的头节点上执行一个 Ray 程序。以下命令连接到 Ray 集群,然后终止 Ray 程序。
# Substitute your output from the last cell in place of "deployment-ray-head-xxxxx"
! kubectl exec deployment-ray-head-xxxxx -it -c ray-head -- python -c "import ray; ray.init('auto')"
# 2022-08-10 11:23:17,093 INFO worker.py:1312 -- Connecting to existing Ray cluster at address: <IP address>:6380...
# 2022-08-10 11:23:17,097 INFO worker.py:1490 -- Connected to Ray cluster. View the dashboard at ...
虽然上述单元格偶尔在 Ray 集群上执行可能有用,但推荐的方法是在 Ray 集群上运行应用程序时使用 Ray Jobs。
Ray 作业提交#
要为 Ray 作业提交设置 Ray 集群,必须确保 Ray 作业端口对客户端是可访问的。Ray 通过头节点上的 Dashboard 服务器接收作业请求。
首先,我们需要识别 Ray 头节点。静态 Ray 集群配置文件设置了一个 Kubernetes 服务,该服务指向 Ray 头 pod。此服务使我们能够与 Ray 集群交互,而无需直接在 Ray 容器中执行命令。要识别示例集群的 Ray 头服务,请运行:
! kubectl get service service-ray-cluster
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# service-ray-cluster ClusterIP 10.92.118.20 <none> 6380/TCP,8265/TCP,10001/TCP... XXs
既然我们已经有了服务的名称,我们可以使用端口转发来访问 Ray Dashboard 端口(默认是8265)。
# Execute this in a separate shell.
# Substitute the service name in place of service-ray-cluster
! kubectl port-forward service/service-ray-cluster 8265:8265
现在我们已经可以访问仪表板端口,我们可以将作业提交到 Ray 集群进行执行:
! ray job submit --address http://localhost:8265 -- python -c "import ray; ray.init(); print(ray.cluster_resources())"
清理#
删除一个 Ray 集群#
删除静态 Ray 集群服务和部署
! kubectl delete -f https://raw.githubusercontent.com/ray-project/ray/master/doc/source/cluster/kubernetes/configs/static-ray-cluster.with-fault-tolerance.yaml
删除静态 Ray 集群网络策略
! kubectl delete -f https://raw.githubusercontent.com/ray-project/ray/master/doc/source/cluster/kubernetes/configs/static-ray-cluster-networkpolicy.yaml