配置 Ray#
注意
对于运行 Java 应用,请参阅Java 应用。
本页面讨论了通过 Python API 和命令行配置 Ray 的各种方法。有关配置的完整概述,请查阅 ray.init
文档。
重要
对于多节点设置,您必须首先在命令行上运行 ray start
来启动机器上的 Ray 集群服务,然后才能在 Python 中调用 ray.init
连接到集群服务。在单机上,您可以直接运行 ray.init()
而无需先运行 ray start
,它会同时启动 Ray 集群服务并连接到它们。
集群资源#
Ray 默认检测可用资源。
import ray
# This automatically detects available resources in the single machine.
ray.init()
如果未运行集群模式,您可以通过 ray.init
指定集群资源覆盖,如下所示。
# If not connecting to an existing cluster, you can specify resources overrides:
ray.init(num_cpus=8, num_gpus=1)
# Specifying custom resources
ray.init(num_gpus=1, resources={'Resource1': 4, 'Resource2': 16})
从命令行启动 Ray 时,将 --num-cpus
和 --num-gpus
标志传递给 ray start
。您还可以指定自定义资源。
# To start a head node.
$ ray start --head --num-cpus=<NUM_CPUS> --num-gpus=<NUM_GPUS>
# To start a non-head node.
$ ray start --address=<address> --num-cpus=<NUM_CPUS> --num-gpus=<NUM_GPUS>
# Specifying custom resources
ray start [--head] --num-cpus=<NUM_CPUS> --resources='{"Resource1": 4, "Resource2": 16}'
如果使用命令行,请按如下方式连接到 Ray 集群
# Connect to ray. Notice if connected to existing cluster, you don't specify resources.
ray.init(address=<address>)
日志记录和调试#
每个 Ray 会话都有一个唯一的名称。默认情况下,名称为 session_{timestamp}_{pid}
。timestamp
的格式为 %Y-%m-%d_%H-%M-%S_%f
(详见Python 时间格式);pid 属于启动进程(调用 ray.init()
的进程或在 ray start
中由 shell 执行的 Ray 进程)。
对于每个会话,Ray 会将其所有临时文件放在 会话目录 下。会话目录 是 根临时路径(默认为 /tmp/ray
)的子目录,因此默认的会话目录是 /tmp/ray/{ray_session_name}
。您可以按名称排序以查找最新的会话。
通过将 --temp-dir={your temp path}
传递给 ray start
来更改 根临时目录。
目前没有稳定的方法可以在调用 ray.init()
时更改根临时目录,但如果需要,您可以向 ray.init()
提供 _temp_dir
参数。
查阅 日志目录结构 获取更多详情。
端口配置#
Ray 需要集群中节点之间进行双向通信。每个节点会打开特定的端口来接收传入的网络请求。
所有节点#
--node-manager-port
: Raylet 的节点管理器端口。默认值:随机值。--object-manager-port
: Raylet 的对象管理器端口。默认值:随机值。--runtime-env-agent-port
: Raylet 的运行时环境代理端口。默认值:随机值。
节点管理器和对象管理器作为独立的进程运行,并使用各自的通信端口。
以下选项指定仪表板代理进程使用的端口。
--dashboard-agent-grpc-port
: 用于监听 grpc 的端口。默认值:随机值。--dashboard-agent-listen-port
: 用于监听 http 的端口。默认值:52365。--metrics-export-port
: 用于暴露 Ray 指标的端口。默认值:随机值。
以下选项指定跨机器的 worker 进程使用的端口范围。范围内的所有端口都应打开。
--min-worker-port
: worker 绑定的最小端口号。默认值:10002。--max-worker-port
: worker 绑定的最大端口号。默认值:19999。
端口号是 Ray 在单个节点上区分多个 worker 的输入和输出的方式。每个 worker 在一个端口号上接收输入并提供输出。因此,默认情况下,每个节点最多有 10,000 个 worker,与 CPU 数量无关。
通常,您应该为 Ray 提供一个宽泛的 worker 端口范围,以防您的机器上恰好有其他程序正在使用这些端口。然而,在调试时,明确指定一个简短的 worker 端口列表(例如 --worker-port-list=10000,10001,10002,10003,10004
)会很有用。请注意,这种做法会限制 worker 的数量,就像指定一个狭窄范围一样。
Head 节点#
除了前面部分指定的端口外,head 节点还需要打开更多端口。
--port
: Ray GCS 服务器的端口。head 节点在该端口上启动一个 GCS 服务器进行监听。默认值:6379。--ray-client-server-port
: Ray Client Server 的监听端口。默认值:10001。--redis-shard-ports
: 非主 Redis 分片端口的逗号分隔列表。默认值:随机值。--dashboard-grpc-port
: (已弃用) 不再使用。仅保留用于向后兼容。如果
--include-dashboard
为 true(默认值),则 head 节点必须打开--dashboard-port
。默认值:8265。
如果 --include-dashboard
为 true,但 head 节点上未打开 --dashboard-port
,您将无法访问仪表板,并且会重复收到以下信息
WARNING worker.py:1114 -- The agent on node <hostname of node that tried to run a task> failed with the following error:
Traceback (most recent call last):
File "/usr/local/lib/python3.8/dist-packages/grpc/aio/_call.py", line 285, in __await__
raise _create_rpc_error(self._cython_call._initial_metadata,
grpc.aio._call.AioRpcError: <AioRpcError of RPC that terminated with:
status = StatusCode.UNAVAILABLE
details = "failed to connect to all addresses"
debug_error_string = "{"description":"Failed to pick subchannel","file":"src/core/ext/filters/client_channel/client_channel.cc","file_line":4165,"referenced_errors":[{"description":"failed to connect to all addresses","file":"src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc","file_line":397,"grpc_status":14}]}"
如果您看到此错误,请检查 --dashboard-port
是否可通过 nc
、nmap
或您的浏览器访问。
$ nmap -sV --reason -p 8265 $HEAD_ADDRESS
Nmap scan report for compute04.berkeley.edu (123.456.78.910)
Host is up, received reset ttl 60 (0.00065s latency).
rDNS record for 123.456.78.910: compute04.berkeley.edu
PORT STATE SERVICE REASON VERSION
8265/tcp open http syn-ack ttl 60 aiohttp 3.7.2 (Python 3.8)
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
请注意,仪表板作为一个单独的子进程运行,它可能在后台悄无声息地崩溃,因此即使您之前检查过端口 8265,现在该端口也可能已关闭(原因很简单,就是上面没有服务在运行了)。这也意味着,如果在端口不可达时执行 ray stop
然后 ray start
,由于仪表板重启,端口可能会再次变为可达。
如果您不希望使用仪表板,请设置 --include-dashboard=false
。
TLS 认证#
您可以配置 Ray 在其 gRPC 通道上使用 TLS。这意味着连接到 Ray head 需要一组适当的凭据,并且各种进程(客户端、head、worker)之间交换的数据是加密的。
TLS 使用私钥和公钥进行加密和解密。所有者保密私钥,TLS 与对方共享公钥。这种模式确保只有预期的接收者才能读取消息。
证书颁发机构(CA)是受信任的第三方,用于认证公钥所有者的身份。CA 颁发的数字证书包含公钥本身、公钥所有者的身份以及证书的到期日期。请注意,如果公钥所有者不想从 CA 获取数字证书,他们可以使用 OpenSSL 等工具生成自签名证书。
要获取数字证书,公钥所有者必须生成证书签名请求(CSR)。CSR 包含有关公钥所有者和公钥本身的信息。Ray 需要额外的步骤来实现成功的 TLS 加密。
以下是使用自签名证书向静态 Kubernetes Ray 集群添加 TLS 认证的分步指南
步骤 1:为 CA 生成私钥和自签名证书#
openssl req -x509 \
-sha256 -days 3650 \
-nodes \
-newkey rsa:2048 \
-subj "/CN=*.ray.io/C=US/L=San Francisco" \
-keyout ca.key -out ca.crt
使用以下命令对私钥文件和自签名证书文件进行编码,然后将编码后的字符串粘贴到 secret.yaml 中。
cat ca.key | base64
cat ca.crt | base64
# 或者,此命令会自动编码并为 CA 密钥对创建 secret。.. code-block:: bash
kubectl create secret generic ca-tls –from-file=ca.crt=<path-to-ca.crt> –from-file=ca.key=<path-to-ca.key>
步骤 2:为 Ray head 和 workers 生成独立的私钥和自签名证书#
YAML 文件中有一个名为 tls
的 ConfigMap,其中包含两个 shell 脚本:gencert_head.sh
和 gencert_worker.sh
。这些脚本在每个部署的 initContainer 中生成 head 和 worker Pod 的私钥和自签名证书文件(tls.key
和 tls.crt
)。通过使用 initContainer,我们可以动态地将 POD_IP
添加到 [alt_names]
部分。
脚本执行以下步骤:首先,生成一个 2048 位 RSA 私钥并将其保存为 /etc/ray/tls/tls.key
。然后,使用 tls.key
文件和 csr.conf
配置文件生成证书签名请求 (CSR)。最后,使用证书颁发机构的 (ca.key and ca.crt
) 密钥对和 CSR (ca.csr
) 创建自签名证书 (tls.crt
)。
步骤 3:为 Ray head 和 worker 设置环境变量以启用 TLS#
您可以通过设置环境变量来启用 TLS。
RAY_USE_TLS
: 使用/不使用 TLS,值为 1 或 0。如果设置为 1,则必须设置以下环境变量。默认值:0。RAY_TLS_SERVER_CERT
:证书文件 (tls.crt)
的位置,Ray 将其提供给其他端点以实现相互认证。RAY_TLS_SERVER_KEY
:私钥文件 (tls.key)
的位置,它是向其他端点证明您是给定证书的授权用户的密码学手段。RAY_TLS_CA_CERT
:CA 证书文件 (ca.crt)
的位置,TLS 可以通过它判断端点的证书是否由正确的机构签名。
步骤 4:验证 TLS 认证#
# Log in to the worker Pod
kubectl exec -it ${WORKER_POD} -- bash
# Since the head Pod has the certificate of the full qualified DNS resolution for the Ray head service, the connection to the worker Pods
# is established successfully
ray health-check --address service-ray-head.default.svc.cluster.local:6379
# Since service-ray-head hasn't added to the alt_names section in the certificate, the connection fails and an error
# message similar to the following is displayed: "Peer name service-ray-head is not in peer certificate".
ray health-check --address service-ray-head:6379
# After you add `DNS.3 = service-ray-head` to the alt_names sections and deploy the YAML again, the connection is able to work.
启用 TLS 会由于相互认证和加密的额外开销而导致性能损失。测试表明,这种开销对于小型工作负载很大,而对于大型工作负载则相对较小。具体开销取决于您的工作负载性质。
Java 应用#
重要
对于多节点设置,您必须首先在命令行上运行 ray start
来启动机器上的 Ray 集群服务,然后才能在 Java 中调用 ray.init()
连接到集群服务。在单机上,您可以直接运行 ray.init()
而无需先运行 ray start
。它会同时启动 Ray 集群服务并连接到它们。
代码搜索路径#
如果您想在多节点集群中运行 Java 应用,必须在您的 driver 中指定代码搜索路径。代码搜索路径告诉 Ray 在启动 Java worker 时从哪里加载 jar 包。在运行代码之前,您必须将 jar 文件分发到 Ray 集群所有节点上的相同路径。
$ java -classpath <classpath> \
-Dray.address=<address> \
-Dray.job.code-search-path=/path/to/jars/ \
<classname> <args>
The /path/to/jars/
points to a directory which contains jars. Workers load all jars in the directory. You can also provide multiple directories for this parameter.
$ java -classpath <classpath> \
-Dray.address=<address> \
-Dray.job.code-search-path=/path/to/jars1:/path/to/jars2:/path/to/pys1:/path/to/pys2 \
<classname> <args>
/path/to/jars/
指向一个包含 jar 包的目录。Worker 会加载该目录中的所有 jar 包。您也可以为该参数提供多个目录。
如果您在单节点集群中运行 Java 应用,则无需配置代码搜索路径。
注意
有关更多信息,请参阅Driver 选项下的 ray.job.code-search-path
。
目前,在单机模式下运行 Java 应用时无法配置 Ray。如果需要配置 Ray,请先运行 ray start
启动 Ray 集群。
Driver 选项#
Java drivers 有一组有限的选项。这些选项不是用于配置 Ray 集群,而仅用于配置 driver。
Ray 使用 Typesafe Config 读取选项。有几种设置选项的方式
系统属性。您可以通过在 driver 命令行中添加
-Dkey=value
格式的选项,或在调用Ray.init()
之前调用System.setProperty("key", "value");
来配置系统属性。
注意
A HOCON 格式的配置文件。默认情况下,Ray 会尝试读取 classpath 根目录下的 ray.conf
文件。您可以通过设置系统属性 ray.config-file
为文件路径来自定义文件位置。
通过系统属性配置的选项优先级高于配置文件中配置的选项。
可用的 driver 选项列表
ray.address
如果 driver 连接到现有的 Ray 集群,则为集群地址。如果为空,Ray 会创建一个新的 Ray 集群。
类型:
String
默认值:空字符串。
ray.job.code-search-path
如果 driver 连接到现有的 Ray 集群,则为集群地址。如果为空,Ray 会创建一个新的 Ray 集群。
类型:
String
Java worker 加载代码的路径。目前,Ray 只支持目录。您可以指定一个或多个目录,用
:
分隔。如果您在单机模式或本地模式下运行 Java 应用,则无需配置代码搜索路径。如果指定了代码搜索路径,Ray 也使用它来加载 Python 代码。此参数对于跨语言编程是必需的。如果指定了代码搜索路径,则只能运行您能在代码搜索路径中找到的 Python 远程函数。
示例:
/path/to/jars1:/path/to/jars2:/path/to/pys1:/path/to/pys2
ray.job.namespace
如果 driver 连接到现有的 Ray 集群,则为集群地址。如果为空,Ray 会创建一个新的 Ray 集群。
此 job 的命名空间。Ray 使用它来实现 job 之间的隔离。不同命名空间中的 job 无法相互访问。如果未指定,Ray 会使用一个随机值。