1053 lines
33 KiB
Markdown
1053 lines
33 KiB
Markdown
# 22 domainCheck 海外 Codex 驾驶员与 Ops Center 落地路线
|
||
|
||
如果当前目标已经从“设计 Codex 驾驶员”进入“准备正式上线”,建议先补看:
|
||
|
||
- `docs/25_domainCheck_海外单脑控制面上线收口总表.md`
|
||
- `docs/schemas/ops_driver_contract.md`
|
||
- `docs/schemas/ops_stack_diagnosis_contract.md`
|
||
|
||
## 一、目标收口
|
||
|
||
这套体系后续不应该再依赖:
|
||
|
||
- 人工登录每台大陆机器
|
||
- 手工 `systemctl`
|
||
- 手工复制 `journalctl`
|
||
- 人工判断哪台机器在跑、哪台机器没跑
|
||
|
||
要收口成两种都能工作的模式:
|
||
|
||
### 模式 A:有 Codex
|
||
|
||
- 海外主机部署 Codex
|
||
- Codex 作为智能驾驶员
|
||
- 自动读取集群状态、同步状态、参与检测节点、日志回传状态
|
||
- 自动决定下一步执行哪类运维动作
|
||
|
||
### 模式 B:没有 Codex
|
||
|
||
- 海外后台照样能点按钮
|
||
- 后台把按钮动作转换成标准化 `ops job`
|
||
- 控制面自动分发到节点
|
||
- 节点回传执行结果、日志、诊断摘要
|
||
|
||
一句话:
|
||
|
||
> Codex 负责“智能判断”,Ops Center 负责“标准动作执行”。
|
||
|
||
---
|
||
|
||
## 二、推荐最终结构
|
||
|
||
### 1. 海外控制面
|
||
|
||
海外控制面承担:
|
||
|
||
- Web 前端
|
||
- API 控制面
|
||
- Ops API
|
||
- 发布包管理
|
||
- 节点纳管
|
||
- 日志汇聚入口
|
||
- 运维任务中心
|
||
|
||
### 2. 大陆节点
|
||
|
||
大陆节点统一视为“被托管节点”:
|
||
|
||
- controller / worker 主服务
|
||
- node agent
|
||
- systemd
|
||
- 本机诊断采集器
|
||
|
||
### 3. 三条运维链路
|
||
|
||
#### 主链路:Agent 拉任务
|
||
|
||
- 最终常态方案
|
||
- 适合日常安装、更新、巡检、采日志
|
||
|
||
#### 辅链路:后台按钮
|
||
|
||
- 前端触发动作
|
||
- 后端创建 `ops job`
|
||
- 节点 agent 执行
|
||
|
||
#### 兜底链路:SSH
|
||
|
||
- 只保留给首次 bootstrap 和紧急救援
|
||
- 不再作为日常主流程
|
||
|
||
---
|
||
|
||
## 三、当前代码基座已经具备的条件
|
||
|
||
当前仓库已经具备这些基础:
|
||
|
||
- `runtime/status`
|
||
- `runtime/cluster`
|
||
- `runtime/readiness`
|
||
- `runtime/sync-summary`
|
||
- debug handoff / diagnosis
|
||
- 远端日志回传开关基础
|
||
- 检测参与节点与待命节点视图基础
|
||
|
||
这意味着我们不是从零开始,而是已经有:
|
||
|
||
> 运行态观测基座
|
||
|
||
现在需要补的是:
|
||
|
||
> 运维动作编排基座
|
||
|
||
---
|
||
|
||
## 四、建议的落地顺序
|
||
|
||
### 第 1 步:先统一成 Ops API
|
||
|
||
本次先补:
|
||
|
||
- `/api/v1/ops/overview`
|
||
- `/api/v1/ops/capabilities`
|
||
- `/api/v1/ops/blueprint`
|
||
- `/api/v1/ops/runbook`
|
||
- `/api/v1/ops/nodes`
|
||
- `/api/v1/ops/jobs`
|
||
|
||
这一步的意义不是“已经远控完成”,而是先把控制面语言统一起来。
|
||
|
||
也就是以后无论:
|
||
|
||
- Codex 判断
|
||
- 后台按钮
|
||
- 节点 agent 执行
|
||
|
||
都围绕统一的 `ops` 模型展开。
|
||
|
||
后续发布链路也应保持这个原则:
|
||
|
||
- `release launchpad`
|
||
- `ops overview.driver_recommendations`
|
||
- `ops runbook.release_progression`
|
||
|
||
三者必须共用同一份发布状态机,而不能各自维护一套“推荐下一步”。
|
||
|
||
同理,标准作业路径也不应只是“展示文案”:
|
||
|
||
- `ops runbook.control_sequences`
|
||
- `POST /api/v1/ops/runbook/sequences/{sequence_key}/resolve`
|
||
- `POST /api/v1/ops/runbook/sequences/{sequence_key}/execute`
|
||
|
||
这三层组合起来,才是海外 Codex 驾驶员和后台按钮都能复用的统一作业入口:
|
||
|
||
- `control_sequences`
|
||
负责提供当前应该走哪条标准路径
|
||
- `resolve`
|
||
负责把这条路径收口成“此刻真正要执行的 driver action / node_codes / payload”
|
||
- `execute`
|
||
负责真正触发后端动作
|
||
|
||
这样海外 Codex 可以先做:
|
||
|
||
1. 读取 `runbook`
|
||
2. 对目标 sequence 调 `resolve`
|
||
3. 判断是自动执行、请求确认,还是只生成建议
|
||
4. 最后再调 `execute`
|
||
|
||
同样地,发布审阅动作也不应只是“跳到某个页面再看”:
|
||
|
||
- `review_smart_rollout_preview`
|
||
- `review_control_rollout`
|
||
- `fix_rollout_blockers`
|
||
|
||
现在这类动作应该直接返回结构化 `release_launchpad_review` 结果,至少包括:
|
||
|
||
- `latest_release`
|
||
- `launchpad_status`
|
||
- `preview`
|
||
- `smart_rollout`
|
||
- `target_node_codes`
|
||
- `gap_rows`
|
||
|
||
这样没有前端时,Codex、CLI、自动化任务也能直接基于 launchpad 预案判断下一步,而不是先依赖 UI 才能继续。
|
||
|
||
这里还要把自动化等级口径固定下来,避免后面又把“审阅”和“执行”混成一类:
|
||
|
||
- `review_smart_rollout_preview`
|
||
- `review_control_rollout`
|
||
- `fix_rollout_blockers`
|
||
|
||
这三类动作现在应统一视为:
|
||
|
||
- `safe_auto`
|
||
- 只读审阅
|
||
- 可以直接由后端执行并返回结构化 `release_launchpad_review`
|
||
|
||
而真正会创建发布或放量对象的动作,例如:
|
||
|
||
- `publish_latest_worker`
|
||
- `create_smart_release_rollout_worker`
|
||
- `create_smart_release_rollout_control`
|
||
- `create_release_rollout_worker`
|
||
- `create_release_rollout_control`
|
||
|
||
则必须继续归类为:
|
||
|
||
- `guarded_auto`
|
||
- 先确认,再执行
|
||
- 必须走正式的发布 / rollout 审批与审计链
|
||
|
||
这样海外 Codex、CLI、按钮驾驶舱三边看到的规则才会一致:
|
||
|
||
- “看预案”可以自动跑
|
||
- “创建放量”不能静默自动提交
|
||
|
||
而不是把判断逻辑重新写在 Codex prompt 或后台页面里。
|
||
|
||
同样,`GET /api/v1/ops/codex-brief` 和 `GET /api/v1/ops/stack-diagnosis` 也不应该只返回“人看得懂的摘要”,还要内嵌:
|
||
|
||
- `contract_navigation.primary_contract_key`
|
||
- `contract_navigation.contract_keys`
|
||
- `contract_navigation.detail_endpoint_pattern`
|
||
|
||
以及每条 entry / issue 对应的 contract hints。
|
||
|
||
现在这条规则应继续扩展到:
|
||
|
||
- `GET /api/v1/ops/driver-feed`
|
||
- `GET /api/v1/ops/activity-stream`
|
||
|
||
也就是说,不只是 Codex 摘要层,连“驾驶主线”和“统一活动流”本身也必须能直接给出 contract navigation,页面、CLI、海外 Codex 才能真正顺着协议跳转,而不是再各自猜一遍。
|
||
|
||
这样海外 Codex 驾驶员在收到“建议动作”或“总检缺口”后,下一步不是靠 prompt 猜协议,而是可以直接按 contract key 去拉:
|
||
|
||
- `GET /api/v1/ops/contracts/{contract_key}`
|
||
|
||
这才是真正可持续的“驾驶层”,而不是一次性的提示词工程。
|
||
|
||
现在这条链路还要再收口一层:
|
||
|
||
- `GET /api/v1/ops/go-live-summary`
|
||
- 作为页面、CLI、海外 Codex 共用的稳定“上线收口摘要”
|
||
- `GET /api/v1/ops/codex-brief`
|
||
- 继续返回 `go_live_summary`
|
||
- `GET /api/v1/ops/driver-feed`
|
||
- 继续返回 `go_live_summary`
|
||
|
||
也就是说,海外 Codex 驾驶员的固定起手式现在应变成:
|
||
|
||
1. 先读 `go-live-summary`
|
||
2. 再读 `codex-brief`
|
||
3. 真要解释阻断原因、看主车道、抄命令时,再下钻 `stack-diagnosis`
|
||
|
||
这样 Codex 不再需要从零拼“当前能不能上线”,而是先接住一份稳定结论,再进入解释层和动作层。
|
||
|
||
这里还要继续固定一个口径:
|
||
|
||
- `go_live_summary.go_live_status`
|
||
- 回答当前是否已经进入统一收口 / 联调 / 复核车道
|
||
- `go_live_summary.publish_status / publish_ready`
|
||
- 回答当前是否已经满足正式发布门禁
|
||
|
||
同时还要把“接入缺口是否已经影响发版门禁”的字段也固定下来,避免海外 Codex 继续自己拼 launchpad gap:
|
||
|
||
- `go_live_summary.launchpad_onboarding_bootstrap_pending_nodes`
|
||
- `go_live_summary.launchpad_onboarding_acceptance_ready_nodes`
|
||
- `go_live_summary.launchpad_recommended_target_node_code`
|
||
- `go_live_summary.launchpad_recommended_recovery_label`
|
||
- `go_live_summary.launchpad_recommended_recovery_summary`
|
||
|
||
这样海外 Codex 的默认判断就应该变成:
|
||
|
||
1. 如果 `publish_status = blocked`
|
||
- 先看硬阻断
|
||
2. 如果 `publish_status = attention`
|
||
- 再优先看 launchpad 是否只是节点接管缺口
|
||
3. 如果 launchpad 已经给出
|
||
- `recommended_target_node_code`
|
||
- `recommended_recovery_summary`
|
||
那就直接进入节点级恢复动作
|
||
|
||
而不是再去从 `release_launchpad.worker_rollout_preview.policy_preview.release_gate.rows` 里二次翻译一次。
|
||
|
||
也就是说海外 Codex 的第一轮判断必须先分清:
|
||
|
||
- “现在可以继续收口”
|
||
- 和 “现在可以正式发版”
|
||
|
||
这两个结论不能再混成一句模糊建议。
|
||
|
||
这里再补一个已经适合前后端直接消费的收口字段:
|
||
|
||
- `driver-feed.automation_coverage`
|
||
- `codex-brief.automation_coverage`
|
||
|
||
它们现在应该统一返回至少这些统计:
|
||
|
||
- `safe_auto_total`
|
||
- `guarded_auto_total`
|
||
- `mixed_total`
|
||
- `ui_only_total`
|
||
- `blocked_total`
|
||
- `preview_only_total`
|
||
- `backend_handled_total`
|
||
- `execution_ready_total`
|
||
- `human_dependency_total`
|
||
- `launch_status`
|
||
- `launch_ready`
|
||
|
||
这组字段的定位要固定:
|
||
|
||
- `automation_level_counts / recommendation_counts`
|
||
回答“当前动作池的自动化构成”
|
||
- `preview_only_total`
|
||
回答“现在有多少动作虽然可自动跑,但本质仍是只读预览/聚焦/审阅”
|
||
- `backend_handled_total`
|
||
回答“当前驾驶主线里有多少动作已经真正后端化,不再依赖人工进页面”
|
||
- `execution_ready_total`
|
||
回答“此刻可以直接执行或确认后执行的动作总数”
|
||
- `human_dependency_total`
|
||
回答“此刻仍需要人工复核、进入工作区、或先排阻断的动作总数”
|
||
- `launch_status / launch_ready`
|
||
给页面、CLI、Codex 一个统一的自动化侧收口判断,而不是每层再各自猜
|
||
|
||
这样后续前端顶部摘要、Codex 驾驶提示、CLI 巡检输出,都可以共享同一套“自动化覆盖率”口径。
|
||
|
||
这里还要固定一个前端交互约束,避免页面重新退回“按钮点了只弹几条 toast”的碎片状态:
|
||
|
||
- Ops Center 首屏的
|
||
- 执行默认下一步
|
||
- 定位下一步
|
||
- 看下一步契约
|
||
- 进入主处理面板
|
||
- 复制收口命令
|
||
- 复制快检命令
|
||
- 这些动作都应统一回到
|
||
- `驾驶回执条`
|
||
|
||
也就是说,首屏动作执行后,页面应该统一返回:
|
||
|
||
- 成功
|
||
- 关注
|
||
- 阻断
|
||
|
||
三类结构化回执,而不是:
|
||
|
||
- 有的只弹 toast
|
||
- 有的静默跳转
|
||
- 有的打开抽屉但没有说明
|
||
|
||
这样值班时第一屏不只是“能点动作”,还必须能在第一屏立即知道:
|
||
|
||
- 动作是否已经生效
|
||
- 当前是否已经进入下一个处理面板
|
||
- 还是仍然缺少上下文 / 需要人工继续处理
|
||
|
||
同时,`doctor-export / doctor-decision` 现在也不应只返回:
|
||
|
||
- `required_failures`
|
||
- `optional_unavailable`
|
||
- `recommended_commands`
|
||
|
||
还要一起返回:
|
||
|
||
- `scene_log_reports_total`
|
||
- `scene_log_reports_ok`
|
||
- `scene_log_status_counts`
|
||
- `scene_log_reports`
|
||
|
||
这样海外 Codex 读取一份 `manifest.json` 或 `doctor-decision` 摘要时,不只是知道“总检建议去看某台节点”,还知道:
|
||
|
||
- 关键节点现场日志附件有没有真正打出来
|
||
- 打出来的是 `healthy / full_capture`
|
||
还是 `waiting_sample / missing_sample`
|
||
- 下一步应该继续看 `driver-feed`
|
||
还是直接下钻具体 `scene-node-log`
|
||
|
||
同时,在线驾驶层本身现在也应固定暴露:
|
||
|
||
- `driver-feed.scene_log_observation`
|
||
- `codex-brief.scene_log_observation`
|
||
|
||
这两个字段不是替代 `doctor-export` 附件,而是给“当前这一刻”的在线控制面提供统一口径:
|
||
|
||
- 现场日志是否关闭
|
||
- 是否已经开启但仍在等样本
|
||
- 当前最适合继续下钻的节点是谁
|
||
- 对应的正式 `focus_ref` 是什么
|
||
|
||
这样离线交接包看 `scene_log_reports`,在线驾驶层看 `scene_log_observation`,职责就完全分开了。
|
||
|
||
同时,页面侧为了减少额外请求,现在也应优先复用 `GET /api/v1/ops/runbook` 自带的:
|
||
|
||
- `primary_resolution`
|
||
- `secondary_resolution`
|
||
|
||
也就是:
|
||
|
||
- 页面首屏直接使用 runbook 内嵌的解析快照
|
||
- CLI / Codex / 自动驾驶器在需要单独复核某条路径时,再额外调用 `resolve`
|
||
|
||
这样“运行手册快照”和“单条路径即时解析”就有了清晰分工,不会每个入口都反复打一轮解析请求。
|
||
|
||
当前还额外补了一个最小任务闭环:
|
||
|
||
- 可登记托管节点
|
||
- 可创建 `ops job`
|
||
- 可查看 `ops job` 执行记录
|
||
- 当前节点可先本机即时执行部分 `runtime.*` 动作
|
||
|
||
这让“后台按钮触发 -> 标准任务留痕”已经开始成型,而不是继续堆零散脚本。
|
||
|
||
当前运维中枢还补了一层很关键的“批量巡检捷径”:
|
||
|
||
- 真正参与检测节点
|
||
- 在线未参与节点
|
||
- 全部有效执行节点
|
||
|
||
它们不会直接执行 shell,而是把目标节点批量预填到 `diagnostics.collect` 模板里,再统一创建 `ops job`。
|
||
|
||
这个设计的意义是:
|
||
|
||
- 页面先把“节点分组口径”统一好
|
||
- Codex 和后台按钮复用同一套动作模型
|
||
- 后续节点变多时,不需要每次人工挑选机器
|
||
|
||
当前这层快捷入口只纳入:
|
||
|
||
- 已纳管
|
||
- 已启用
|
||
- Node Agent 在线
|
||
- 当前属于有效执行节点
|
||
|
||
这样能避免“页面看起来能点,但其实任务根本发不到节点”的假动作。
|
||
|
||
并且这层已经不只是“打开模板”,还开始支持标准巡检序列:
|
||
|
||
- `health.snapshot`
|
||
- `logs.collect`
|
||
- `diagnostics.collect`
|
||
|
||
也就是一键把“健康快照 -> Worker 日志 -> 诊断包”整套任务批量排进 `ops job` 队列。
|
||
|
||
这样后续无论:
|
||
|
||
- 海外 Codex 自动判断
|
||
- 还是后台按钮人工触发
|
||
|
||
都复用同一套巡检动作编排,而不是再写新的临时脚本。
|
||
|
||
现在 OpsCenter 还要继续并入“执行现场”:
|
||
|
||
- 直接看真正参与检测节点
|
||
- 直接看在线但未参与的待命节点
|
||
- 直接看远端日志回传当前是关闭 / 关键 / 全量
|
||
- 并且在同一页上切换日志回传模式
|
||
|
||
也就是说,海外驾驶舱不应该要求操作者再切去 Runtime 页面拼状态,而要在运维中枢里直接完成“观察现场 -> 切日志回传 -> 下发标准巡检”这一整段动作。
|
||
|
||
同时运维中枢开始具备第一版“驾驶建议卡”:
|
||
|
||
- 首个缺口节点优先执行接入收口 / 接管验收
|
||
- 先补现场日志回传
|
||
- 先看真正参与检测的节点
|
||
- 再排查在线未参与节点
|
||
- 最后进入 Release / Rollout
|
||
|
||
其中“先补现场日志回传”很关键:
|
||
|
||
- 如果参与节点存在,但远端日志回传还没开
|
||
- 驾驶建议应优先让操作者开启关键回传
|
||
- 如果日志回传已开但还没有现场样本
|
||
- 则优先抓 Worker 日志,确认为什么现场过程没被镜像回来
|
||
- 日志回传本身也应该成为正式 contract,而不是只有一个布尔开关:
|
||
- 当前状态是关闭 / 等待样本 / 部分覆盖 / 关键覆盖 / 全量观察
|
||
- 当前参与节点覆盖了几台
|
||
- 哪些参与节点仍未回传样本
|
||
- 下一步建议动作是什么
|
||
|
||
这一步的意义是把“海外 Codex 驾驶员”的判断逻辑,先沉淀成页面里可见、可点、可回执的正式入口。
|
||
|
||
同样,“参与检测节点”也不能只给一个总数,而要继续拆成:
|
||
|
||
- 执行中 / 已领待跑
|
||
- 近窗刚有吞吐
|
||
- 在线待命
|
||
- 负载待确认
|
||
|
||
这样海外控制面看到“在线 3 台、有效执行 3 台”时,才不会误以为这 3 台都在真正做同一种事情。
|
||
|
||
同理,Release / Rollout 也不能只停留在“有没有版本”这一层,而要补成正式门禁对象:
|
||
|
||
- `release_hub.default_rollout_gate`
|
||
- 里面明确给出:
|
||
- 默认 Release 是谁
|
||
- 默认 Rollout 目标节点是谁
|
||
- 当前门禁状态是 `missing_release / release_not_ready / artifact_missing / no_targets / blocked / attention / ready`
|
||
- 当前阻断原因、告警原因、推荐动作
|
||
- 当前 remote-agent 就绪数、巡检通过数
|
||
|
||
这样首页驾驶建议、Release Hub、Codex 自动驾驶、后续后台按钮,才能基于同一份门禁判断,而不是页面自己再拼一套“能不能发版”的逻辑。
|
||
|
||
现在这层还要继续后移:
|
||
|
||
- `GET /api/v1/ops/overview` 不只返回运行摘要
|
||
- 也直接返回 `driver_recommendations`
|
||
- 每条建议带标准化 `action_code`、节点列表和展示文案
|
||
|
||
这样页面只是负责把动作映射到现有按钮,而不是自己再次判断一遍优先级。
|
||
|
||
继续往下一步,就是把能标准化的建议动作直接后端化:
|
||
|
||
- `POST /api/v1/ops/driver-actions/execute`
|
||
- 先覆盖:
|
||
- 开/关现场日志回传
|
||
- 批量标准巡检
|
||
- 批量抓 Worker 日志
|
||
- 批量收诊断包
|
||
|
||
这样页面、脚本、Codex 驾驶员都先走同一个后端执行入口;还不能后端化的动作,再暂时回退到前端交互。
|
||
|
||
并且动作命名也要继续收敛到通用语义:
|
||
|
||
- `run_standard_inspection`
|
||
- `open_worker_logs`
|
||
- `open_diagnostics`
|
||
|
||
不要长期把动作名绑死在 `participating / standby` 这种页面上下文里,否则后续同一动作很难在不同入口复用。
|
||
|
||
现在又继续往后收了一层:
|
||
|
||
- `GET /api/v1/ops/playbooks`
|
||
- `GET /api/v1/ops/playbook-runs`
|
||
- `GET /api/v1/ops/playbook-runs/{run_code}`
|
||
- `GET /api/v1/ops/playbook-runs/{run_code}/events`
|
||
- `GET /api/v1/ops/activity-stream`
|
||
- `POST /api/v1/ops/playbook-runs/{run_code}/rerun`
|
||
- `POST /api/v1/ops/playbook-runs/{run_code}/cancel`
|
||
- `POST /api/v1/ops/playbooks/preview`
|
||
- `POST /api/v1/ops/playbooks/execute`
|
||
|
||
这层不是替代 `ops job`,而是把一组固定的高层运维意图继续往下展开。
|
||
|
||
同时每一次 playbook 执行,不应该只留下零散的子任务,而应该形成一条正式“编排回执”:
|
||
|
||
- 每次执行生成独立 `run_code`
|
||
- 每个展开后的 `ops job` 都挂上同一份 playbook metadata
|
||
- 控制面可以按 `run_code` 重新聚合:
|
||
- 本轮编排是什么
|
||
- 目标节点有哪些
|
||
- 当前卡在哪一步
|
||
- 最近一条可查看事件的任务是哪条
|
||
|
||
这样页面、Codex 驾驶员和后续自动化,都不再需要自己从多条 `ops job` 记录里反推“这一轮到底发生了什么”。
|
||
|
||
继续再往前一步,playbook run 不能只“看”,还要能直接作为运维对象被操作:
|
||
|
||
- 直接按 `run_code` 查看详情
|
||
- 直接按 `run_code` 重跑同一轮编排
|
||
- 直接按 `run_code` 取消当前仍未收口的子任务
|
||
|
||
这样运维中心面对的就不再只是“原子 job 列表”,而是正式的“编排回执对象”。
|
||
|
||
再往前收一层,OpsCenter 还要把:
|
||
|
||
- playbook run
|
||
- standalone ops job
|
||
- rollout
|
||
|
||
统一压成一条“活动流”。
|
||
|
||
这样海外驾驶舱里看到的就不再是三块割裂入口,而是:
|
||
|
||
- 最近发生了什么
|
||
- 这是编排、单任务还是 rollout
|
||
- 当前状态是什么
|
||
- 一键应该跳到哪个详情抽屉
|
||
|
||
这一层已经开始落成:
|
||
|
||
- 后端聚合 `activity-stream`
|
||
- 前端活动流面板直接复用:
|
||
- playbook run 详情抽屉
|
||
- ops job 事件抽屉
|
||
- rollout 任务抽屉
|
||
|
||
最近又补了一层很关键的驾驶口径:
|
||
|
||
- `runbook_sequence`
|
||
|
||
也就是说,统一活动流里现在不只收“已经发生的执行回执”,还会收:
|
||
|
||
- 当前固定标准作业路径此刻解析出的下一步动作快照
|
||
|
||
这样海外控制面看到活动流时,能同时得到两类信息:
|
||
|
||
- 最近现场到底发生了什么
|
||
- 当前更推荐先进入哪条固定路径
|
||
|
||
并且这条 `runbook_sequence` 活动不是新 job,也不是新 rollout,而是:
|
||
|
||
- 对 `ops runbook.control_sequences[*].primary_resolution`
|
||
的时间线化投影
|
||
|
||
它点进去后应直接把页面焦点定位到对应的标准作业路径卡片,而不是再跳去一个无关抽屉。
|
||
|
||
再往前一步,还需要一份正式给“驾驶员”消费的统一结果:
|
||
|
||
- `GET /api/v1/ops/driver-feed`
|
||
|
||
这份 feed 不应该只是页面内部拼接,而要由后端直接给出:
|
||
|
||
- 当前最高优先建议
|
||
- 其他驾驶建议
|
||
- 标准作业路径
|
||
|
||
并且每条都明确声明:
|
||
|
||
- 这是 `driver_action`
|
||
还是
|
||
- `runbook_sequence`
|
||
|
||
这样海外 Codex、后台按钮和 CLI 才能共享一套真正稳定的执行 contract,而不是继续在前端或 prompt 里二次判断。
|
||
|
||
在这层之上,还要再补一层真正适合“海外 Codex 自动驾驶”的判断结果:
|
||
|
||
- `GET /api/v1/ops/codex-brief`
|
||
|
||
这层不是重复造一个 feed,而是在 `driver-feed` 之上补齐:
|
||
|
||
- 这条动作是 `safe_auto`
|
||
- 还是 `guarded_auto`
|
||
- 还是 `mixed`
|
||
- 还是 `ui_only`
|
||
- 或者已经 `blocked`
|
||
|
||
同时直接给出:
|
||
|
||
- 推荐动作口径:
|
||
- `auto_execute`
|
||
- `confirm_then_execute`
|
||
- `resolve_first`
|
||
- `open_ui`
|
||
- `blocked`
|
||
- 最终应命中的 API:
|
||
- `/ops/driver-actions/execute`
|
||
- 或 `/ops/runbook/sequences/{sequence_key}/execute`
|
||
- 请求预览:
|
||
- `action_code / node_codes / action_payload`
|
||
- 或 `sequence_key / secondary / action_payload`
|
||
|
||
这样海外 Codex 就不需要再把“哪些能自动开、哪些必须人工确认、哪些只能进 UI”重新写死在 prompt 里,而是直接消费控制面给出的统一自动驾驶 contract。
|
||
|
||
并且活动流不该只是“堆最近 20 条”,还要具备正式运维视角:
|
||
|
||
- 按 `kind` 筛:
|
||
- playbook run
|
||
- standalone ops job
|
||
- rollout
|
||
- runbook sequence
|
||
- 按 `status` 筛
|
||
- 按关键词搜:
|
||
- 编号
|
||
- 对象
|
||
- 摘要
|
||
- 发起来源
|
||
|
||
这样节点数和动作数上来以后,活动流才能继续保持可用,而不会退化成人工翻时间线。
|
||
|
||
这样后续 Codex 驾驶员与人工操作员共用的就是同一条“最近活动 -> 直接钻取”的驾驶链路。
|
||
|
||
最近又再收一层“可读性 contract”:
|
||
|
||
- `GET /api/v1/ops/playbook-runs` 已支持按 `status`、`group_key`、`query` 过滤
|
||
- 回执聚合结果会直接给出:
|
||
- `focus_level`
|
||
- `focus_step_key`
|
||
- `focus_step_title`
|
||
- `focus_summary`
|
||
- `problem_steps`
|
||
- `active_steps`
|
||
- 前端不再只展示“这轮 run 有几步”,还会直接提示:
|
||
- 当前最该看的步骤是哪一步
|
||
- 它是在执行中,还是已经异常
|
||
- 应该优先去看哪条事件入口
|
||
|
||
这样海外控制面看到的就不是一张“机械回执表”,而是已经带有现场聚焦能力的编排驾驶面板。
|
||
|
||
继续再补一层之后,编排详情也不该只停在“看 step 状态”,还要能直接看整轮事件流:
|
||
|
||
- 不再要求操作者点进每一条子任务再翻事件
|
||
- 控制面可以直接按 `run_code` 拉整轮编排的聚合事件
|
||
- 还能继续按 `step_key`、`node_code` 做二次过滤
|
||
|
||
这样 playbook run 在海外控制面里的形态才完整:
|
||
|
||
- 能看总状态
|
||
- 能看当前焦点
|
||
- 能看每一步
|
||
- 也能直接回放整轮现场事件
|
||
|
||
再往前收一层,顶部“运维驾驶建议”也不该只盯节点和日志,而要开始直接消费 playbook run:
|
||
|
||
- 如果最近存在异常编排,驾驶建议优先提示这轮 `run_code`
|
||
- 建议里直接带上当前焦点步骤
|
||
- 点一下就能打开该轮编排详情或最近事件
|
||
|
||
这样海外控制面看到的就是:
|
||
|
||
- 先告诉你哪轮编排最值得优先处理
|
||
- 再把你直接带到对应的编排现场
|
||
|
||
这才符合“海外 Codex 驾驶员 / 按钮化驾驶舱”的设计目标。
|
||
|
||
再往前一步,驾驶建议还不该只盯 playbook run,本轮已经开始让它继续消费统一活动流:
|
||
|
||
- 如果最近存在异常 `ops job`
|
||
- 或存在异常 / 待审批 `rollout`
|
||
- recommendation 也应直接把这条 activity 顶上来
|
||
- 点一下直接落到对应 `job events` 或 `rollout jobs`
|
||
|
||
也就是说,驾驶建议的优先级已经开始变成:
|
||
|
||
- 先看异常编排
|
||
- 再看异常活动
|
||
- 再处理接管缺口、日志回传和巡检动作
|
||
|
||
这样海外控制面才不是“会推荐很多动作”,而是真正会把操作者先送到最值得处理的现场。
|
||
|
||
再继续收一层,driver action 也不该只返回“handled / unhandled”,而要开始返回正式的 `ui-intent`:
|
||
|
||
- 后端统一决定这次动作是:
|
||
- 直接执行
|
||
- 创建 playbook
|
||
- 还是打开某个界面入口
|
||
- 前端不再自己硬编码“这个 action_code 到底该弹哪个抽屉”
|
||
|
||
例如现在已经开始固化的 intent 方向:
|
||
|
||
- `playbook_run_detail`
|
||
- `playbook_run_latest_events`
|
||
- `job_events`
|
||
- `rollout_jobs`
|
||
- `managed_node_handover`
|
||
- `managed_node_edit`
|
||
- `open_release_dialog`
|
||
- `open_rollout_dialog`
|
||
- `focus_release_hub`
|
||
|
||
这样控制面、Codex 驾驶员、后续自动化脚本三方看到的动作 contract 会越来越一致。
|
||
|
||
这里再补一条新的收口约束:
|
||
|
||
- `focus_release_hub`
|
||
不应只是“打开版本区”的导航动作
|
||
- 它现在还应同时返回结构化 `release_hub_preview`
|
||
至少带:
|
||
- `summary`
|
||
- `launchpad`
|
||
|
||
这样页面仍然可以跳到 Release Hub,但 CLI、Codex、自动化任务即使不进页面,也能继续基于 release hub 摘要判断下一步。
|
||
|
||
同样,`release_package` 在打包自动化真正落地前,也不应继续只是“打开打包面板”:
|
||
|
||
- 页面侧仍可消费 `ui_intent = open_release_dialog`
|
||
- 但后端应同时返回 `release_package_preview`
|
||
例如:
|
||
- `available`
|
||
- `package_name`
|
||
- `release_version_suggestion`
|
||
- `reason`
|
||
|
||
这样海外 Codex 和 CLI 至少能先判断:
|
||
|
||
- 现场是否已经存在可用发布包
|
||
- 建议的版本号是什么
|
||
- 当前卡在“缺包”还是“只是还没进页面确认”
|
||
|
||
例如:
|
||
|
||
- `inspection.standard`
|
||
- `health.snapshot`
|
||
- `logs.collect(worker)`
|
||
- `diagnostics.collect`
|
||
- `scene.logs.key`
|
||
- `logs.collect(worker, 120)`
|
||
- `scene.diagnostics`
|
||
- `diagnostics.collect(200)`
|
||
|
||
这样前端按钮、海外 Codex 驾驶员、后续自动化脚本都不需要自己再手动拼“三连动作”,而是统一复用后端定义的 playbook。
|
||
|
||
现在 OpsCenter 页面也已经开始直接接这层 playbook:
|
||
|
||
- 页面可读取 `playbooks`
|
||
- 页面可做 `playbook preview`
|
||
- 标准巡检主入口优先直接调用 `inspection.standard`
|
||
- 接管后一键验收优先直接调用 `onboarding.acceptance`
|
||
|
||
这意味着“标准巡检”第一次不再由前端自己顺序创建三组模板任务,而是正式走后端编排层。
|
||
|
||
同样的收口方向现在也已经开始覆盖“纳管新节点”与“现场观察”:
|
||
|
||
- `node_onboarding`
|
||
- 主动作:`bootstrap_run`
|
||
- 次动作:`run_acceptance`
|
||
- `scene_observe`
|
||
- 主动作:`run_scene_logs_key`
|
||
- 次动作:`run_scene_logs_full`
|
||
- `standard_inspection`
|
||
- 主动作:`run_standard_inspection`
|
||
- 次动作:`open_diagnostics`
|
||
- `release_progression`
|
||
- Launchpad 就绪时优先:`publish_latest_worker`
|
||
- 只有 Release、但还没形成明确 Launchpad 推荐时:`create_release_rollout_worker`
|
||
|
||
其中发布链要继续严格区分两种动作层级:
|
||
|
||
- `review_smart_rollout_preview / review_control_rollout / fix_rollout_blockers`
|
||
- 属于 `safe_auto`
|
||
- 目标是读 launchpad 预案、看门禁缺口、返回结构化审阅结果
|
||
- `publish_latest_worker / create_*_release_rollout_*`
|
||
- 属于 `guarded_auto`
|
||
- 目标是正式创建发布 / rollout 对象
|
||
- 必须继续要求确认和审计留痕
|
||
|
||
也就是说,Runbook 里的主次步骤已经开始直接落到正式驾驶动作,而不是统一先打开弹窗再让操作者自己决定。
|
||
|
||
也就是说:
|
||
|
||
- 有 Codex 时,它读这些状态后自动帮你挑动作
|
||
- 没 Codex 时,你在后台也能沿着同样的优先级直接点下去
|
||
|
||
再往下一层,运维中枢还需要具备“巡检结果收口面板”:
|
||
|
||
- 不是只会发 `health.snapshot / logs.collect / diagnostics.collect`
|
||
- 而是要按节点把这三类任务最近结果重新聚合
|
||
- 直接看出这台节点是:
|
||
- 已健康收口
|
||
- 仍在执行
|
||
- 存在异常
|
||
- 还没形成巡检记录
|
||
|
||
这样海外控制面才真正像驾驶舱,而不是“按钮发射器”。
|
||
|
||
现在这层已经开始正式后移到后端语义:
|
||
|
||
- `GET /api/v1/ops/overview` 里直接带 `inspection`
|
||
- 也单独提供 `GET /api/v1/ops/inspection-overview`
|
||
- 前端优先消费后端聚合结果,本地计算只作为 fallback
|
||
|
||
这样后续无论是:
|
||
|
||
- 海外 Codex 驾驶员
|
||
- 页面按钮
|
||
- 自动化巡检脚本
|
||
|
||
都读同一份“节点巡检收口状态”,不会再出现页面一套、脚本一套、人工 SQL 又一套的口径分裂。
|
||
|
||
这一层再往前,还应该有“异常节点优先队列”:
|
||
|
||
- 先把巡检失败 / 阻断 / 取消的节点顶上来
|
||
- 再显示仍在执行中的节点
|
||
- 最后才是未形成巡检记录的节点
|
||
|
||
并且日志聚合口径要严格:
|
||
|
||
- 标准巡检只认 Worker 日志
|
||
- 不能把 Node Agent 的临时排障日志混进 Worker 巡检收口
|
||
|
||
### 第 2 步:补 ops jobs
|
||
|
||
这一步后续建议直接以 [ops_job_contract.md](/www/wwwroot/getDomain/docs/schemas/ops_job_contract.md:1) 为正式母本,不再让页面、CLI、Codex、Node Agent 各自定义任务结构。
|
||
|
||
后续新增:
|
||
|
||
- `ops_jobs`
|
||
- `ops_job_steps`
|
||
- `managed_nodes`
|
||
- `node_log_streams`
|
||
|
||
每个动作必须有:
|
||
|
||
- 谁发起
|
||
- 发给哪台机器
|
||
- 目标服务
|
||
- 执行结果
|
||
- stdout/stderr
|
||
- 结构化摘要
|
||
|
||
### 第 3 步:补 node agent
|
||
|
||
Node Agent 第一版建议只做四类动作:
|
||
|
||
- `service.restart`
|
||
- `service.status`
|
||
- `health.check`
|
||
- `logs.collect`
|
||
|
||
先把最常用的远程运维闭环跑通,再逐步扩成:
|
||
|
||
- `deploy.release`
|
||
- `config.render`
|
||
- `diagnostics.collect`
|
||
- `bootstrap.finish`
|
||
|
||
### 第 4 步:补发布与回滚
|
||
|
||
正式收口成:
|
||
|
||
- 海外控制面构建 release 包
|
||
- 节点下载 release
|
||
- 校验 checksum
|
||
- 切换软链
|
||
- 重启服务
|
||
- 失败自动回滚
|
||
|
||
---
|
||
|
||
## 五、Codex 在这里真正扮演什么角色
|
||
|
||
Codex 不应该只是“聊天助手”,而应该是:
|
||
|
||
### 1. 运维驾驶员
|
||
|
||
Codex 读取:
|
||
|
||
- readiness
|
||
- cluster
|
||
- sync-summary
|
||
- debug diagnosis
|
||
- ops overview
|
||
|
||
然后给出:
|
||
|
||
- 当前是网络问题、配置问题、节点未参与、还是同步问题
|
||
- 下一步先拉日志、先重启、先巡检、还是先暂停同步
|
||
|
||
### 2. 动作编排器
|
||
|
||
当 Codex 确认动作后:
|
||
|
||
- 创建 ops job
|
||
- 标准化执行
|
||
- 等待回执
|
||
- 汇总结果
|
||
|
||
### 3. 联调加速器
|
||
|
||
以后你不需要再复制大量日志给我看,而是让 Codex 直接在海外控制面读:
|
||
|
||
- 节点状态
|
||
- 任务结果
|
||
- 聚合日志
|
||
- 诊断包摘要
|
||
|
||
---
|
||
|
||
## 六、你以后理想的操作方式
|
||
|
||
你只需要在海外控制面做三件事:
|
||
|
||
### 1. 配置节点
|
||
|
||
- 节点名称
|
||
- SSH / bootstrap 信息
|
||
- 区域
|
||
- 角色
|
||
- 发布通道
|
||
|
||
### 2. 看状态
|
||
|
||
- 哪些节点在线
|
||
- 哪些节点是有效执行节点
|
||
- 哪些节点正在领任务
|
||
- 哪些节点只是在线待命
|
||
- 哪些节点同步失败
|
||
|
||
### 3. 点动作
|
||
|
||
- 安装节点
|
||
- 更新节点
|
||
- 重启节点
|
||
- 拉日志
|
||
- 巡检
|
||
- 收诊断包
|
||
- 治理 Node Agent 回执积压 / 死信
|
||
|
||
如果装了 Codex,就再多一步:
|
||
|
||
- 让 Codex 自动判断“该点哪个动作”
|
||
|
||
## 六点五、回执队列已经进入统一驾驶入口
|
||
|
||
当前 Node Agent 回执队列不再只是“后端看得见”,而是已经进入统一驾驶面:
|
||
|
||
- OpsCenter 托管节点表可以直接打开“回执队列治理”抽屉
|
||
- `driver_recommendations` 遇到 `dead_letter / retrying` 时,会优先下发标准队列治理动作
|
||
- 海外单入口 CLI 也可以直接查看、冲刷、重放和丢弃
|
||
|
||
这意味着:
|
||
|
||
- 没有 Codex 时,人工也能在海外控制面闭环处理
|
||
- 有 Codex 时,Codex 不需要自己发明死信处理逻辑
|
||
- 页面、CLI、Codex 都围绕同一组 `ops job` 入口治理回执队列
|
||
|
||
当前统一 CLI 入口已经支持:
|
||
|
||
```bash
|
||
cd /opt/domaincheck/domain-api
|
||
|
||
# 查看某台节点当前回执队列状态
|
||
bash domain-api/deploy/multi-region/drive_ops_center.sh queue-status mainland-worker-01
|
||
|
||
# 只看可见死信头部记录
|
||
bash domain-api/deploy/multi-region/drive_ops_center.sh queue-records mainland-worker-01 dead_letter
|
||
|
||
# 立即冲刷积压回执
|
||
bash domain-api/deploy/multi-region/drive_ops_center.sh queue-flush mainland-worker-01 20
|
||
|
||
# 重放当前可见死信
|
||
bash domain-api/deploy/multi-region/drive_ops_center.sh queue-replay mainland-worker-01 20
|
||
|
||
# 对头部死信执行单条动作
|
||
bash domain-api/deploy/multi-region/drive_ops_center.sh queue-replay-record mainland-worker-01 event-ops-123-2
|
||
bash domain-api/deploy/multi-region/drive_ops_center.sh queue-discard-record mainland-worker-01 event-ops-123-2 "确认已人工归档"
|
||
```
|
||
|
||
当前阶段仍然要严格坚持:
|
||
|
||
- 所有动作都创建正式 `ops job`
|
||
- 当前只操作 `record_visibility=head_only` 的可见头部记录
|
||
- 不直接 SSH 到节点手改队列文件
|
||
|
||
这样以后即使从 `head_only` 扩到“远端全量记录正式投影”,也只是扩展可见范围,不需要推翻当前治理模型。
|
||
|
||
## 六点六、现场观察 runbook 也不再依赖弹窗
|
||
|
||
`scene_observe` 这条标准作业路径现在也开始从“打开 playbook 弹窗”收口到“直接执行正式动作”:
|
||
|
||
- 主动作:`run_scene_logs_key`
|
||
- 次动作:`run_scene_logs_full`
|
||
- 两者都直接落到标准 `ops playbook` 执行链,而不是先让操作者进入模板弹窗二次确认
|
||
|
||
这样海外单脑在排查“谁在跑、为什么卡住、日志有没有回来”时,已经可以直接从 runbook 进入执行态,Codex 和后台按钮也能复用同一条现场观察链路。
|
||
|
||
---
|
||
|
||
## 七、当前最优结论
|
||
|
||
当前最优路线不是继续堆更多手工排查命令,而是:
|
||
|
||
1. 以海外主机为唯一运维入口
|
||
2. 用 `ops api + ops jobs + node agent` 接管所有大陆节点
|
||
3. SSH 只做 bootstrap,不做日常主链路
|
||
4. Codex 作为智能驾驶员可选增强,但不是唯一依赖
|
||
5. 没有 Codex 时,后台按钮也能完整跑通
|
||
|
||
这条路线的优点是:
|
||
|
||
- 节点越多越省心
|
||
- 跨地域调试成本显著下降
|
||
- 可以沉淀成正式运维平台,而不是临时联调脚本集合
|