本地测试自动扩缩容#

测试自动扩缩容行为对于自动扩缩容的开发以及依赖自动扩缩容行为的应用程序的调试非常重要。您可以通过以下任一方法在本地运行自动扩缩容,而无需启动真实集群。

使用 RAY_FAKE_CLUSTER=1 ray start#

说明

  1. 导航到您本地克隆的 Ray 仓库的根目录。

  2. 找到 fake_multi_node/example.yaml 示例文件,并根据您的主节点实际拥有的 CPU 和 GPU 数量填写 head node type 配置。YAML 文件格式与集群自动扩缩容配置相同,但某些字段不受支持。

  3. 在 YAML 文件中按需配置 worker 类型和其他自动扩缩容配置。

  4. 在本地启动伪集群

$ ray stop --force
$ RAY_FAKE_CLUSTER=1 ray start \
    --autoscaling-config=./python/ray/autoscaler/_private/fake_multi_node/example.yaml \
    --head --block
  1. 使用 ray.init("auto") 将您的应用程序连接到本地伪集群。

  2. 运行 ray status 查看集群状态,或运行 cat /tmp/ray/session_latest/logs/monitor.* 查看自动扩缩容监视器日志。

$ ray status
======== Autoscaler status: 2021-10-12 13:10:21.035674 ========
Node status
---------------------------------------------------------------
Healthy:
 1 ray.head.default
 2 ray.worker.cpu
Pending:
 (no pending nodes)
Recent failures:
 (no failures)

Resources
---------------------------------------------------------------
Usage:
 0.0/10.0 CPU
 0.00/70.437 GiB memory
 0.00/10.306 GiB object_store_memory

Demands:
 (no resource demands)

使用 ray.cluster_utils.AutoscalingCluster#

要以编程方式创建伪多节点自动扩缩容集群并连接到它,您可以使用 cluster_utils.AutoscalingCluster。以下是一个基本的自动扩缩容测试示例,该测试会启动触发自动扩缩容的任务。

cluster = AutoscalingCluster(
    head_resources={"CPU": 2},
    worker_node_types={
        "cpu_node": {
            "resources": {
                "CPU": 4,
                "object_store_memory": 1024 * 1024 * 1024,
            },
            "node_config": {},
            "min_workers": 0,
            "max_workers": 2,
        },
        "gpu_node": {
            "resources": {
                "CPU": 2,
                "GPU": 1,
                "object_store_memory": 1024 * 1024 * 1024,
            },
            "node_config": {},
            "min_workers": 0,
            "max_workers": 2,
        },
        "tpu_node": {
            "resources": {
                "CPU": 2,
                "TPU": 4,
                "object_store_memory": 1024 * 1024 * 1024,
            },
            "node_config": {},
            "min_workers": 0,
            "max_workers": 2,
        },
        "tpu_v5e_node": {
            "resources": {
                "CPU": 4,
                "TPU": 8,
                "object_store_memory": 1024 * 1024 * 1024,
            },
            "node_config": {},
            "min_workers": 0,
            "max_workers": 2,
        },
        "tpu_v6e_node": {
            "resources": {
                "CPU": 4,
                "TPU": 8,
                "object_store_memory": 1024 * 1024 * 1024,
            },
            "node_config": {},
            "min_workers": 0,
            "max_workers": 2,
        },
    },
    autoscaler_v2=autoscaler_v2,
)

try:
    cluster.start()
    ray.init("auto")

    # Triggers the addition of a GPU node.
    @ray.remote(num_gpus=1)
    def f():
        print("gpu ok")

    # Triggers the addition of a CPU node.
    @ray.remote(num_cpus=3)
    def g():
        print("cpu ok")

    # Triggers the addition of a TPU node.
    @ray.remote(resources={"TPU": 4})
    def h():
        print("tpu ok")

    # Triggers the addition of a 8-chip TPU node.
    @ray.remote(resources={"TPU": 8})
    def i():
        print("8-chip tpu ok")

    ray.get(f.remote())
    ray.get(g.remote())
    ray.get(h.remote())
    ray.get(i.remote())
    ray.shutdown()
finally:
    cluster.shutdown()

Python 文档

class ray.cluster_utils.AutoscalingCluster(head_resources: dict, worker_node_types: dict, autoscaler_v2: bool = False, **config_kwargs)[source]#

创建一个本地自动扩缩容集群用于测试。

请参阅 test_autoscaler_fake_multinode.py 以获取端到端示例。

DeveloperAPI: 此 API 在 Ray 的次要版本之间可能会发生变化。

start(_system_config=None, override_env: Dict | None = None)[source]#

启动集群。

此调用返回后,您可以使用 ray.init(“auto”) 连接到集群。

shutdown()[source]#

终止集群。

fake_multinode 的功能和限制#

自动扩缩容的大部分功能在伪多节点模式下都得到支持。例如,如果您更新 YAML 文件内容,自动扩缩容器将像在真实集群中一样,捕获新配置并应用更改。节点选择、启动和终止受与真实集群相同的装箱和空闲超时算法的约束。

然而,也存在一些限制。

  1. 所有节点上的 Raylet 都在本地机器上非容器化运行,因此它们共享相同的 IP 地址。有关替代的本地多节点设置,请参阅 fake_multinode_docker 部分。

  2. 不支持 auth、setup、initialization、Ray start、文件同步以及任何特定于云的配置。

  3. 必须限制节点数量/节点 CPU/对象存储内存,以避免使本地机器过载。

使用 Docker compose 本地测试容器化多节点#

更进一步,如果您想在本地测试一个多节点设置,其中每个节点使用自己的容器(因此拥有独立的文件系统、IP 地址和 Ray 进程),则可以使用 fake_multinode_docker 节点提供程序。

该设置与 fake_multinode 提供程序非常相似。但是,您需要启动一个监视进程(docker_monitor.py),该进程负责运行 docker compose 命令。

先决条件

  1. 请确保已安装 Docker

  2. 请确保已安装 Docker Compose V2 插件

使用 RAY_FAKE_CLUSTER=1 ray up#

说明

  1. 导航到您本地克隆的 Ray 仓库的根目录。

  2. 找到 fake_multi_node/example_docker.yaml 示例文件,并根据您的主节点实际拥有的 CPU 和 GPU 数量填写 head node type 配置。YAML 文件格式与集群自动扩缩容配置相同,但某些字段不受支持。

  3. 在 YAML 文件中按需配置 worker 类型和其他自动扩缩容配置。

  4. 请确保主机系统上的 shared_volume_dir 为空。

  5. 启动监视进程

$ python ./python/ray/autoscaler/_private/fake_multi_node/docker_monitor.py \
    ./python/ray/autoscaler/_private/fake_multi_node/example_docker.yaml
  1. 使用 ray up 启动 Ray 集群。

$ RAY_FAKE_CLUSTER=1 ray up -y ./python/ray/autoscaler/_private/fake_multi_node/example_docker.yaml
  1. 使用 ray.init("ray://:10002") 将您的应用程序连接到本地伪集群。

  2. 或者,获取主节点的 shell。

$ docker exec -it fake_docker_fffffffffffffffffffffffffffffffffffffffffffffffffff00000_1 bash

使用 ray.autoscaler._private.fake_multi_node.test_utils.DockerCluster#

此实用程序用于编写使用多节点行为的测试。 DockerCluster 类可用于在临时目录中设置 Docker compose 集群,启动监视进程,等待集群启动,连接到它,以及更新配置。

请参阅 API 文档和示例测试用例,了解如何使用此实用程序。

class ray.autoscaler._private.fake_multi_node.test_utils.DockerCluster(config: Dict[str, Any] | None = None)[source]#

Docker 集群包装器。

创建用于启动伪多节点 Docker 集群的目录。

包含用于在测试中根据需要更新集群配置以及启动和连接集群的 API。

connect(client: bool = True, timeout: int = 120, **init_kwargs)[source]#

连接到 docker-compose Ray 集群。

假定集群位于 RAY_TESTHOST(默认为 127.0.0.1)。

参数:
  • client – 如果为 True,则使用 Ray client 连接到集群。如果为 False,则使用 GCS 连接到集群。

  • timeout – 连接超时(秒)。

  • **init_kwargs – 传递给 ray.init() 的关键字参数。

remote_execution_api() RemoteAPI[source]#

创建一个对象,用于从集群内部控制集群状态。

static wait_for_resources(resources: Dict[str, float], timeout: int = 60)[source]#

等待直到 Ray 集群资源可用。

参数:
  • resources – 在此函数返回之前所需的最小资源。

  • timeout – 超时时间(秒)。

update_config(config: Dict[str, Any] | None = None)[source]#

更新自动扩缩容配置。

对基础配置进行深度更新,加入新配置。这可以改变自动扩缩容行为。

参数:

config – 用于更新当前配置的局部配置。

setup()[source]#

设置 Docker compose 集群环境。

创建临时目录,写入初始配置文件,并在需要时拉取 Docker 镜像。

teardown(keep_dir: bool = False)[source]#

拆除 Docker compose 集群环境。

参数:

keep_dir – 如果为 True,则集群目录在终止后不会被删除。

start()[source]#

启动 Docker compose 集群。

启动监视进程并运行 ray up

stop()[source]#

停止 Docker compose 集群。

运行 ray down 并停止监视进程。

kill_node(node_id: str | None = None, num: int | None = None, rand: str | None = None)[source]#

杀死节点。

如果提供了 node_id,则杀死该节点。

如果提供了 num,则根据此数字构造 node_id 并杀死该节点。

如果提供了 rand(值为 workerany),则杀死一个随机节点。

fake_multinode_docker 的功能和限制#

伪多节点 Docker 节点提供程序在各自的容器中提供了功能齐全的节点。但是,仍然存在一些限制。

  1. 不支持 auth、setup、initialization、Ray start、文件同步以及任何特定于云的配置(但将来可能会支持)。

  2. 必须限制节点数量/节点 CPU/对象存储内存,以避免使本地机器过载。

  3. 在 Docker-in-Docker 设置中,必须遵循仔细的设置才能使伪多节点 Docker 提供程序正常工作(见下文)。

Docker 环境中的共享目录#

容器会将两个位置挂载到主机存储:

  • /cluster/node:此位置(在容器中)将指向 cluster_dir/nodes/<node_id>(在主机上)。此位置对于每个节点是唯一的,但可以用于主机检查此目录中存储的内容。

  • /cluster/shared:此位置(在容器中)将指向 cluster_dir/shared(在主机上)。此位置是节点之间共享的,并有效地充当共享文件系统(类似于 NFS)。

在 Docker-in-Docker (dind) 环境中进行设置#

在 Docker-in-Docker (dind) 环境中进行设置时(例如 Ray OSS Buildkite 环境),需要注意一些事项。为了清楚起见,请考虑以下概念:

  • 主机是没有容器化的机器,代码在该机器上执行(例如 Buildkite runner)。

  • 外部容器是直接在主机上运行的容器。在 Ray OSS Buildkite 环境中,会启动两个容器 - 一个 dind 网络主机和一个包含 Ray 源代码和 wheel 文件的容器。

  • 内部容器是伪多节点 Docker 节点提供程序启动的容器。

多节点 Docker 节点提供程序的控制平面位于外部容器中。但是,docker compose 命令是从连接的 Docker-in-Docker 网络执行的。在 Ray OSS Buildkite 环境中,这是主机 Docker 上运行的 dind-daemon 容器。如果您例如从主机挂载 /var/run/docker.sock,它将是主机 Docker 守护进程。我们之后将两者都称为主机守护进程

外部容器会修改需要挂载到内部容器(并在其中修改)的文件。这意味着主机守护进程也必须能够访问这些文件。

同样,内部容器会公开端口 - 但由于容器实际上是由主机守护进程启动的,因此这些端口也只能在主机(或 dind 容器)上访问。

对于 Ray OSS Buildkite 环境,我们因此设置了一些环境变量:

  • RAY_TEMPDIR="/ray-mount"。此环境变量定义了集群文件的临时目录创建位置。此目录必须能够被主机、外部容器和内部容器访问。在内部容器中,我们可以控制目录名称。

  • RAY_HOSTDIR="/ray"。如果共享目录在主机上的名称不同,我们可以动态地重写挂载点。在此示例中,外部容器通过 -v /ray:/ray-mount 或类似命令启动,因此主机上的目录是 /ray,外部容器中的是 /ray-mount(请参阅 RAY_TEMPDIR)。

  • RAY_TESTHOST="dind-daemon" 由于容器由主机守护进程启动,我们不能简单地连接到 localhost,因为端口未暴露给外部容器。因此,我们可以使用此环境变量设置 Ray 主机。

最后,docker-compose 显然需要一个 Docker 镜像。默认的 Docker 镜像是 rayproject/ray:nightly。Docker 镜像需要安装并启用 openssh-server。在 Buildkite 中,我们从 rayproject/ray:nightly-py38-cpu 构建一个新镜像,以避免在每次节点启动时(这是默认方式)安装此软件。此基础镜像已在之前的某个构建步骤中构建。

因此,我们设置:

  • RAY_DOCKER_IMAGE="rayproject/ray:multinode-py38"

  • RAY_HAS_SSH=1

以使用此 Docker 镜像,并告知我们的多节点基础设施 SSH 已安装。

本地开发#

如果您正在对伪多节点 Docker 模块进行本地开发,您可以设置:

  • FAKE_CLUSTER_DEV="auto"

这将把 ray/python/ray/autoscaler 目录挂载到已启动的节点。请注意,这可能在您的 Docker-in-Docker 设置中不起作用。

如果您想指定要挂载的顶级 Ray 目录,您可以使用:

  • FAKE_CLUSTER_DEV_MODULES="autoscaler,tune"

这将把 ray/python/ray/autoscalerray/python/ray/tune 都挂载到节点容器中。模块列表应以逗号分隔,无空格。