(高级) 不使用 KubeRay 部署静态 Ray 集群#

Ray 的这种部署方法不再需要使用自定义资源定义 (CRDs)。相比之下,CRDs 是使用 KubeRay 的先决条件。KubeRay 的关键组件之一 KubeRay Operator 通过监听 Kubernetes 事件(创建/删除/更新)来管理 Ray 集群资源。尽管 KubeRay Operator 可以在单个命名空间内运行,但使用 CRDs 具有集群范围的作用域。如果部署 KubeRay 不具备必要的 Kubernetes 管理权限,本文档介绍了一种在不使用 KubeRay 的情况下将静态 Ray 集群部署到 Kubernetes 的方法。但是,需要注意的是,这种部署方法缺乏 KubeRay 提供的内置自动扩缩容功能。

准备工作#

安装最新的 Ray 版本#

使用Ray 作业提交与远程集群交互时需要此步骤。

! pip install -U "ray[default]"

有关更多详细信息,请参阅安装 Ray

安装 kubectl#

要与 Kubernetes 交互,我们将使用 kubectl。安装说明可在Kubernetes 文档中找到。

访问 Kubernetes 集群#

我们需要访问 Kubernetes 集群。有两种选择

  1. 配置对远程 Kubernetes 集群的访问权限 或者

  2. 通过安装 kind 在本地运行示例。运行以下命令启动您的 kind 集群

! kind create cluster

要执行本指南中的示例,请确保您的 Kubernetes 集群(或本地 Kind 集群)可以处理 3 个 CPU 和 3Gi 内存的额外资源请求。另外,请确保您的 Kubernetes 集群和 Kubectl 版本均不低于 1.19。

部署 Redis 实现故障容错#

请注意,Kubernetes 部署配置文件中包含一个用于将 Redis 部署到 Kubernetes 的部分,以便 Ray 头节点可以通过它写入 GCS 元数据。如果 Redis 已经在 Kubernetes 上部署,则可以省略此部分。

部署静态 Ray 集群#

在本节中,我们将在不使用 KubeRay 的情况下将静态 Ray 集群部署到default命名空间。要使用其他命名空间,请在 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 集群部署完成后,您可以运行以下命令查看头节点和工作节点的 Pods

! 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

等待 Pods 达到 Running 状态。这可能需要几分钟时间——大部分时间用于下载 Ray 镜像。在另一个 shell 中,您可以使用以下命令实时观察 Pods 的状态

# If you're on MacOS, first `brew install watch`.
# Run in a separate shell:

! watch -n 1 kubectl get pod

如果您的 Pods 卡在 Pending 状态,您可以通过 kubectl describe pod deployment-ray-head-xxxx-xxxxx 查看错误,并确保您的 Docker 资源限制设置得足够高。

请注意,在生产环境中,您会希望使用更大的 Ray Pods。实际上,将每个 Ray Pod 设置为占用整个 Kubernetes 节点是有利的。有关更多详细信息,请参阅配置指南

为静态 Ray 集群部署网络策略#

如果您的 Kubernetes 对 Pods 有默认的拒绝网络策略,则需要手动创建一个网络策略,以允许 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 集群一样,我们可以直接 exec 进入头 Pod 并运行 Ray 程序。

首先,运行以下命令获取头 Pod

! kubectl get pods --selector=app=ray-cluster-head

# NAME                                             READY   STATUS    RESTARTS   AGE
# deployment-ray-head-xxxxx                        1/1     Running   0          XXs

现在我们可以在之前确定的头 Pod 上执行 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 作业

Ray 作业提交#

要为 Ray 作业提交设置 Ray 集群,需要确保 Ray Jobs 端口可供客户端访问。Ray 通过头节点上的 Dashboard 服务器接收作业请求。

首先,我们需要识别 Ray 头节点。静态 Ray 集群配置文件设置了一个针对 Ray 头 Pod 的Kubernetes Service。此 Service 允许我们与 Ray 集群交互,而无需直接在 Ray 容器中执行命令。要识别示例集群的 Ray 头 Service,请运行

! 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

现在我们有了 Service 的名称,可以使用端口转发来访问 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

现在我们已经可以访问 Dashboard 端口,可以提交作业到 Ray 集群执行

! ray job submit --address http://localhost:8265 -- python -c "import ray; ray.init(); print(ray.cluster_resources())"

清理#

删除 Ray 集群#

删除静态 Ray 集群的 Service 和 Deployment

! 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