Ray Serve 生产环境部署到 VM:使用serve deploy与 Serve Config 的完整指南
【免费下载链接】rayRay is an AI compute engine. Ray consists of a core distributed runtime and a set of AI Libraries for accelerating ML workloads.项目地址: https://gitcode.com/gh_mirrors/ra/ray
导读
本文基于 Ray 开源仓库的 deploy-vm.md 文档,系统讲解如何将 Ray Serve 应用以声明式配置的方式部署到本地单节点或由 Ray Cluster Launcher 启动的远程多节点 VM 集群上。读完本文,你将掌握serve deploy/serve config/serve status三个核心 CLI 命令的完整用法、Serve Config 文件的全部字段语义、通过--address与RAY_DASHBOARD_ADDRESS定位远程集群的方法,以及生产环境下安全更新应用(含user_config热更新与整集群替换)的工程实践。
一、在 VM 上部署 Serve 应用的整体思路
在 VM 场景下部署 Ray Serve 应用,核心流程可以概括为三步:编写应用代码与配置文件 → 启动 Ray 集群 → 通过serve deploy将配置以 HTTP 方式下发到集群。Ray Serve 会以声明式的方式持续收敛集群状态,使线上运行的部署与配置文件描述的目标状态保持一致。
这种部署方式与开发阶段的serve run有本质区别:serve run通常用于本地迭代调试,而serve deploy面向的是长期运行的 Ray 集群,无论该集群是本地单节点,还是由 Ray Cluster Launcher 启动的远程多节点集群,用法完全一致。
本文的示例沿用生产指南中的 Text ML 应用(config.md),其应用代码与配置文件组织如下:
$ ls text_ml.py serve_config.yaml其中text_ml.py定义了一个由Translator(翻译)与Summarizer(摘要)两个部署组成的应用图,配置示例源码可参考 text_ml.py。
二、快速开始:部署到本地集群
1. 启动 Ray 集群
ray start --head会在当前机器上启动一个长期存活的本地 Ray 集群(head 节点):
$ ray start --head ...如果需要停止集群,使用ray stop命令。
2. 部署配置文件
$ serve deploy serve_config.yaml 2022-06-20 17:26:31,106 SUCC scripts.py:139 -- Sent deploy request successfully! * Use `serve status` to check deployments' statuses. * Use `serve config` to see the running app's config.3. "Sent deploy request successfully!" 的真实含义
这条成功信息并不等于应用已经上线。它的准确含义是:
- Ray 集群已成功接收你的配置文件;
- 如果集群上还没有 Serve 应用,它将启动一个新的 Serve 应用;
- 该 Serve 应用会按照配置文件中覆盖的参数,把部署图中的各部署下发到集群。
整个部署过程是异步的:Ray 集群会不断尝试让自身状态收敛到配置文件描述的目标状态(包括拉起 replica、恢复失败实例等)。因此必须使用 serve status 确认应用是否真正就绪,而不能只依赖这条提示。
从源码实现看,serve deploy实际上是通过 Ray 集群的 dashboard HTTP 接口把配置提交给 ServeController,命令对应的实现位于 python/ray/serve/scripts.py(deploy命令,成功提示信息在"Sent deploy request successfully.\n "附近)。
三、部署到远程集群
1. 指定 dashboard 地址
默认情况下serve deploy认为集群运行在本地。当目标集群在远程时,通过可选参数--address(简写-a)指定远程 Ray 集群的 dashboard 地址,格式为:
[RAY_CLUSTER_URI]:[DASHBOARD_PORT]例如本地集群由ray start --head启动时,地址为http://127.0.0.1:8265,可以显式部署到该地址:
$ serve deploy config_file.yaml -a http://127.0.0.1:8265Ray dashboard 的默认端口是8265。如需修改,在ray start时使用--dashboard-port参数:
$ ray start --head --dashboard-port=<your-port>2. 远程部署时依赖必须可达
:::{note} 当在远程集群上部署时,必须确保import_path指向的应用代码在集群上可被导入。如果代码或依赖不在集群环境内,应通过runtime_env打包。参见 handling-dependencies.md。 :::
这里特别提醒:serve deploy的配置是通过 HTTP 传输到集群的,但配置里引用的 Python 代码并不会随配置一起传输。集群上必须能访问到import_path对应的模块——这正是runtime_env存在的意义。需要打包pip依赖或工作目录时,在应用配置中声明runtime_env即可(详见第五节)。
3. 环境变量 RAY_DASHBOARD_ADDRESS:统一指定集群地址
Serve CLI 存在两套默认地址逻辑:
serve start与serve run默认使用本地集群的Ray head 节点地址;如果设置了RAY_ADDRESS环境变量,则优先使用该值。- 除上述两个命令外的所有 Serve CLI 命令(包括
serve deploy、serve config、serve status)默认使用本地集群的Ray dashboard 地址;如果设置了RAY_DASHBOARD_ADDRESS环境变量,则优先使用该值。
因此,在部署脚本或 CI 流水线中,最稳妥的做法是把目标集群地址写入RAY_DASHBOARD_ADDRESS,这样所有管理命令都会自动指向同一集群,避免每次敲-a。查看、设置、清除该变量的命令:
$ echo $RAY_DASHBOARD_ADDRESS $ export RAY_DASHBOARD_ADDRESS=[YOUR VALUE] $ unset RAY_DASHBOARD_ADDRESS在提交任何部署命令前,建议先echo检查该变量,确认当前指向的是你期望的集群地址,防止把配置误发到错误的集群。
从源码看,RAY_DASHBOARD_ADDRESS的默认回退逻辑正是定义在 python/ray/serve/scripts.py 中(如default=os.environ.get("RAY_DASHBOARD_ADDRESS", "http://localhost:8265")),所有需要访问 dashboard 的 CLI 命令共享这一机制。
四、Serve Config 文件:声明式部署的核心
serve deploy接受一个 YAML 格式的 Serve Config 文件。该文件允许你配置与 Serve 相关的所有内容——从系统级组件(如 proxy)到应用级选项(如每个部署的参数)。它最大的价值在于:修改单个部署参数后重新部署即可动态更新线上应用,无需重启或重建应用。完整的格式与字段说明见 config.md。
配置文件的整体骨架如下:
proxy_location: ... http_options: host: ... port: ... request_timeout_s: ... keep_alive_timeout_s: ... grpc_options: port: ... grpc_servicer_functions: ... request_timeout_s: ... logging_config: log_level: ... logs_dir: ... encoding: ... enable_access_log: ... applications: - name: ... route_prefix: ... import_path: ... runtime_env: ... external_scaler_enabled: ... deployments: - name: ... num_replicas: ... ... - name: ... ...1. proxy_location:代理部署位置
- EveryNode(默认):在每个至少运行一个 replica actor 的节点上部署代理;
- HeadOnly:仅在 head 节点运行单个代理;
- Disabled:完全不运行代理。仅在通过 DeploymentHandle 调用应用时使用。
此外,代理的健康检查与生命周期行为可通过以下环境变量调整:
RAY_SERVE_PROXY_HEALTH_CHECK_PERIOD_S:控制器检查各代理健康状态的间隔(秒),默认10.0;RAY_SERVE_PROXY_HEALTH_CHECK_TIMEOUT_S:健康检查响应超时(秒),默认10.0。连续 3 次失败将被判为不健康并重启;RAY_SERVE_PROXY_READY_CHECK_TIMEOUT_S:启动时等待代理就绪的超时(秒),默认5.0;RAY_SERVE_PROXY_MIN_DRAINING_PERIOD_S:代理终止前停留在 draining 状态的最短时间(秒),默认30.0。draining 期间代理会主动通过健康检查失败来让负载均衡器停止调度新流量,同时已有请求继续完成。
2. http_options:HTTP 配置
注意:HTTP 配置对 Ray 集群是全局的,运行时不可动态更新。
host:HTTP 代理监听的主机 IP,可省略,默认0.0.0.0(公开暴露部署)。若使用 Kubernetes,必须设为0.0.0.0才能对外暴露;port:HTTP 代理监听端口,可省略,默认8000;request_timeout_s:请求的端到端超时,超时后请求会被终止并在另一 replica 上重试。默认无超时;keep_alive_timeout_s:HTTP 代理的 keep-alive 超时。
3. grpc_options:gRPC 配置
同样为集群级全局配置,运行时不可更新:
port:gRPC 代理监听端口,默认9000;grpc_servicer_functions:gRPCadd_servicer_to_server函数的导入路径列表,须在 Serve 运行环境中可导入。默认为空列表(不启动 gRPC 服务);request_timeout_s:请求端到端超时,默认无超时。
4. logging_config:日志配置
logging_config是全局配置,可统一配置 controller、proxy 与 replica 的日志。也可以为应用或部署级别单独设置logging_config,其优先级高于全局配置。常用字段包括log_level、logs_dir、encoding(如TEXT或JSON)与enable_access_log。更完整的说明见 monitoring.md 中的日志章节。
5. applications:应用级配置
每个application的字段如下:
name:应用名称,必须唯一(serve build会自动生成);route_prefix:该应用对外提供 HTTP 服务的路由前缀,默认/,必须唯一;import_path:顶层 Serve 部署的导入路径(即传给serve run的路径)。最简配置文件可以只含import_path;runtime_env:应用运行环境,用于打包pip包等依赖。若指定了runtime_env,import_path必须在该环境内可用;其working_dir与py_modules只能使用远程 URI,不能使用本地 zip 或目录;external_scaler_enabled:启用外部扩缩容 REST API。启用后,该应用内的所有部署都不能再使用内置autoscaling_config。默认False;deployments(可选):覆盖代码中@serve.deployment设置的部署选项列表,每项必须包含与代码匹配的name。省略时按代码中的参数启动全部部署;args:传给应用构建函数(application builder)的参数。
6. 示例配置
下面是为 Text ML 应用编写的完整示例(即本文第一节部署所用的serve_config.yaml):
proxy_location: EveryNode http_options: host: 0.0.0.0 port: 8000 applications: - name: default route_prefix: / import_path: text_ml:app runtime_env: pip: - torch - transformers deployments: - name: Translator num_replicas: 1 user_config: language: french - name: Summarizer num_replicas: 1需要指出的是,deployments列表中的每一项都是可选的。上例即使删掉整个Summarizer条目,配置文件依然有效——部署时Summarizer仍会按照代码中@serve.deployment装饰器里的配置被部署。
五、使用serve build自动生成配置
手写配置文件容易出错,Ray 提供了serve build命令,从应用导入路径自动生成包含全部部署及其参数的配置文件,随后再按需微调参数即可用于生产:
$ ls text_ml.py $ serve build text_ml:app -o serve_config.yaml $ ls text_ml.py serve_config.yaml生成的serve_config.yaml内容如下:
proxy_location: EveryNode http_options: host: 0.0.0.0 port: 8000 grpc_options: port: 9000 grpc_servicer_functions: [] logging_config: encoding: TEXT log_level: INFO logs_dir: null enable_access_log: true applications: - name: default route_prefix: / import_path: text_ml:app runtime_env: {} deployments: - name: Translator num_replicas: 1 user_config: language: french - name: Summarizer使用注意:
runtime_env在serve build生成时始终为空,必须手动填写。如果torch、transformers未在集群全局环境中安装,应把它们加入runtime_env.pip;- 生成的配置会自动包含默认的 HTTP 与 gRPC 选项,可按需修改这些参数。
六、部署后的巡检:serve config 与 serve status
serve deploy是异步的,因此部署后必须用 CLI 巡检真实状态。完整的巡检文档见 monitoring.md。与部署一样,针对远程集群,这两个命令同样支持--address/-a参数。
1. serve config:查看目标状态
serve config返回集群最近一次收到的配置文件——也就是 Serve 应用的目标状态(goal state)。Ray 集群会持续向该状态收敛(部署部署、恢复失败的 replica 等)。部署上面的示例配置后:
$ serve config name: default route_prefix: / import_path: text_ml:app runtime_env: pip: - torch - transformers deployments: - name: Translator num_replicas: 1 user_config: language: french - name: Summarizer num_replicas: 12. serve status:查看当前状态
serve status报告 proxy 与 applications 两部分的当前状态:
proxies:每个代理按所在节点的 node ID 标识,状态包括:
STARTING:正在启动,尚不能处理请求;HEALTHY:正常服务请求;UNHEALTHY:健康检查失败,将被杀死并在该节点重建;DRAINING:健康但已对新请求关闭,可能仍有请求在处理;DRAINED:已关闭新请求,且无未完成请求。
applications:每个应用包含四个字段:
status:应用总状态,取值有NOT_STARTED(集群上未部署任何应用)、DEPLOYING(正在执行serve deploy请求)、RUNNING(稳态,正维护最新目标状态)、DEPLOY_FAILED(最近一次部署失败);message:当前状态的上下文说明;deployment_timestamp:Serve 收到最近一次serve deploy请求的 UNIX 时间戳(基于 ServeController 本地时钟);deployments:各部署的状态列表,每个部署含:status:UPDATING(正在向目标状态更新)、HEALTHY(健康且 replica 数达标)、UNHEALTHY(更新后变不健康,可能因扩容失败、健康检查失败或系统/机器错误)、DEPLOY_FAILED(启动或更新失败,常见于构造函数出错)、UPSCALING/DOWNSCALING(启用自动扩缩容时的扩缩状态);replica_states:各 replica 状态及数量,取值STARTING、UPDATING(正在执行reconfigure)、RECOVERING、RUNNING、STOPPING;message:上下文说明。
示例输出:
$ serve status proxies: cef533a072b0f03bf92a6b98cb4eb9153b7b7c7b7f15954feb2f38ec: HEALTHY applications: default: status: RUNNING message: '' last_deployed_time_s: 1694041157.2211847 deployments: Translator: status: HEALTHY replica_states: RUNNING: 1 message: '' Summarizer: status: HEALTHY replica_states: RUNNING: 1 message: ''在 Python 代码中,也可以通过serve.status()API 获取同样的信息(以 dataclass 形式返回),便于在驱动脚本或部署内部做自动化巡检。
七、更新线上应用:轻量更新、user_config 热更新与代码更新
serve deploy是幂等的:应用配置永远收敛到(并遵守)最近一次成功部署的配置,无论此前部署过什么。因此更新应用的方式就是修改配置文件后重新serve deploy。更完整的说明见 inplace-updates.md。
1. 轻量配置更新:不重启 replica
以下部署参数的修改属于轻量更新,不会拆除并重启该部署的 replica,因此停机时间更短:
num_replicasautoscaling_configuser_configmax_ongoing_requestsgraceful_shutdown_timeout_sgraceful_shutdown_wait_loop_shealth_check_period_shealth_check_timeout_s
2. user_config:不重启即可动态变更
user_config可接受任意 JSON 可序列化对象(字典、列表、字符串等),Serve 会将其应用到所有运行中与未来的 replica 上,且不会重启 replica。利用这一特性可以:
- 动态调整模型权重与版本,无需重启集群;
- 调整模型组合图的流量切分比例;
- 配置任意功能开关、A/B 测试与超参数。
启用该特性只需在部署类中实现reconfigure方法,它接收 JSON 可序列化对象作为唯一参数:
@serve.deployment class Model: def reconfigure(self, config: Dict[str, Any]): self.threshold = config["threshold"]如果创建部署时(装饰器或 Serve Config 中)设置了user_config,Serve 会在__init__之后立即调用reconfigure并传入该配置;之后修改配置文件中的user_config并重新serve deploy同样会触发该方法。
对应 YAML:
... deployments: - name: Model user_config: threshold: 1.5实战演练:沿用 Text ML 应用。先启动集群并部署(必要时先ray stop清理旧集群):
$ ray start --head $ serve deploy serve_config.yaml向应用发送翻译请求后,将Translator的user_config.language从french改为german:
applications: - name: default route_prefix: / import_path: text_ml:app runtime_env: pip: - torch - transformers deployments: - name: Translator num_replicas: 1 user_config: language: german不停止集群,直接重新部署:
$ serve deploy serve_config.yaml然后通过serve status等待应用状态回到RUNNING,再发送一次请求——返回文本已由法语变为德语。整个过程 replica 未被重启,翻译服务几乎无缝切换。
3. 代码更新:必须重启 replica
以下值的变更会触发整个部署的 replica 全部重启:
ray_actor_optionsplacement_group_bundlesplacement_group_strategy
以下应用级配置的变更同样视为代码更新,应用中所有部署都会被重启:
import_pathruntime_env
:::{warning} 虽然在技术上可以通过更换import_path与runtime_env直接部署一个全新的部署图来更新应用,但这不推荐用于生产环境。
生产环境大规模代码更新的最佳实践是:启动一个新的 Ray 集群 → 用serve deploy将新代码部署到新集群 → 部署完成后把流量从旧集群切换到新集群。这也是 "Deploy on VM" 指南中关于重大更新(如runtime_env变更)的官方建议:先起新集群、更新配置并部署,待新部署完成后切换流量。 :::
八、生产部署检查清单
综合以上内容,整理一份可直接落地的部署检查清单:
- 应用代码可达:确认
import_path指向的模块在目标集群(每个节点)上可导入;远程部署时优先通过runtime_env的working_dir/pip打包依赖,注意runtime_env的working_dir与py_modules仅支持远程 URI; - 地址确认:检查
RAY_DASHBOARD_ADDRESS是否指向预期集群;远程部署时用--address显式指定[RAY_CLUSTER_URI]:[DASHBOARD_PORT]; - 配置生成与校验:用
serve build从代码自动生成配置,再手动补充runtime_env、调整num_replicas、user_config等参数; - 部署后巡检:
serve deploy成功后使用serve config核对目标状态、serve status等待所有部署进入HEALTHY、应用进入RUNNING; - 更新策略:参数级变更走轻量更新(不重启 replica),
user_config用于运行时动态调参;代码级变更(import_path/runtime_env/ray_actor_options等)走"新集群 + 切流量"策略; - 集群生命周期:本地测试用
ray start --head/ray stop管理;生产环境用 Ray Cluster Launcher 维护远程集群。
九、深入阅读
- 配置文件完整格式与字段语义:production-guide/config.md
- 在线更新应用的细节:advanced-guides/inplace-updates.md
- 巡检与监控(
serve config/serve status、日志、指标):monitoring.md - 远程集群的启动与管理:cluster/vms/getting-started.rst
- 依赖与 runtime_env 处理:production-guide/handling-dependencies.md
- CLI 命令源码实现:python/ray/serve/scripts.py
【免费下载链接】rayRay is an AI compute engine. Ray consists of a core distributed runtime and a set of AI Libraries for accelerating ML workloads.项目地址: https://gitcode.com/gh_mirrors/ra/ray
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考