V2 独立版愿景

节点管理

HeteroFlow 是本站的异构算力与大模型调度产品。节点管理。节点管理 硬件验证边界(截至 2026-10-20) :本文中的“10 种品牌/检测器”指代码检测与适配范围,不代表 10 种硬件都完成了真机端到端验证。现有项目记录显示 NVIDIA 多机型已有真机端到端证据;国产加速卡检测逻辑已做软件及厂商命令输出对照,真机端到端验证仍待对应…

节点管理

> 硬件验证边界(截至 2026-10-20):本文中的“10 种品牌/检测器”指代码检测与适配范围,不代表 10 种硬件都完成了真机端到端验证。现有项目记录显示 NVIDIA 多机型已有真机端到端证据;国产加速卡检测逻辑已做软件及厂商命令输出对照,真机端到端验证仍待对应硬件。

节点管理是 HeteroFlow 把一台台裸金属服务器、云主机乃至 WSL 工作站变成可调度算力资源的全托管子系统:节点上部署 Agent 后自动注册进平台,每 5 秒一跳心跳上报 GPU 状态与环境信息,服务端持续做健康判定与故障处置,监控指标沉淀为历史曲线,退役时有删除保护兜底。从接入到退出的整条生命线——注册 → 心跳 → 健康 → 监控 → 退役——全部由平台托管,运维只需要关心机器本身。

平台内置 10 种 GPU 品牌检测器(另有虚拟 GPU 兜底,共 11 种类型),国产卡优先识别。心跳同时承载 GPU 分片能力、推理引擎版本、本地模型发现等环境自描述信息,调度器、推理网关、镜像预热等上层能力全部以节点子系统维护的这些数据为地基。

功能总览

能力一句话说明状态
节点注册双路径Agent 心跳隐式注册为主,手动 API 创建保留为运营通道已实现
心跳机制默认 5 秒一跳,内容覆盖 GPU 指标、分片能力、推理引擎、模型发现已实现
节点状态机在线/可疑/离线/降级四态自动判定,30s/60s 双阈值已实现
节点故障统一处置失联任务一律服务端裁决:有活节点就温和重排,全灭才判死真机验证
GPU 自动识别10 检测器优先级链 + 虚拟 GPU 兜底,国产优先已适配(国产 8 家无真机)
掉卡逐卡探测运行中掉卡连续 3 拍判丢、GPU_LOST 告警、调度自动跳过已实现(未经真机掉卡验证)
GPU 分片能力上报MIG/MPS 能力随心跳每跳回写,宁可少报不假报已实现(NVIDIA 真机验证)
公网/内网双 IP 维护公网 IP 按心跳 TCP 源地址每跳回写,内网 IP 供训练直连已实现
显式网络域标签heteroflow.network_zone 声明内网可达性,杜绝跨域训练静默挂起已实现
节点物理位置Region/Zone/Rack 管理员手动填写,供拓扑感知就近调度已实现
节点监控历史 CPU/内存/GPU 曲线 + 能耗与碳排放观测已实现
环境总览统计节点/在线/离线/GPU 厂商分布一屏尽收,支撑千节点分页已实现
镜像预热独立于任务生命周期的运维态拉取与镜像有无查询通道真机验证
删除保护活跃任务与模型注册两道预检,默认拒绝而非静默级联已实现
节点归属租户读路径判据与指派接口就绪;当前部署只有共享节点一种模式已实现-部分

节点注册:双路径接入

Agent 自动注册(主路径)

节点接入的标准方式是部署 Agent:一键部署脚本在目标机器上安装 agent 并注册为 systemd 服务,Agent 启动即执行 DetectAll() 全量 GPU 检测,随后向 POST /api/v1/nodes/{id}/heartbeat 发出第一跳心跳——服务端发现节点不存在时隐式创建节点记录:以心跳请求的 TCP 源地址作为公网 IP,验证并落库 MAC 地址,生成默认名称 agent-{id},初始化 GPU 子表。整条流程无需任何人工填表,部署完成即出现在节点列表(部署细节见《Agent 系统》)。

Agent 的标准流程只发心跳、从不调用创建接口;节点身份由 X-API-Key 系统密钥(服务端 auth.agent_secret)认证,天然绑定节点作用域。

手动创建(运营通道)

POST /api/v1/nodes 保留 UPSERT 语义的创建/更新接口,用于平台运营者补录或修正节点信息。自 2026-10-01 起该接口只认 agent 系统密钥与平台运营者(sk-admin- key 或 role=admin JWT),普通租户成员一律 403——因为它能改写 ip/status/gpu_used 等权威字段,而推理网关按 node.IP 拼转发地址,不能暴露给租户。前端的节点创建页面已下线("节点只由 Agent 自注册"),避免用户点到注定被拒的操作。

心跳机制

心跳是 Server 与 Agent 之间的核心通道,默认 5 秒一跳(环境变量 HETEROFLOW_HEARTBEAT_INTERVAL_SEC 或 agent-config.json 可配,合法区间 5~300 秒),既上报实时指标,也承载环境自描述与任务下发应答。

心跳内容全景:

类别字段说明
基础负载cpu_used / memory_used / gpu_temperature / gpu_memory_used_mb节点级实时负载
执行能力docker_available / executable / exec_mode / error_message不可执行时状态机判"降级"
规格自描述cpu_cores / memory_gb / mac / internal_ip隐式注册与规格更新的来源
Agent 标识agent_version / agent_git_commit / agent_build_time构建三元组,每跳回写,节点页可查
GPU 逐卡状态gpu_stats每卡型号/显存/利用率/温度/compute_capability/metrics_available;D30 起采集失败且能归因到卡的条目不再上报陈旧读数
掉卡信号gpu_collect_failures / gpu_collector_error逐卡采集失败清单与采集器整体失败声明,GPU 卡丢失判定的第二信号
分片能力gpu_capabilitiesMIG/MPS 能力每跳回写,daemon 挂掉下一跳摘牌
标签labels按 key 合并进 node_labels,含网络域标签
任务侧task_health / live_task_ids任务健康检查结果与 docker inspect 实测存活清单
推理引擎vllm_available / inference_engines / inference_engine_versions检测 vLLM、llama.cpp、MindIE、SGLang 等引擎及版本,回灌节点记录,供模型部署与网关调度引用
模型发现discovered_models本地已存在的大模型清单(路径/体积/格式)

服务端处理的关键设计(core/pkg/api/node_heartbeat.go):

  • 公网 IP 每跳按 TCP 源地址回写:刻意不信任 X-Forwarded-For(可伪造),云厂商回收重分配公网 IP 后不会残留旧地址;IP 变化立即失效推理网关后端缓存。
  • GPUUsed 防超卖记账:按活跃任务 SUM(gpu_required) 计算,不按任务条数——4 卡任务算占 4 张卡,心跳不会用低估值覆盖调度器的账。
  • 写入路径二选一:稳态心跳走 UpdateNodeHeartbeat 快路径只写心跳列;结构性字段(GPU 型号/规格/labels)变化或新建节点才整行 Update,避免高频整行覆盖并发写入。
  • 读节点出错回 503 不写任何东西:瞬时读故障不会被误当成"节点不存在"而走隐式建节点分支改写真实节点。
  • 分片卡池幂等补注册:每跳都把 GPU 注册进 SliceManager(已存在只更新不清空),Server 重启后一个心跳周期内自愈。
  • node_metrics 自动清理:每 500 次心跳触发一次过期清理,默认保留 7 天(METRICS_RETENTION_HOURS 可覆盖)。

心跳响应在有待执行任务时携带 scheduled_tasks,Agent 据此认领分配给自己的任务(Agent 另有独立的 5 秒任务轮询通道,两者并存)。断线重连零人工:Agent 恢复心跳的瞬间,状态机自动把 offline/suspect 节点拉回 online,GPU 与分片能力随当跳心跳自动补齐。

节点状态机

节点状态由心跳时间与执行能力共同决定。服务端有两个协作者:HealthChecker 每 5 秒全量扫描,按超时被动判定;心跳处理器 收到心跳时主动恢复。两者只会写入 online / suspect / offline / degraded 四个状态(busy/error/recovering 有常量声明但无服务端自动写入路径,属防御性保留)。

容易混淆的是节点级与 GPU 级两套状态:nodes.status 是节点整体四态;gpus.status(available/busy)是每张卡的占用情况,由心跳按卡回写,资源过滤插件依赖它。一个节点可以整体 online 而部分卡 busy,也可以在个别卡被判丢失时继续正常调度其余卡。

判定阈值(代码常量,core/pkg/constants):

阈值值含义
心跳间隔 < 30s(SuspectTimeout)且 Executable=true → online;不可执行 → degraded正常态
30s ≤ 间隔 < 60s(OfflineTimeout)→ suspect(仍接受任务)网络抖动容忍窗
间隔 ≥ 60s→ offline不接受新任务
状态触发条件调度行为前端显示
online心跳正常且可执行接受新任务绿色"在线"
suspect心跳静默 30~60 秒接受任务(仍可用)橙色"可疑"
offline心跳静默超 60 秒不接受任务红色"离线"
degradedExecutable=false(Docker/GPU 故障)不接受新任务灰色"降级"

多实例部署下 HealthChecker 只在主实例运行(见《集群管理》选主机制)。

节点故障统一处置政策

"节点出故障时任务怎么办"有统一口径:处置一律由服务端裁决——集群里还有在线节点就把任务重排回 pending 交给调度器重新调度,全灭才判 failed,Agent 不再自行判死。三个入口:

入口触发处置
节点离线迁移AlertMonitor 每 30 秒巡检,心跳静默 > 45 秒判离线(NODE_OFFLINE,独立于状态机的 30s/60s)running/scheduled/starting/waking → pending 重排;stopping → stopped、draining → completed 就地判终态;sleeping/preempting 不动(各有专属路径)
容器丢失裁决Agent 60 秒对账发现"服务端认为 running、本机没有容器"Agent 先向服务端二次确认归属,只上报事实不判死;服务端对组任务按集群死活裁决重排或判死,查不清就 fail-closed 下轮重试
唤醒队列休眠实例所在节点不可承接唤醒节点判 alive/dead/unknown 三态:死节点迁走重建,查询抖动本轮不动(避免平白重建健康实例)

配套细节:所有状态迁移过状态机白名单校验、CAS 写库防竞态;就地判终态分支补 GPU-秒结算;排队超时死线以 created_at/updated_at 较晚者为锚点——跑了很久的服务被重排的瞬间不会被排队超时当场判死。

GPU 自动识别与掉卡探测

10 检测器优先级链

Agent 启动时按固定优先级遍历检测器:摩尔线程 MUSA → 海光 DCU → 寒武纪 → 壁仞 → 昇腾 → 昆仑 → 天数智芯 → NVIDIA → 沐曦 → 燧原;一个都没命中则创建虚拟 GPU 兜底(无卡环境的测试兜底)。这是识别顺序(异构混部优先识别国产算力),不是调度打分权重。每家检测器通过设备文件或厂商 smi 工具判定在场,命令查找带 WSL2 等非常规路径兜底(WSL2 的 nvidia-smi 固定装在 /usr/lib/wsl/lib,裸 PATH 查找会把有卡节点误判成虚拟 GPU);壁仞检测的已知问题由服务端按显存特征值二次修正(32512MB→106M、65536MB→BR100)。各厂商检测方法与输出解析的完整矩阵见《GPU 检测》专题。

GPU 类型类型标识检测工具指标支持
摩尔线程 MUSAmusamthreads-gmi利用率/显存/温度
海光 DCUhygonhy-smi利用率/显存/温度
寒武纪 MLUcambriconcnmon(开发中)利用率/显存/温度
壁仞 BRbirenbrsmi / birensmi利用率/显存
华为昇腾 NPUascendnpu-smi利用率/显存/温度
百度昆仑 XPUkunlunxpu_smi / xpu-smi(开发中)利用率/显存/温度
天数智芯iluvatarixsmi利用率/显存/温度
NVIDIAnvidianvidia-smi利用率/显存/温度/算力
沐曦 MetaXmetaxmx-smi利用率/显存/温度
燧原enflameefsmi利用率/显存/温度
虚拟 GPUvirtual内置兜底基础指标

指标可用性以心跳 metrics_available 为准:各检测器只上报本轮真正解析命中的指标,服务端据此区分"真 0"与"没采到",不会把采不到的温度当成 0°C。

运行中掉卡:逐卡探测与 GPU_LOST

节点仍在正常发心跳、但某张登记在册的卡连续 3 拍"看不到"(没出现在心跳 gpu_stats 里,或 Agent 显式上报该卡采集失败)时,平台判定该卡丢失:

  • 产生节点级 GPU_LOST 告警(ERROR),判定依据(心跳缺席 / Agent 报采集失败 / 混合)写进告警文案与 gpus.lost_basis;占用该卡的任务各记一条容错事件;
  • 调度器不再把新任务分配给这张卡(gpus.lost_at 落库,Server 重启仍有效);已在卡上运行的任务不动——不迁移、不判失败,卡恢复走既有对账路径;
  • 统计诚实:丢失卡仍计入 GPU 总数(不悄悄抹掉),但不算可用不算繁忙,仪表盘、健康详情、环境总览各自单独计数;
  • 卡连续 2 拍重新出现 → 自动解除、重新参与分配,告警按 RECOVERED 消解。

逐卡探测能力因厂商而异(能力矩阵由测试钉住,新增厂商必须显式分类):

支持度厂商
完整支持NVIDIA(逐卡查询 + UUID 核对)
部分支持昇腾、昆仑、寒武纪(单卡节点或全部卡同时失败判不出)
不支持海光、天数智芯、壁仞、摩尔线程、沐曦、燧原(整机输出按位置匹配,无法归因到具体卡,仍需重启 Agent 后重新检测发现)

掉卡场景未经真机验证(单测/仿真心跳验证);采集器整体失败(工具不存在、NVML 初始化失败等)不等于所有卡都丢——Agent 另用 gpu_collector_error 声明,服务端整拍不信任"在场"也不判丢失。

GPU 分片能力上报

每张卡的 MIG/MPS 分片能力以 gpu_capabilities 随心跳每跳回写,口径"宁可少报不可假报":

  • mig_capable 仅当 nvidia-smi 报告 MIG mode Enabled(硬件支持但未启用不算);
  • mps_capable 仅当宿主机 MPS daemon 当前确认存活(挂掉下一跳即摘牌);
  • best_tier 标记最佳分片层级(1-9,数字越小越强):MIG=1(硬件隔离)、MPS=2(软复用+限额)、仅软件记账=9;vNPU/vMLU 等字段为结构预留,不声称支持;
  • 容器化环境节点(is_container=true)自动降级 Bronze 级记账,不执行硬件级切分。

分片语义与调度细节见《GPU 显存分片》。

IP 维护与网络域

字段来源更新时机用途
ip(公网)心跳 TCP 源地址(不信任转发头)每跳回写推理网关后端地址、跨域训练 MASTER_ADDR
internal_ip(内网)Agent 上报(跳过 docker 网桥地址)每跳更新同 VPC 内多机训练直连优先使用

显式网络域标签解决内网 IP 撞址:私网地址只在一个 VPC 内唯一,不同 VPC 的两台节点可能上报同一个内网 IP——旧的"按 IP 前缀猜同网"判据会把它们判成同子网,训练任务下发内网 MASTER_ADDR 后 NCCL 永久挂起、零报错。现改用显式声明(core/pkg/scheduler/network_domain.go):

标签说明
heteroflow.network_zone运维显式声明的网络域标识(推荐直接用云厂商 VPC ID)。两台节点值相同 = 声明"内网互相可达"
heteroflow.vpc_id预留给 Agent 从云厂商 instance metadata 自动上报(标签通道就绪,自动采集为后续工作)

判定规则先反证后正证:内网撞址或 region 不同 → 证明跨域;全部节点带一致显式域标识 → 证明同域;其余 → 无法证明。只有证明同域才走内网 + NCCL,跨域与无法证明一律回退公网 + gloo——宁可慢或明确失败,不要静默永久挂起(确定单 VPC 的部署可用策略 assume_same 显式恢复旧行为)。

节点物理位置

nodes 表的 Region/Zone/Rack 三列供拓扑感知调度使用:同一训练组(TP/PP/Gang 协同)的各个 rank 会被优先调度到这三个字段相同的节点上,降低跨云跨地区多机训练的网络延迟。写入方式是管理员专用接口 PUT /api/v1/admin/nodes/{id}/location(与归属租户接口同一套 admin:write 门禁):三个字段可选,省略 = 不改动、显式空串 = 清空,语义严格区分;非空值上限 64 字符。窄 SQL 写入不整行覆盖,与并发心跳互不干扰。前端节点详情面板"物理位置"一行点击"编辑"弹窗填写。

节点监控

心跳指标每跳写入 node_metrics 表(默认保留 7 天),节点监控页据此渲染历史曲线;能耗累计量独立存储、长期保留。

  • 曲线:GPU 利用率/显存/温度与 CPU/内存使用率双图,按 GPU 可切换单卡或聚合;
  • 能耗与碳排放:累计能耗(kWh)、逐卡与整机功耗曲线(实测)、CPU 功耗估算单独成图并标注"估算";碳排放展示随排放因子配置与查看者角色分级——因子未配置时对外不展示绝对值,没有数据一律显示"—"不是 0;
  • GPU 健康页(/nodes/gpu-health):GPU 显存 ECC 错误计数的故障预测统计、预测列表与采集能力矩阵(预测有效性尚未经真实数据验证,样本不足时不显示百分比)。

环境总览统计

GET /api/v1/environment/summary 一屏回答"集群长什么样":节点总数、GPU 总数(含判定丢失单独计数)、在线可检测(online/busy/degraded/suspect 口径)、离线、按状态分布、GPU 厂商分布。配套的节点列表分页接口(GET /api/v1/nodes?limit=&offset=&q=&status=&gpu_type=)把搜索与筛选全部下推后端,任何条件下单次只取一页——千节点级集群不做全量拉取。环境检测页在此之上对存活节点自动跑关注镜像清单检测(见下节)。

镜像预热(运维态镜像通道)

任务启动时拉镜像是刚需路径(3 次 × 5 分钟预算),镜像预热提供一条独立于任务生命周期的运维态通路,让节点在接第一个任务之前就把镜像备好:

能力接口说明
后台拉取POST /nodes/{id}/images/pull预算 2 小时,Agent 每 60 秒回写进度;以"进度停摆 10 分钟"判僵死,拉再久不误杀
镜像有无查询POST /nodes/{id}/images/check一次最多 32 个镜像,秒级回答 present/体积/image_id
匹配模式引用形态决定带 tag/digest → 精确匹配(验证升级是否生效);不带 tag → 仓库匹配(列本地所有 tag 与体积,回答"这个引擎有哪些版本")
关注镜像清单GET /nodes/{id}/images/watched服务端权威下发:按节点 GPU 类型组装引擎镜像/基础镜像/训练镜像清单,前后端与 Agent 两侧契约测试钉住防脱节
请求应答通道GET /image-requests/{id}、GET /image-requests?node_id=请求行状态机 pending → processing → completed/failed,janitor 清理僵尸行与过期行

两条路径与任务态拉取完全独立、互不干扰(不共享常量与代码,Agent 侧运维拉取之间串行但从不阻塞任务启动拉取);pull 完成的回报被服务端校验(拒收"拉完了但镜像不在"的假成功),拉取失败重试无害——已下载的层留在 docker 缓存,重新下单即续传。私有镜像走两条已落地路径:平台自有镜像在节点内构建后推入内网 registry(10.7GB 训练镜像实测约 4 分钟拉完);客户私有仓库经任务级凭证透传(仅任务态路径,运维态拉取走节点 daemon 现有配置)。版本兼容上,旧版 Agent 收到不带 tag 的条目按 :latest 精确回报,升级 Server 不要求同时升级全部节点 Agent。前端入口在环境总览页(/environment),对当前页存活节点自动检测、离线节点如实标注"无法检测"不下发指令。通道细节见《运维态镜像通道》。

节点退役与删除

DELETE /api/v1/nodes/{id} 在删除前执行两道预检,默认拒绝而不是静默级联:

1. 活跃任务预检(没有 force 出口):节点上有 scheduled/starting/running/stopping/draining/sleeping/waking/paused 任务 → 409 拒绝并点名任务 ID 与状态。删掉节点行后离线迁移永远遍历不到该节点,任务会永久停在 running 并一直占租户配额——force 对这一条无效是刻意设计;

2. 模型注册预检(force 可级联):节点上有模型注册且未带 ?force=true → 409 点名模型;带 force → 先删模型再删节点,删了什么在响应体逐条回报。

权限分层:平台管理员可删任何节点;租户管理员只能删本租户私有节点;共享节点与 member/viewer 一律 403;Agent 系统密钥一律 403(Agent 从不删节点)。节点行删除时 gpus 与 node_labels 级联删除。

节点归属租户(保守口径)

nodes.tenant_id 列承载节点归属语义:空/NULL = 共享节点(对所有租户可见可调度),非空 = 专属节点(仅属主租户可见)。如实说明当前状态:归属判据(列表、调度过滤、显式指派校验三处同义)与管理员指派接口 PUT /api/v1/admin/nodes/{id}/tenant 在代码中已就绪(含乐观并发保护,冲突返回 409),但当前生产部署没有启用这一模式——生产库全部节点该列为 NULL,实际运行的只有"共享节点"一种形态。归属变更的驱逐策略(drain 温和等待 / evict 优雅停止)与"专属节点"的产品语义,以多租户体系正式启用为准,详见《多租户与权限》。

页面功能介绍

/nodes 节点管理页

左侧节点卡片列表 + 右侧滑出详情面板,30 秒自动刷新。

操作 / 区域行为背后 API
顶部统计面板总 GPU / 工作中 / 空闲 / 判定丢失 / 总调度 / 失败调度 / 成功率一排概览GET /nodes(前端聚合)
搜索框按名称、ID、IP、机架、可用区、GPU 型号过滤前端过滤
排序切换任务量(默认)/ GPU 繁忙 / 利用率 / 名称四种模式前端排序
节点卡片点击弹出详情;状态徽章 + GPU 类型/推理引擎标签 + CPU/内存/GPU 状态条/显存/利用率/任务统计GET /nodes
卡片展开区逐卡型号/状态/利用率/显存/温度;判定丢失的卡显示「判定丢失」标签与处置说明同上(gpus.lost_at)
详情-删除节点二次确认后删除;有活跃任务/模型注册时如实展示 409 原因DELETE /nodes/{id}
详情-归属租户编辑(管理员)下拉选择租户或共享;首次提交固定 drain,检测到其它租户在跑任务时弹窗二选一(保持等待 / 立即优雅停止),停止失败清单如实展示PUT /admin/nodes/{id}/tenant
详情-物理位置编辑(管理员)Region/Zone/Rack 三个文本框,清空即提交空串(与"不改动"区分)PUT /admin/nodes/{id}/location
详情-标签/已缓存模型系统标签键值对;heteroflow.cache/models 解析出已缓存模型清单GET /nodes/{id}

/nodes/monitor 节点监控页

左侧在线/离线分组节点列表(可搜索)+ 右侧监控面板。

操作 / 区域行为背后 API
时间范围选择器1 小时 / 6 小时 / 24 小时 / 3 天 / 7 天GET /nodes/metrics/{id}?hours=
自动刷新开关每 90 秒自动刷新曲线与能耗同上 + GET /nodes/{id}/energy
实时指标概览GPU 利用率/显存/CPU/内存/温度五卡片,阈值着色,不支持的指标显示"不支持"同上
GPU 选择器多卡节点按单卡或聚合查看同上(gpu_data 逐卡数据)
能耗与碳排放区累计能耗、逐卡/整机功耗曲线、CPU 估算曲线;无数据显"—"GET /nodes/{id}/energy

/environment 环境总览页(镜像预热入口)

总览仪表盘 + 状态分区标签(在线可检测/离线/全部)+ 服务端分页表格;对存活节点自动跑关注镜像清单检测、展示"n/m 齐全"摘要与逐镜像版本明细;部署按钮触发后台拉取并 5 秒轮询进度。离线节点如实标注、不下发检测指令。

后端逻辑概念表

概念含义
隐式注册首跳心跳即建节点:TCP 源地址为公网 IP、验证 MAC、默认名 agent-{id}
HealthChecker5 秒周期全量扫描节点状态的后台协程,只写 status 一列,不处置任务
SuspectTimeout / OfflineTimeout可疑 30 秒 / 离线 60 秒判定阈值(代码常量)
AlertMonitor30 秒巡检、45 秒判离线的告警协程,负责 NODE_OFFLINE 与任务迁移处置
快路径写入稳态心跳只写心跳列的窄更新,避免高频整行覆盖
网络域heteroflow.network_zone 显式声明的内网可达域,同域内网+NCCL、其余公网+gloo
cardprobeAgent 逐卡探测(D30):采集失败能归因到具体卡时上报,掉卡判定的第二信号
GPU_LOST节点在心跳但某卡连续 3 拍不可见的 ERROR 告警;2 拍重现自动闭合
lost_at / lost_basis卡丢失判定时刻与依据(heartbeat_absent / agent_collect_failure / mixed),调度器据此跳过
容器丢失裁决Agent 只上报事实、服务端按集群死活裁决的统一处置入口
image-requests运维态镜像通道的请求应答表,pending→processing→终态,janitor 清理
node_metrics监控指标历史表,默认保留 7 天,每 500 拍心跳触发清理

API 参考

接口说明
GET /api/v1/nodes节点列表;status 过滤,limit/offset/q/gpu_type 分页搜索(千节点级)
GET /api/v1/nodes/{id}节点详情;专属节点越权一律 404(不泄露存在性)
POST /api/v1/nodes创建/UPSERT 节点;仅 agent 密钥与平台运营者,租户成员 403
DELETE /api/v1/nodes/{id}删除节点;两道预检,?force=true 仅覆盖模型注册级联
POST /api/v1/nodes/{id}/heartbeat心跳(PUT 等价);隐式注册、指标落库、任务下发应答
GET /api/v1/nodes/metrics/{id}?hours=历史监控指标;租户可见性与详情接口同判据
GET /api/v1/nodes/{id}/energy累计能耗/功耗趋势;无数据字段为 null 不是 0
PUT /api/v1/admin/nodes/{id}/tenant节点归属指派(admin:write;当前部署未启用专属节点模式)
PUT /api/v1/admin/nodes/{id}/location物理位置 Region/Zone/Rack 手动填写(admin:write)
POST /api/v1/nodes/{id}/images/pull运维态后台拉取镜像(2 小时预算)
POST /api/v1/nodes/{id}/images/check镜像有无查询(≤32 个,精确/仓库两种匹配)
GET /api/v1/nodes/{id}/images/watched该节点关注镜像清单(服务端权威)
GET /api/v1/image-requests[?node_id=&status=]拉取/检测请求行轮询与历史
GET /api/v1/environment/summary环境总览统计

已知边界

1. 容器化节点强制 Bronze 记账:is_container=true 的节点不做硬件级切分,分片能力自动降级。

2. 掉卡探测厂商覆盖不全:NVIDIA 完整,昇腾/昆仑/寒武纪部分,海光/天数/壁仞/摩尔线程/沐曦/燧原不支持运行中探测(需重启 Agent 才能发现少了卡);掉卡场景整体未经真机验证。

3. 国产卡检测无真机:8 家国产 GPU 检测逻辑对齐官方文档与输出夹具,但无真机端到端验证,"已适配检测"不等于"已跑通训练/推理"。

4. GPU_LOST 连续计数在进程内存:Server 重启后未判定的缺席需重新累计;已判定状态经 gpus.lost_at 落库共享。

5. member/viewer 看不到节点类告警:节点没有"创建者"概念,节点作用域告警对普通成员整支关闭,是否放宽待产品决策。

6. vpc_id 自动采集未实现:网络域标签通道就绪,Agent 从云 metadata 自动上报 VPC ID 属后续工作,当前需运维手动打 heteroflow.network_zone。

7. GPU 故障预测未验证:ECC 预测的有效性尚未经真实数据验证,样本不足时不显示百分比。

<!-- 状态标注说明: 真机验证=真实GPU端到端 / 已实现=代码+测试钉住 / 已适配=检测逻辑对齐官方文档但无真机 / 已实现-部分=机制就绪但当前部署未启用 -->