拓冰建站拓冰建站
首页 / 资讯中心 / 正文

KubeRay RayService 故障排查指南:从 Operator 日志到 Serve 应用状态的完整排障路径

人工智能分布式训练强化学习任务调度模型推理服务【免费下载链接】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点击查看免费下载RayService 是 KubeRay 为 Ray Serve 提供的 Kubernetes 自定义资源CRD创建 RayService 时KubeRay Operator 会先创建对应的 RayCluster待集群就绪后再向 dashboard agent 提交请求将serveConfigV2中声明的 Ray Serve 应用部署上去。因此排障链条横跨「控制面KubeRay Operator— 数据面Ray Serve 脚本与配置」两层一旦问题出在数据面定位难度会明显上升。本文以 doc/source/cluster/kubernetes/troubleshooting/rayservice-troubleshooting.md 为骨架系统讲解 5 类可观测手段和 11 类高频故障的定位与修复方法读完即可建立一套从日志到状态、从配置到网络的完整排障流程。排障前需要理解RayService 的部署链路在动手排障前先明确 RayService 的正常工作链路详见 RayService 部署指南KubeRay Operator 根据spec.rayClusterConfig创建 RayClusterhead Pod 启动并就绪后Operator 向 head 的 dashboard agent 端口52365发送PUT /api/serve/applications/请求创建spec.serveConfigV2声明的 Serve 应用Operator 周期性通过GET /api/serve/applications/拉取应用状态写入 RayService CR 的status中。理解这条链路后你会发现几乎所有故障都可以归入三类配置错误Serve 脚本、serveConfigV2、import_path、依赖缺失、请求链路故障网络策略、dashboard agent 未就绪/未运行、资源与状态机问题资源不足触发重启循环、升级冲突、Initializing 卡死。下文先讲通用观测手段再逐一拆解具体故障。观测手段五类定位入口手段 1查看 KubeRay Operator 日志Operator 日志是定位控制面行为的第一手资料尤其适合确认「Operator 是否发起了请求、因为什么原因重启了集群」kubectl logs $KUBERAY_OPERATOR_POD -n $YOUR_NAMESPACE | tee operator-log将输出重定向到operator-log文件后即可在文件内检索error、Restart RayCluster等关键词。Operator 日志中的典型信息包括Serve 应用创建请求的失败原因、触发 RayCluster 重启的具体理由例如 Issue 8 中的serviceUnhealthySecondThreshold超时以及AvailableWorkerReplicas与DesiredWorkerReplicas的对比。手段 2检查 RayService CR 的状态与事件RayService 的status与events记录了 Operator 视角下的应用状态kubectl describe rayservice $RAYSERVICE_NAME -n $YOUR_NAMESPACE重点关注Status.ActiveServiceStatus.ApplicationStatuses每个 Serve 应用及其部署的健康状态RUNNING/HEALTHY/UPDATINGConditions例如ReadyTrue表示 Serve 端点数量大于 0可对外提供服务UpgradeInProgress用于标识是否存在待切换的新集群EventsOperator 发出的事件如 Issue 11 的超时 Warning 事件。手段 3检查 head 与 worker Pod 内的 Serve 日志Serve 的系统级日志ServeController、HTTP Proxy、访问日志和用户日志都落盘在 Pod 内kubectl exec -it $RAY_POD -n $YOUR_NAMESPACE -- bash # 检查 /tmp/ray/session_latest/logs/serve/ 下的日志/tmp/ray/session_latest/logs/serve/目录是 Ray Serve 的标准日志落盘位置相关说明见 Ray Serve 日志 与 Ray 日志配置。此外head Pod 上的/tmp/ray/session_latest/logs/还包含dashboard.log与dashboard_agent.log分别对应 dashboard 与 dashboard agent 进程的运行状况是排查 Issue 5、Issue 7 的关键。手段 4通过 Ray Dashboard 观察 Serve 应用将 head Pod 的 dashboard 端口转发到本地后可在浏览器中直接查看 Serve 页面kubectl port-forward $RAY_POD -n $YOUR_NAMESPACE 8265:8265 # 浏览器访问 $YOUR_IP:8265进入 Serve 页面Serve 页面会展示 Controller status、Proxy status、Application status 三个关键健康标签以及每个应用/部署的RUNNING、HEALTHY状态、副本数与最后部署时间适合快速建立全局视图。更详细的 Dashboard 观测说明见 Serve 视图文档。也可以直接转发 RayService 管理的 head 服务来固定访问入口kubectl port-forward svc/rayservice-sample-head-svc 8265:8265。手段 5使用 Ray State CLI 检查 Actor 状态在 head Pod 内使用 Ray State CLI 可以绕过 Kubernetes 层直接查看 Serve 各组件ServeController、ServeReplica、ProxyActor的运行情况# 登录 head Pod export HEAD_POD$(kubectl get pods --selectorray.io/node-typehead -o custom-columnsPOD:metadata.name --no-headers) kubectl exec -it $HEAD_POD -- ray summary actors # [示例输出] # Actors Summary: 2023-07-11 17:58:24.625032 # Stats: # ------------------------------------ # total_actors: 14 # # Table (group by class): # ------------------------------------ # CLASS_NAME STATE_COUNTS # 0 ServeController ALIVE: 1 # 1 ServeReplica:fruit_app_OrangeStand ALIVE: 1 # 2 ProxyActor ALIVE: 3 # 4 ServeReplica:math_app_Multiplier ALIVE: 1 # 5 ServeReplica:math_app_create_order ALIVE: 1 # 7 ServeReplica:fruit_app_FruitMarket ALIVE: 1 # 8 ServeReplica:math_app_Adder ALIVE: 1 # 9 ServeReplica:math_app_Router ALIVE: 1 # 10 ServeReplica:fruit_app_MangoStand ALIVE: 1 # 11 ServeReplica:fruit_app_PearStand ALIVE: 1ray summary actors的输出直接反映 Serve 控制面组件的存活情况如果某个ServeReplica缺失或处于非 ALIVE 状态说明对应部署的副本未能正常拉起可以据此顺藤摸瓜去查 Pod 日志或资源状态。Ray State CLI 的完整用法见 Ray State CLI 参考。常见问题详解Issue 1Ray Serve 脚本本身有误serveConfigV2中的应用逻辑部署图、路由、请求处理函数属于数据面KubeRay 与 Ray Serve 都不会在提交阶段发现脚本层面的语法或逻辑错误错误通常要等到应用状态变为UNHEALTHY或副本反复启动失败时才暴露。建议在把脚本部署到 RayService 之前先在本机或独立 RayCluster 中按 Serve 开发工作流 完成本地验证确认import_path指向的应用对象能够成功构建。只有本地验证通过后再进入 KubeRay 部署才能把变量隔离在数据面之外。Issue 2serveConfigV2配置格式错误RayService CR 将serveConfigV2声明为 YAML 多行字符串目的是获得书写灵活性但代价是没有严格的类型检查——字段名拼写、命名风格错误都不会在提交时被拒绝而是延迟到运行时才暴露。排障要点参照 Ray Serve API 文档 中多应用 APIPUT /api/serve/applications/的 schema 核对字段命名风格与serveConfig不同serveConfigV2遵循 snake_case。例如单应用配置中的numReplicas在多应用配置中必须写作num_replicas。类似的还有maxReplicasPerNode→max_replicas_per_node、userConfig→user_config。从源码看多应用配置的结构定义在 python/ray/serve/schema.py 中ServeApplicationSchemaL783描述单个应用的name、import_path、route_prefix、runtime_env、deployments等字段ServeDeploySchemaL1087则通过applications: List[ServeApplicationSchema]L1129组织多应用列表。排查配置时可以对照这两个类的字段定义逐项核对。Issue 3Ray 镜像缺少应用所需依赖Serve 应用尤其是模型推理类应用往往需要镜像之外的 Python 依赖两种解决途径自建 Ray 镜像把依赖固化进镜像如在 Dockerfile 中pip install适用于依赖稳定、需要频繁部署的场景通过runtime_env指定在serveConfigV2中声明依赖由 Ray 在运行时安装灵活但会增加首次部署时间。例如 MobileNet 示例中starlette.requests.form()需要python-multipart而官方镜像rayproject/ray:x.y.z并未预装该包因此必须在 runtime_env 中补充声明serveConfigV2: | applications: - name: mobilenet import_path: mobilenet.mobilenet:app runtime_env: working_dir: https://github.com/ray-project/serve_config_examples/archive/b393e77bbd6aba0881e3d94c05f968f05a387b96.zip pip: [python-multipart0.0.6]依赖缺失的典型症状是副本反复CrashLoopBackOff应用状态长时间停留在UPDATING或UNHEALTHY此时结合手段 3 查看 replica 日志中的ModuleNotFoundError即可确认。Issue 4import_path写法错误import_path的格式为模块路径:应用变量名其语义可以拆解为三段。以 MobileNet 示例为例serveConfigV2: | applications: - name: mobilenet import_path: mobilenet.mobilenet:app runtime_env: working_dir: https://github.com/ray-project/serve_config_examples/archive/b393e77bbd6aba0881e3d94c05f968f05a387b96.zip pip: [python-multipart0.0.6]其中mobilenet.mobilenet:app的含义是第一个mobilenetworking_dir中应用的根目录名第二个mobilenet该目录下的 Python 文件名即mobilenet/mobilenet.pyappPython 文件中代表 Ray Serve 应用的变量名通常通过app FruitStandDeployment.bind(...)或deployment_graph构建。任何一段对不上目录名、文件名、变量名都会导致应用在导入阶段失败。排障时建议先在本地按 Issue 1 的方式验证import_path可导入再提交到 RayService。import_path字段的完整格式说明见 ServeApplicationSchema.import_path 的文档条目。Issue 5创建/更新 Serve 应用失败KubeRay Operator 在 head Pod 就绪后立即提交PUT /api/serve/applications/请求但dashboard、dashboard agent 与 GCS 需要在 head Pod 就绪后再花几秒完成启动因此请求在最初几次失败是正常现象。错误信息 1connect: connection refusedPut http://${HEAD_SVC_FQDN}:52365/api/serve/applications/: dial tcp $HEAD_IP:52365: connect: connection refused处理步骤等待约 1 分钟再观察——这通常是组件启动时序导致的暂时性失败若超过 1 分钟仍持续失败则可能是 dashboard 或 dashboard agent 未能正常启动进入 head Pod 检查/tmp/ray/session_latest/logs/下的dashboard.log与dashboard_agent.log。错误信息 2i/o timeoutPut http://${HEAD_SVC_FQDN}:52365/api/serve/applications/: dial tcp $HEAD_IP:52365: i/o timeouti/o timeout与connection refused不同说明端口并未直接拒绝连接而是数据包没有收到响应最常见的原因是 Kubernetes NetworkPolicy 阻断了 Pod 与 dashboard agent 端口52365之间的流量。此时应检查集群中的 NetworkPolicy 规则确认 Operator → head Pod 的52365端口通路。Issue 6runtime_env相关故障serveConfigV2中可以为应用指定运行时环境working_dir、pip依赖等常见故障有两类working_dir指向私有 AWS S3 桶但 Pod 没有访问该桶的权限缺少 IAM 角色、访问密钥或 ServiceAccount 注解NetworkPolicy 阻断了 Pod 与runtime_env中外部 URL 之间的流量导致working_dir下载失败或 pip 安装超时。这两类问题的现象相似副本长时间处于启动中日志中出现下载/连接相关错误。排查顺序建议为先看副本日志中的具体异常权限 403 还是连接超时再对应检查云凭证配置或网络策略。Issue 7无法获取 Serve 应用状态Operator 在成功提交PUT请求后会持续通过GET /api/serve/applications/拉取状态Get http://${HEAD_SVC_FQDN}:52365/api/serve/applications/: dial tcp $HEAD_IP:52365: connect: connection refused与 Issue 5 不同——PUT成功说明 dashboard agent 当时是就绪的因此GET失败属于异常状态组件随后可能发生了崩溃。最典型的原因是head Pod 上的 dashboard agent 进程未运行。可以按以下步骤复现与验证# Step 1: 登录 head Pod kubectl exec -it $HEAD_POD -n $YOUR_NAMESPACE -- bash # Step 2: 找到 dashboard agent 进程的 PID ps aux # [示例输出] # ray 156 ... 0:03 ray::DashboardAgent -- # Step 3: 手动杀掉 dashboard agent 进程 kill 156 # Step 4: 查看 dashboard agent 日志确认退出原因 cat /tmp/ray/session_latest/logs/dashboard_agent.log # [示例输出] # 2023-07-10 11:24:31,962 INFO web_log.py:206 -- 10.244.0.5 [10/Jul/2023:18:24:31 0000] GET /api/serve/applications/ HTTP/1.1 200 13940 - Go-http-client/1.1 # ... # 2023-07-10 11:24:38,590 WARNING agent.py:531 -- Exiting with SIGTERM immediately... # Step 5: 在新终端查看 KubeRay Operator 日志确认 GET 请求开始失败 kubectl logs $KUBERAY_OPERATOR_POD -n $YOUR_NAMESPACE | tee operator-log # [示例输出] # Get http://rayservice-sample-raycluster-rqlsl-head-svc.default.svc.cluster.local:52365/api/serve/applications/: dial tcp 10.96.7.154:52365: connect: connection refused这个实验表明一旦 dashboard agent 退出Operator 的GET请求就会持续收到connection refused。生产中遇到此类报错应重点检查dashboard_agent.log中的崩溃原因而不是怀疑 NetworkPolicy。Issue 8资源不足导致 RayCluster 重启循环KubeRay v0.6.1 及更早版本注意KubeRay Operator 目前没有针对「Kubernetes 集群资源耗尽」的明确处理方案因此确保集群有充足资源容纳 Serve 应用是首选策略。当 Serve 应用状态在超过serviceUnhealthySecondThreshold秒后仍未变为RUNNING时Operator 会将该 RayCluster 标记为不健康并着手准备新 RayCluster。若集群资源确实不足新集群同样无法部署应用于是形成重启循环。可通过如下实验复现该场景一个只有 8 个 CPU 的节点RayCluster1 个 head Pod4 个物理 CPU但rayStartParams中num-cpus0防止 Serve 副本调度到 head 上 1 个默认 1 CPU 的 worker PodserveConfigV2声明 5 个 Serve 部署每个部署 1 个副本、需要 1 CPU。# Step 1: 查看节点可用 CPU kubectl get nodes -o custom-columnsNODE:.metadata.name,ALLOCATABLE_CPU:.status.allocatable.cpu # [示例输出] # NODE ALLOCATABLE_CPU # kind-control-plane 8 # Step 2: 安装 KubeRay Operator # Step 3: 创建资源不足的 RayService kubectl apply -f ray-service.insufficient-resources.yaml # Step 4: 查看 RayService 状态副本因资源不足而无法调度 kubectl describe rayservices.ray.io rayservice-sample -n $YOUR_NAMESPACE # [示例输出] # fruit_app_FruitMarket: # Health Last Update Time: 2023-07-11T02:10:02Z # Last Update Time: 2023-07-11T02:10:35Z # Message: Deployment fruit_app_FruitMarket has 1 replicas that have taken more than 30s to be scheduled. This may be caused by waiting for the cluster to auto-scale, or waiting for a runtime environment to install. Resources required for each replica: {CPU: 1.0}, resources available: {}. # Status: UPDATING # Step 5: 超过 serviceUnhealthySecondThreshold此处为 300s后Operator 创建新 RayCluster kubectl logs $KUBERAY_OPERATOR_POD -n $YOUR_NAMESPACE | tee operator-log # [示例输出] # 2023-07-11T02:14:58.109Z INFO controllers.RayService Restart RayCluster {appName: fruit_app, restart reason: The status of the serve application fruit_app has not been RUNNING for more than 300.000000 seconds. Hence, KubeRay operator labels the RayCluster unhealthy and will prepare a new RayCluster.} # ... # 2023-07-11T02:14:58.122Z INFO controllers.RayService Restart RayCluster {ServiceName: default/rayservice-sample, AvailableWorkerReplicas: 1, DesiredWorkerReplicas: 5, restart reason: The serve application is unhealthy, restarting the cluster. If the AvailableWorkerReplicas is not equal to DesiredWorkerReplicas, this may imply that the Autoscaler does not have enough resources to scale up the cluster. Hence, the serve application does not have enough resources to run. ...}日志中AvailableWorkerReplicas与DesiredWorkerReplicas不一致是资源不足的关键信号它说明 Autoscaler 无法获得足够资源把集群扩到期望规模。对应的修复方向是扩容 Kubernetes 节点、降低应用资源需求或减少副本数而不是反复观察 Operator 自动重启。Issue 9从单应用 API 无缝升级到多应用 APIKubeRay v0.6.0 起通过serveConfigV2支持 Ray Serve API V2多应用。但Ray Serve 不允许同一集群中同时使用 API V1 与 API V2。若在现有使用serveConfig的 RayService 上原地替换为serveConfigV2会遇到ray.serve.exceptions.RayServeException: You are trying to deploy a multi-application config, however a single-application config has been deployed to the current Serve instance already. Mixing single-app and multi-app is not allowed. Please either redeploy using the single-application config format ServeApplicationSchema, or shutdown and restart Serve to submit a multi-app config of format ServeDeploySchema. If you are using the REST API, you can submit a multi-app config to the the multi-app API endpoint /api/serve/applications/.解决方案将serveConfig替换为serveConfigV2同时把rayVersion修改为一个无实际效果的值Ray 2.0.0 及以后rayVersion不决定实际镜像仅用于触发升级例如2.100.0。这会触发新 RayCluster 的创建从而以「新集群方式」完成 API 版本迁移而不是原地更新。如果按上述步骤操作后仍报错且开启了 GCS fault tolerance则问题可能出在ray.io/external-storage-namespace注解新旧 RayCluster 若使用相同的存储命名空间会共享旧集群的元数据。此时应移除该注解让 KubeRay 为每个 RayCluster 自动生成唯一键。Issue 10启用 GCS fault tolerance 时的无停机升级问题KubeRay 会为 head Pod 设置环境变量RAY_external_storage_namespace其取值来自gcsFaultToleranceOptions.externalStorageNamespace或更早的ray.io/external-storage-namespace注解。该值代表 Ray 集群元数据在 Redis 中的存储命名空间head Pod 恢复时会用该值重连 Redis 以恢复集群数据。风险在于如果该值在 RayService 中固定零停机升级时新 RayCluster 会访问与旧集群相同的 Redis 存储命名空间。由于 Redis 中已存在旧集群的元数据Operator 可能误以为 Serve 应用已经就绪从而过早地退役旧 RayCluster 并将流量切到新集群——而新集群此时可能还在初始化 Serve 应用造成流量中断。推荐做法移除ray.io/external-storage-namespace注解不设置时KubeRay 自动使用每个 RayCluster CR 的 UID 作为RAY_external_storage_namespace值新旧集群互不可见天然隔离或者为每个 RayCluster 手动设置唯一的RAY_external_storage_namespace值。关于默认命名空间如何同时支持 GCS fault tolerance 与零停机升级见 GCS fault tolerance 与零停机升级。Issue 11RayService 卡在 Initializing——用初始化超时快速失败当底层 Pod 被调度但无法启动如ImagePullBackOff、CrashLoopBackOff或其他容器启动错误时RayService 可能无限期停留在 Initializing 状态持续占用集群资源且根因更难定位。机制KubeRay 通过注解ray.io/initializing-timeout暴露可配置的初始化超时。超时触发后 Operator 的行为RayServiceReady条件被置为Falsereason 为InitializingTimeoutRayService 进入终态失败此时修改 spec 不会触发重试恢复需要删除并重新创建 RayServiceRayService CR 上的集群名称被清空触发底层 RayCluster 资源的清理删除仍会遵循RayClusterDeletionDelaySeconds的延迟发出一个记录超时与失败原因的Warning事件。启用方式只需在 RayService 的metadata中加注解无需任何其他 CRD 变更。注解值支持 Go duration 字符串如30m、1h或整数秒如1800metadata: annotations: ray.io/initializing-timeout: 30m使用建议超时值需要在「正常启动所需时间」与「快速失败以节省集群资源」之间权衡设置过短可能误杀正常部署中的服务设置过长则失去 fail-fast 的意义。结合手段 2 观察RayServiceReady条件与事件即可判断是否触发了InitializingTimeout。排障流程速查将上述方法与问题对应可以形成一条快速路径症状首选观测手段对应 Issue应用部署后状态异常手段 3Pod 内 Serve 日志1、3、6提交配置后立刻报错手段 2CR 状态 Issue 2 的字段核对2、4创建/更新请求失败手段 1Operator 日志 head Pod 内dashboard.log/dashboard_agent.log5、7集群反复重启手段 1Operator 日志中的restart reason8升级后报错或流量中断手段 2CR 状态与事件9、10服务卡在 Initializing手段 2RayServiceReady条件与 Warning 事件11排障的顺序建议是先看 Operator 日志确认控制面行为 → 再看 RayService CR 状态确认应用视图 → 最后进入 Pod 查 Serve 与 dashboard agent 日志确认进程级细节。数据面问题Issue 1–4、6尽量先在本地或独立 RayCluster 复现把「脚本/配置错误」与「Kubernetes 环境问题」分离控制面与基础设施问题Issue 5、7、8、11则紧抓 Operator 日志中的请求与重启记录。掌握这套方法后RayService 的绝大多数故障都可以在十分钟内完成定性。赞分享人工智能分布式训练强化学习任务调度模型推理服务【免费下载链接】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点击查看免费下载相关推荐KubeRay 集群与 RayService 故障排查完整指南从 init container 卡死到 Serve 应用起不来KubeRay 集群与 RayService 故障排查完整指南从 init container 卡死到 Serve 应用起不来 本文基于 Ray 官方仓库中的人工智能分布式训练强化学习任务调度模型推理服务Cilium Gateway API 故障排查指南从状态条件到 Operator 日志的系统化排障方法Cilium Gateway API 故障排查指南从状态条件到 Operator 日志的系统化排障方法 在 Kubernetes 环境中部署 Cilium 的云原生网络服务网格可观测性网络安全eBPFVector 故障排查实战指南从日志定位到调试日志的完整排障流程Vector 故障排查实战指南从日志定位到调试日志的完整排障流程 本指南基于 Vector 官方操作文档 website/content/en/guides可观测性数据工程数据集成日志分析上一篇Eino许可证Apache-2.0开源协议使用指南下一篇t5-small-qg-hl部署指南云端与本地环境配置详解创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门