使用 CLI 或 SDK 进行监控#

Ray 中的监控和调试功能可通过 CLI 或 SDK 使用。

CLI 命令 ray status#

您可以通过在主节点上运行 CLI 命令 ray status 来监控节点状态和资源使用情况。它会显示:

  • 节点状态:正在运行和正在向上或向下自动扩展的节点。正在运行的节点地址。关于待处理节点和失败节点的信息。

  • 资源使用情况:集群的 Ray 资源使用情况。例如,所有 Ray 任务和 Actor 请求的 CPU。使用的 GPU 数量。

以下是一个示例输出:

$ 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 status -v。这对于调查为什么特定节点无法自动缩减很有帮助。

Ray 状态 CLI 和 SDK#

提示

请通过 反馈表 提供有关使用 Ray 状态 API 的反馈!

使用 Ray 状态 API 通过 CLI 或 Python SDK(开发者 API)访问 Ray 的当前状态(快照)。

注意

此功能需要使用 pip install "ray[default]" 完全安装 Ray。此功能还需要仪表板组件可用。启动 Ray 集群时需要包含仪表板组件,这对于 ray startray.init() 来说是默认行为。

注意

状态 API CLI 命令是 稳定的,而 Python SDK 是 开发者 API。建议使用 CLI 而不是 Python SDK。

开始使用#

此示例使用以下脚本,该脚本运行两个任务并创建两个 Actor。

import ray
import time

ray.init(num_cpus=4)

@ray.remote
def task_running_300_seconds():
    time.sleep(300)

@ray.remote
class Actor:
    def __init__(self):
        pass

# Create 2 tasks
tasks = [task_running_300_seconds.remote() for _ in range(2)]

# Create 2 actors
actors = [Actor.remote() for _ in range(2)]

查看任务的汇总状态。如果命令没有立即返回输出,请重试命令。

ray summary tasks
======== Tasks Summary: 2022-07-22 08:54:38.332537 ========
Stats:
------------------------------------
total_actor_scheduled: 2
total_actor_tasks: 0
total_tasks: 2


Table (group by func_name):
------------------------------------
    FUNC_OR_CLASS_NAME        STATE_COUNTS    TYPE
0   task_running_300_seconds  RUNNING: 2      NORMAL_TASK
1   Actor.__init__            FINISHED: 2     ACTOR_CREATION_TASK
from ray.util.state import summarize_tasks
print(summarize_tasks())
{'cluster': {'summary': {'task_running_300_seconds': {'func_or_class_name': 'task_running_300_seconds', 'type': 'NORMAL_TASK', 'state_counts': {'RUNNING': 2}}, 'Actor.__init__': {'func_or_class_name': 'Actor.__init__', 'type': 'ACTOR_CREATION_TASK', 'state_counts': {'FINISHED': 2}}}, 'total_tasks': 2, 'total_actor_tasks': 0, 'total_actor_scheduled': 2, 'summary_by': 'func_name'}}

列出所有 Actor。

ray list actors
======== List: 2022-07-23 21:29:39.323925 ========
Stats:
------------------------------
Total: 2

Table:
------------------------------
    ACTOR_ID                          CLASS_NAME    NAME      PID  STATE
0  31405554844820381c2f0f8501000000  Actor                 96956  ALIVE
1  f36758a9f8871a9ca993b1d201000000  Actor                 96955  ALIVE
from ray.util.state import list_actors
print(list_actors())
[ActorState(actor_id='...', class_name='Actor', state='ALIVE', job_id='01000000', name='', node_id='...', pid=..., ray_namespace='...', serialized_runtime_env=None, required_resources=None, death_cause=None, is_detached=None, placement_group_id=None, repr_name=None), ActorState(actor_id='...', class_name='Actor', state='ALIVE', job_id='01000000', name='', node_id='...', pid=..., ray_namespace='...', serialized_runtime_env=None, required_resources=None, death_cause=None, is_detached=None, placement_group_id=None, repr_name=None)]

使用 get API 获取单个任务的状态。

# In this case, 31405554844820381c2f0f8501000000
ray get actors <ACTOR_ID>
---
actor_id: 31405554844820381c2f0f8501000000
class_name: Actor
death_cause: null
is_detached: false
name: ''
pid: 96956
resource_mapping: []
serialized_runtime_env: '{}'
state: ALIVE
from ray.util.state import get_actor
# In this case, 31405554844820381c2f0f8501000000
print(get_actor(id=<ACTOR_ID>))

通过 ray logs API 访问日志。

ray list actors
# In this case, ACTOR_ID is 31405554844820381c2f0f8501000000
ray logs actor --id <ACTOR_ID>
--- Log has been truncated to last 1000 lines. Use `--tail` flag to toggle. ---

:actor_name:Actor
Actor created
from ray.util.state import get_log

# In this case, ACTOR_ID is 31405554844820381c2f0f8501000000
for line in get_log(actor_id=<ACTOR_ID>):
    print(line)

关键概念#

Ray 状态 API 允许您通过 **summary**、**list** 和 **get** API 访问 **资源** 的 **状态**。它还支持 **logs** API 来访问日志。

  • states:相应资源的集群状态。状态包括不可变的元数据(例如,Actor 的名称)和可变状态(例如,Actor 的调度状态或 PID)。

  • resources:Ray 创建的资源。例如,Actor、任务、对象、放置组等。

  • summary:返回资源汇总视图的 API。

  • list:返回资源的每个单独实体的 API。

  • get:返回单个资源实体的详细信息的 API。

  • logs:用于访问 Actor、任务、Worker 或系统日志文件的日志的 API。

用户指南#

按类型获取实体状态的摘要#

返回给定 Ray 实体(对象、Actor、任务)的汇总信息。建议首先通过 summary API 开始监控状态。当您发现异常(例如,Actor 运行时间过长,任务长时间未调度)时,您可以使用 listget API 来获取单个异常实体的更多详细信息。

汇总所有 Actor

ray summary actors
from ray.util.state import summarize_actors
print(summarize_actors())
{'cluster': {'summary': {'Actor': {'class_name': 'Actor', 'state_counts': {'ALIVE': 2}}}, 'total_actors': 2, 'summary_by': 'class'}}

汇总所有任务

ray summary tasks
from ray.util.state import summarize_tasks
print(summarize_tasks())
{'cluster': {'summary': {'task_running_300_seconds': {'func_or_class_name': 'task_running_300_seconds', 'type': 'NORMAL_TASK', 'state_counts': {'RUNNING': 2}}, 'Actor.__init__': {'func_or_class_name': 'Actor.__init__', 'type': 'ACTOR_CREATION_TASK', 'state_counts': {'FINISHED': 2}}}, 'total_tasks': 2, 'total_actor_tasks': 0, 'total_actor_scheduled': 2, 'summary_by': 'func_name'}}

汇总所有对象

注意

默认情况下,对象按调用点汇总。但是,调用点默认不被 Ray 记录。要获取调用点信息,请在启动 Ray 集群时设置环境变量 RAY_record_ref_creation_sites=1

RAY_record_ref_creation_sites=1 ray start --head
ray summary objects
from ray.util.state import summarize_objects
print(summarize_objects())
{'cluster': {'summary': {'disabled': {'total_objects': 6, 'total_size_mb': 0.0, 'total_num_workers': 3, 'total_num_nodes': 1, 'task_state_counts': {'SUBMITTED_TO_WORKER': 2, 'FINISHED': 2, 'NIL': 2}, 'ref_type_counts': {'LOCAL_REFERENCE': 2, 'ACTOR_HANDLE': 4}}}, 'total_objects': 6, 'total_size_mb': 0.0, 'callsite_enabled': False, 'summary_by': 'callsite'}}

有关 ray summary 命令的更多详细信息,请参阅 状态 CLI 参考

列出特定类型的所有实体状态#

获取资源列表。可能的资源包括:

列出所有节点

ray list nodes
from ray.util.state import list_nodes
list_nodes()

列出所有放置组

ray list placement-groups
from ray.util.state import list_placement_groups
list_placement_groups()

列出本地引用的由进程创建的对象

提示

您可以使用一个或多个过滤器来列出资源:使用 --filter-f

ray list objects -f pid=<PID> -f reference_type=LOCAL_REFERENCE
from ray.util.state import list_objects
list_objects(filters=[("pid", "=", 1234), ("reference_type", "=", "LOCAL_REFERENCE")])

列出活动的 Actor

ray list actors -f state=ALIVE
from ray.util.state import list_actors
list_actors(filters=[("state", "=", "ALIVE")])

列出正在运行的任务

ray list tasks -f state=RUNNING
from ray.util.state import list_tasks
list_tasks(filters=[("state", "=", "RUNNING")])

列出未运行的任务

ray list tasks -f state!=RUNNING
from ray.util.state import list_tasks
list_tasks(filters=[("state", "!=", "RUNNING")])

列出名称为 func 的正在运行的任务

ray list tasks -f state=RUNNING -f name="task_running_300_seconds()"
from ray.util.state import list_tasks
list_tasks(filters=[("state", "=", "RUNNING"), ("name", "=", "task_running_300_seconds()")])

列出更详细的任务

提示

当指定 --detail 时,API 可以查询更多数据源以获取详细状态信息。

ray list tasks --detail
from ray.util.state import list_tasks
list_tasks(detail=True)

有关 ray list 命令的更多详细信息,请参阅 状态 CLI 参考

获取特定实体(任务、Actor 等)的状态#

获取任务的状态

ray get tasks <TASK_ID>
from ray.util.state import get_task
get_task(id=<TASK_ID>)

获取节点的状态

ray get nodes <NODE_ID>
from ray.util.state import get_node
get_node(id=<NODE_ID>)

有关 ray get 命令的更多详细信息,请参阅 状态 CLI 参考

获取特定实体(任务、Actor 等)的日志#

状态 API 还允许您访问 Ray 日志。请注意,您无法从已失效的节点访问日志。默认情况下,API 会打印来自主节点的日志。

从集群中的主节点获取所有可检索的日志文件名

ray logs cluster
# You could get the node ID / node IP from `ray list nodes`
from ray.util.state import list_logs
# `ray logs` by default print logs from a head node.
# To list the same logs, you should provide the head node ID.
# Get the node ID / node IP from `ray list nodes`
list_logs(node_id=<HEAD_NODE_ID>)

从节点获取特定日志文件

# Get the node ID / node IP from `ray list nodes`
ray logs cluster gcs_server.out --node-id <NODE_ID>
# `ray logs cluster` is alias to `ray logs` when querying with globs.
ray logs gcs_server.out --node-id <NODE_ID>
from ray.util.state import get_log

# Node IP can be retrieved from list_nodes() or ray.nodes()
for line in get_log(filename="gcs_server.out", node_id=<NODE_ID>):
    print(line)

从节点流式传输日志文件

# Get the node ID / node IP from `ray list nodes`
ray logs raylet.out --node-ip <NODE_IP> --follow
# Or,
ray logs cluster raylet.out --node-ip <NODE_IP> --follow
from ray.util.state import get_log

# Retrieve the Node IP from list_nodes() or ray.nodes()
# The loop blocks with `follow=True`
for line in get_log(filename="raylet.out", node_ip=<NODE_IP>, follow=True):
    print(line)

通过 Actor ID 流式传输 Actor 的日志

ray logs actor --id=<ACTOR_ID> --follow
from ray.util.state import get_log

# Get the Actor's ID from the output of `ray list actors`.
# The loop blocks with `follow=True`
for line in get_log(actor_id=<ACTOR_ID>, follow=True):
    print(line)

流式传输 PID 的日志

ray logs worker --pid=<PID> --follow
from ray.util.state import get_log

# Retrieve the node IP from list_nodes() or ray.nodes()
# get the PID of the worker running the Actor easily when output
# of worker is directed to the driver (default)
# The loop blocks with `follow=True`
for line in get_log(pid=<PID>, node_ip=<NODE_IP>, follow=True):
    print(line)

有关 ray logs 命令的更多详细信息,请参阅 状态 CLI 参考

故障语义#

状态 API 不保证始终返回一致或完整的集群快照。默认情况下,所有 Python SDK 在 API 输出缺失时都会引发异常。CLI 返回部分结果并提供警告消息。以下是 API 输出可能缺失的情况。

查询失败

状态 API 查询“数据源”(例如,GCS、raylet 等)以获取并构建集群快照。然而,数据源有时不可用(例如,源已关闭或过载)。在这种情况下,API 会返回集群的部分(不完整)快照,并通过警告消息告知用户输出不完整。所有警告都通过 Python 的 warnings 库打印,并且可以被抑制。

数据截断

当返回的实体数量(行数)过大(> 100K)时,状态 API 会截断输出数据以确保系统稳定性(发生这种情况时,无法选择截断的数据)。发生截断时,将通过 Python 的 warnings 模块通知。

垃圾回收的资源

根据资源的生命周期,某些“已完成”的资源可能无法通过 API 访问,因为它们已被垃圾回收。

注意

不要依赖此 API 来获取已完成资源的正确信息。例如,Ray 会定期垃圾回收 DEAD 状态的 Actor 数据以减少内存使用。或者,当任务的 lineage 超出范围时,它会清理 FINISHED 状态的任务。

API 参考#

从集群外部使用 Ray CLI 工具#

这些 CLI 命令必须在 Ray 集群的节点上运行。以下是有关如何从 Ray 集群外部的机器执行这些命令的示例。

使用 ray exec 在集群上执行命令

$ ray exec <cluster config file> "ray status"

使用 kubectl exec 和配置的 RayCluster 名称在集群上执行命令。Ray 使用针对 Ray 主 Pod 的 Service 来在集群上执行 CLI 命令。

# First, find the name of the Ray head service.
$ kubectl get pod | grep <RayCluster name>-head
# NAME                                             READY   STATUS    RESTARTS   AGE
# <RayCluster name>-head-xxxxx                     2/2     Running   0          XXs

# Then, use the name of the Ray head service to run `ray status`.
$ kubectl exec <RayCluster name>-head-xxxxx -- ray status