1164 lines
25 KiB
Markdown
1164 lines
25 KiB
Markdown
# 23 domainCheck 终局运维架构设计:海外单脑控制面
|
||
|
||
## 一、先回答最核心的问题:`ops job` 是什么
|
||
|
||
`ops job` 不是一条 shell 命令,也不是“点一下按钮马上执行”的临时动作。
|
||
|
||
`ops job` 的本质是:
|
||
|
||
> 一条可审计、可编排、可回放、可中断、可回滚的运维意图记录。
|
||
|
||
它表达的是:
|
||
|
||
- 谁发起了什么目标
|
||
- 目标作用到哪些节点
|
||
- 按什么策略执行
|
||
- 分成哪些步骤
|
||
- 每一步执行结果是什么
|
||
- 有没有失败
|
||
- 失败后是否回滚
|
||
- 最终系统是否达成目标状态
|
||
|
||
也就是说:
|
||
|
||
- shell 是“执行手段”
|
||
- `ops job` 是“运维对象”
|
||
|
||
最终系统里,不应该由前端、Codex、定时器直接执行 shell。
|
||
|
||
它们都只能做一件事:
|
||
|
||
> 创建 `ops job`
|
||
|
||
然后由专门的执行器去消费这个 `ops job`。
|
||
|
||
---
|
||
|
||
## 二、为什么最终不要“直接执行 shell”
|
||
|
||
因为“直接执行 shell”有 7 个天然缺陷:
|
||
|
||
### 1. 无法审计
|
||
|
||
你知道执行了什么命令,但不知道:
|
||
|
||
- 谁触发的
|
||
- 为什么触发
|
||
- 是否按预期执行完
|
||
- 执行前后的系统状态
|
||
|
||
### 2. 无法标准化
|
||
|
||
今天你执行:
|
||
|
||
- `systemctl restart domaincheck-worker`
|
||
|
||
明天可能要补:
|
||
|
||
- 重启前健康检查
|
||
- 失败后重试
|
||
- 失败后回滚
|
||
- 成功后采样验证
|
||
|
||
如果直接跑 shell,这些逻辑会散落在脚本、前端、人工脑子里。
|
||
|
||
### 3. 无法并发调度
|
||
|
||
当节点从 `2` 台增加到 `10` 台,直接 shell 无法优雅表达:
|
||
|
||
- 先更新 controller
|
||
- 再灰度更新一台 worker
|
||
- 观察 10 分钟
|
||
- 再滚动更新剩余节点
|
||
|
||
### 4. 无法做回滚
|
||
|
||
shell 通常只描述“怎么做”,不描述“失败怎么办”。
|
||
|
||
### 5. 无法限流和保护
|
||
|
||
比如:
|
||
|
||
- 同一时间最多更新 1 台 controller
|
||
- 同一地域最多重启 2 台 worker
|
||
- 正在跑检测的节点禁止强更
|
||
|
||
这些都不是 shell 擅长的层面。
|
||
|
||
### 6. 无法与 Codex 协作
|
||
|
||
Codex 可以判断,但最终必须落到稳定、标准、可追踪的动作模型,否则还是人工时代。
|
||
|
||
### 7. 无法沉淀成平台
|
||
|
||
你要的不是“几个脚本”,而是“海外一台机器接管全部大陆机器”的正式运维平台。
|
||
|
||
平台核心对象必须是 `ops job`,不是 shell。
|
||
|
||
但这里还有一个非常重要的配套原则:
|
||
|
||
- 不直接执行 shell
|
||
- 不等于只会给出“你再去跑这几条命令”的人工建议
|
||
|
||
真正终局形态里,还需要一层:
|
||
|
||
> 组合恢复入口
|
||
|
||
比如“远端日志回传恢复”这类高频动作,就不应该让人工自己拼:
|
||
|
||
1. 开关键回传
|
||
2. 看 overview 有没有生效
|
||
3. 再决定去看哪台节点日志
|
||
|
||
而应该被固化成正式单入口,例如:
|
||
|
||
```bash
|
||
bash domain-api/deploy/multi-region/drive_ops_center.sh log-sync-recover
|
||
```
|
||
|
||
它表达的不是一条 shell,而是一条标准运维意图:
|
||
|
||
- 执行恢复动作
|
||
- 读取复核结果
|
||
- 输出下一跳命令
|
||
|
||
也就是说,终局平台既不是“裸 shell”,也不是“只有抽象 job 没有现场入口”,而是:
|
||
|
||
- 底层执行对象是 `ops job`
|
||
- 上层驾驶入口是组合意图命令
|
||
|
||
这样海外单脑控制面、后台按钮、Codex 驾驶员,才能既保持标准化,又保持现场处理效率。
|
||
|
||
同理,“运行中 API 还是旧代码 / 旧 schema” 这类问题,也不应该再退回到人工只记一条:
|
||
|
||
```bash
|
||
systemctl restart domaincheck-api
|
||
```
|
||
|
||
正式平台里它应该被提升为组合恢复入口,例如:
|
||
|
||
```bash
|
||
bash domain-api/deploy/multi-region/drive_ops_center.sh runtime-refresh-recover http://127.0.0.1:8100
|
||
```
|
||
|
||
如果当前不是只做单点刷新,而是要把:
|
||
|
||
- 运行时刷新
|
||
- 总检复核
|
||
- 上线门禁
|
||
- 下一跳动作判断
|
||
|
||
一起串成一条标准联调车道,那么入口应该继续提升为:
|
||
|
||
```bash
|
||
bash domain-api/deploy/multi-region/drive_ops_center.sh go-live-recover http://127.0.0.1:8100
|
||
```
|
||
|
||
它表达的依然不是“直接 shell”,而是:
|
||
|
||
- 先识别 runtime drift
|
||
- 再执行统一恢复
|
||
- 再回读 go-live / stack diagnosis contract
|
||
- 最后输出主动作与复核动作
|
||
|
||
这样页面、CLI、Codex 驾驶员就不会再次退回到:
|
||
|
||
- 人工猜该不该重启
|
||
- 人工猜重启完先看哪个接口
|
||
- 人工自己拼下一跳命令
|
||
|
||
而是继续保持“上层是组合意图入口、底层才是执行手段”的正式平台结构。
|
||
|
||
同样,“节点接管缺口恢复”也不应该拆成散落在脑子里的三四步:
|
||
|
||
- 先看哪台节点有缺口
|
||
- 再看 handover 详情
|
||
- 再生成 bootstrap plan
|
||
- 再手工整理下一步命令
|
||
|
||
它同样应该被固化成正式组合入口,例如:
|
||
|
||
```bash
|
||
bash domain-api/deploy/multi-region/drive_ops_center.sh agent-gap-recover
|
||
```
|
||
|
||
它表达的依然不是“直接 SSH 干活”,而是一条标准运维意图:
|
||
|
||
- 找到首个接管缺口节点
|
||
- 读取该节点 handover 状态
|
||
- 生成该节点接入方案
|
||
- 输出该节点当前 onboarding 阶段
|
||
- 输出后续检查与执行建议
|
||
|
||
为了不让值班同事继续在脑子里手动拼:
|
||
|
||
- `node-handover`
|
||
- `node-bootstrap-plan`
|
||
- `onboarding.acceptance`
|
||
|
||
还应该有一个节点级入口:
|
||
|
||
```bash
|
||
bash domain-api/deploy/multi-region/drive_ops_center.sh node-onboarding http://127.0.0.1:8100 mainland-worker-01
|
||
```
|
||
|
||
它负责把单节点当前到底处于:
|
||
|
||
- 待补资料
|
||
- 待生成 bootstrap
|
||
- 待执行 bootstrap
|
||
- 可进入 `onboarding.acceptance`
|
||
|
||
统一压成一个节点级结果。
|
||
|
||
并且当节点已经进入 `acceptance_ready` 时,不应该再让值班同事自己拼 playbook 参数,而是继续直接给出:
|
||
|
||
```bash
|
||
bash domain-api/deploy/multi-region/drive_ops_center.sh node-acceptance-plan http://127.0.0.1:8100 mainland-worker-01
|
||
bash domain-api/deploy/multi-region/drive_ops_center.sh node-acceptance-run http://127.0.0.1:8100 mainland-worker-01 ops-center
|
||
```
|
||
|
||
也就是:
|
||
|
||
- 先看这次验收将创建哪些标准化任务
|
||
- 再把验收统一签发进 ops job / playbook run 体系
|
||
|
||
同理,bootstrap 也不应该只停在“生成脚本块”,还应该有:
|
||
|
||
```bash
|
||
bash domain-api/deploy/multi-region/drive_ops_center.sh node-bootstrap-preview http://127.0.0.1:8100 mainland-worker-01
|
||
bash domain-api/deploy/multi-region/drive_ops_center.sh node-bootstrap-run http://127.0.0.1:8100 mainland-worker-01 ops-center
|
||
```
|
||
|
||
这样:
|
||
|
||
- 需要人工落地脚本时,用 `node-bootstrap-plan`
|
||
- 需要纳入标准工单追踪时,用 `node-bootstrap-run`
|
||
- 需要 ready 之后做验收时,用 `node-acceptance-run`
|
||
|
||
再往上还应该有一个真正的节点级自动恢复入口:
|
||
|
||
```bash
|
||
bash domain-api/deploy/multi-region/drive_ops_center.sh node-recover http://127.0.0.1:8100 mainland-worker-01
|
||
bash domain-api/deploy/multi-region/drive_ops_center.sh node-recover http://127.0.0.1:8100 mainland-worker-01 confirm ops-center
|
||
```
|
||
|
||
它的职责不是提供新的能力,而是替值班同事做状态分流:
|
||
|
||
- 当前还在接入阶段,就转向 `node-bootstrap-run`
|
||
- 当前已经进入验收窗口,就转向 `node-acceptance-run`
|
||
- 默认先预览决策,`confirm` 后再真正执行
|
||
|
||
这样平台里真正被沉淀下来的就不是“几条应急命令”,而是:
|
||
|
||
- `log-sync-recover`
|
||
- `agent-gap-recover`
|
||
- `node-onboarding`
|
||
- `node-recover`
|
||
- 后续还会继续有 `release-rollout-recover`
|
||
- `delivery-queue-recover`
|
||
|
||
也就是说,终局平台里的高频运维动作,最终都应该沉淀为:
|
||
|
||
- 组合恢复入口
|
||
- 正式 preview / execute contract
|
||
- 一次动作只执行一次
|
||
|
||
特别是 `node-recover` 这类入口,后续必须固定成:
|
||
|
||
- preview 走 `onboarding/recovery/preview`
|
||
- confirm 走 `onboarding/recovery/execute`
|
||
|
||
如果后端 execute 已经成功接单,CLI / 页面 / Codex 不允许再补跑一次底层:
|
||
|
||
- `node-bootstrap-run`
|
||
- `node-acceptance-run`
|
||
|
||
因为这已经不是“展示问题”,而是会直接造成重复创建 `ops job / playbook run` 的正式执行错误。
|
||
|
||
这里再补一个页面落地约束,避免海外单脑控制面首屏继续堆四五套重复摘要:
|
||
|
||
- Ops Center 首屏必须先有一块
|
||
- `单脑驾驶舱首屏`
|
||
- 它不是新的数据源
|
||
- 而是把现有
|
||
- `go-live-summary`
|
||
- `stack-diagnosis`
|
||
- `driver-feed`
|
||
- `codex-brief.automation_coverage`
|
||
统一压成一屏结论
|
||
|
||
首屏至少应固定展示:
|
||
|
||
- 上线收口状态
|
||
- 发布闸门状态
|
||
- 自动化收口状态
|
||
- 主处理车道
|
||
- 默认下一步
|
||
- 后端接管覆盖
|
||
- 观察层完整度
|
||
- 现场日志覆盖度
|
||
|
||
并且页面分层必须明确:
|
||
|
||
- 首屏负责
|
||
- 判断
|
||
- 决策
|
||
- 默认下一步
|
||
- 一键进入处理面板
|
||
- 下方详情区负责
|
||
- 解释原因
|
||
- 展开问题清单
|
||
- 展示推荐动作与命令
|
||
- 提供 contract 下钻
|
||
|
||
也就是说,下方区块不应该再和首屏重复堆一遍相同按钮,而应明确退到“详情 / 复核 / 下钻”角色。
|
||
|
||
这样值班时第一眼先回答四个问题:
|
||
|
||
1. 现在能不能上线
|
||
2. 现在能不能正式发版
|
||
3. 现在是不是已经进入自动化可接管状态
|
||
4. 现在默认下一步到底是什么
|
||
|
||
然后才继续下钻到:
|
||
|
||
- 问题清单
|
||
- 推荐动作
|
||
- job / playbook / rollout 细节
|
||
|
||
也就是说,页面首屏本身就应该体现“海外单脑”的产品形态,而不是只把多个接口原样堆到一起。
|
||
|
||
> 标准组合恢复入口
|
||
|
||
而不是重新退化回人工 shell 时代。
|
||
|
||
这里还要固定一个已经进入实现层的动作口径:
|
||
|
||
- 如果后端已经把首个缺口节点收敛成 `bootstrap_run`
|
||
- 页面、CLI、Codex 都优先显示“跑接入收口”
|
||
- 如果后端已经把首个缺口节点收敛成 `run_acceptance`
|
||
- 页面、CLI、Codex 都优先显示“跑接管验收”
|
||
- `fix_managed_nodes`
|
||
- 仅保留为兜底入口
|
||
- 不能再覆盖已经明确收敛的单节点恢复动作
|
||
|
||
---
|
||
|
||
## 三、最高级方案的总目标
|
||
|
||
最终形态不是“海外后台 + 若干工具脚本”,而是:
|
||
|
||
> 一套以海外控制面为唯一运维大脑、以 `ops job` 为核心对象、以节点 agent 为标准执行器、以 Codex 为智能驾驶员的正式运维平台。
|
||
|
||
一句话理解:
|
||
|
||
- 海外控制面负责“决策、编排、发布、审计、汇聚”
|
||
- 大陆节点负责“执行、回传、承载业务”
|
||
- Codex 负责“分析、建议、触发”
|
||
|
||
---
|
||
|
||
## 四、终局架构分层
|
||
|
||
建议直接按 8 层设计。
|
||
|
||
### 1. Control Plane 控制面
|
||
|
||
部署在海外主机。
|
||
|
||
职责:
|
||
|
||
- Web UI
|
||
- API
|
||
- 运维中心
|
||
- 节点目录
|
||
- 发布中心
|
||
- 日志中心
|
||
- 审计中心
|
||
|
||
它是唯一入口。
|
||
|
||
### 2. Intent Layer 意图层
|
||
|
||
所有动作先变成意图:
|
||
|
||
- 新增节点
|
||
- 安装节点
|
||
- 更新节点
|
||
- 重启服务
|
||
- 拉取日志
|
||
- 采集诊断
|
||
- 启动检测
|
||
- 暂停检测
|
||
- 回滚版本
|
||
|
||
这些意图统一落成 `ops job`。
|
||
|
||
### 3. Workflow Engine 工作流层
|
||
|
||
把一个运维动作拆成步骤和状态机。
|
||
|
||
例如 `deploy.release`:
|
||
|
||
1. 预检
|
||
2. 下载发布包
|
||
3. 校验 checksum
|
||
4. 解压到 releases
|
||
5. 切换 current
|
||
6. 重启服务
|
||
7. 健康检查
|
||
8. 标记成功
|
||
9. 失败则回滚
|
||
|
||
这层不关心 shell 细节,只关心工作流编排。
|
||
|
||
### 4. Scheduler 调度层
|
||
|
||
决定:
|
||
|
||
- 哪个 job 先执行
|
||
- 哪些节点能执行
|
||
- 是否需要分批
|
||
- 是否需要串行
|
||
- 是否超过并发上限
|
||
- 是否落在维护窗口
|
||
|
||
### 5. Executor 执行器层
|
||
|
||
真正执行动作的不是前端,也不是 Codex,而是执行器。
|
||
|
||
执行器分 3 类:
|
||
|
||
- `node-agent executor`
|
||
- `release executor`
|
||
- `diagnostic executor`
|
||
|
||
兜底再保留:
|
||
|
||
- `ssh rescue executor`
|
||
|
||
### 6. Node Agent 节点代理层
|
||
|
||
每台大陆节点都跑一个常驻 `domaincheck-node-agent`。
|
||
|
||
职责:
|
||
|
||
- 主动注册
|
||
- 主动心跳
|
||
- 拉取待执行 job
|
||
- 本地执行命令
|
||
- 采集 stdout/stderr
|
||
- 推送结构化结果
|
||
- 推送日志和诊断包
|
||
|
||
### 7. Artifact & Release 发布层
|
||
|
||
发布必须是不可变版本制。
|
||
|
||
不能把正式运维建立在:
|
||
|
||
- 节点直接 `git pull`
|
||
- 节点工作区可能脏
|
||
- root/www 用户混跑
|
||
|
||
正式模型应该是:
|
||
|
||
- 海外控制面构建 release 包
|
||
- release 包有版本号和 checksum
|
||
- 节点只下载、校验、切换
|
||
- 回滚也只是在 release 之间切换
|
||
|
||
### 8. Observability 观测与审计层
|
||
|
||
所有动作必须产生:
|
||
|
||
- 事件
|
||
- 日志
|
||
- 结构化结果
|
||
- 诊断包
|
||
- 审计记录
|
||
|
||
这层既给前端看,也给 Codex 看。
|
||
|
||
---
|
||
|
||
## 五、`ops job` 的正式对象模型
|
||
|
||
### 1. 一个 `ops job` 至少包含这些字段
|
||
|
||
- `job_code`
|
||
- `job_type`
|
||
- `requested_by`
|
||
- `source`
|
||
- `priority`
|
||
- `target_selector`
|
||
- `execution_policy`
|
||
- `desired_state`
|
||
- `payload`
|
||
- `status`
|
||
- `plan`
|
||
- `result`
|
||
- `created_at`
|
||
- `started_at`
|
||
- `finished_at`
|
||
|
||
### 2. `ops job` 的 5 个核心部分
|
||
|
||
#### A. Intent
|
||
|
||
用户真正想做什么。
|
||
|
||
例如:
|
||
|
||
- `service.restart`
|
||
- `deploy.release`
|
||
- `node.bootstrap`
|
||
|
||
#### B. Selector
|
||
|
||
作用到谁。
|
||
|
||
例如:
|
||
|
||
- 指定节点
|
||
- 指定 region=mainland
|
||
- 指定 role=worker
|
||
- 指定 `hybrid=true`
|
||
|
||
#### C. Policy
|
||
|
||
怎么执行。
|
||
|
||
例如:
|
||
|
||
- 串行
|
||
- 每批 1 台
|
||
- 失败即停止
|
||
- 健康检查失败自动回滚
|
||
|
||
#### D. Plan
|
||
|
||
实际拆出来的步骤。
|
||
|
||
例如:
|
||
|
||
- 预检
|
||
- 执行
|
||
- 验证
|
||
- 回滚
|
||
|
||
#### E. Result
|
||
|
||
最终结果和证据。
|
||
|
||
例如:
|
||
|
||
- 成功 / 失败 / 部分成功
|
||
- stdout / stderr 摘要
|
||
- 健康检查结果
|
||
- 诊断包链接
|
||
|
||
---
|
||
|
||
## 六、`ops job` 的状态机
|
||
|
||
建议不要只用简单的 `queued/running/success/failed`。
|
||
|
||
正式版建议:
|
||
|
||
- `draft`
|
||
- `approved`
|
||
- `queued`
|
||
- `planning`
|
||
- `scheduled`
|
||
- `dispatching`
|
||
- `running`
|
||
- `verifying`
|
||
- `partially_succeeded`
|
||
- `succeeded`
|
||
- `rollback_running`
|
||
- `rolled_back`
|
||
- `failed`
|
||
- `cancelled`
|
||
- `timed_out`
|
||
|
||
这样后续你看后台时,能明确知道卡在哪一层。
|
||
|
||
---
|
||
|
||
## 七、`ops job` 不是单步骤,而是 DAG 工作流
|
||
|
||
最高级方案里,一个 job 不应只是一条线性步骤,而应支持 DAG。
|
||
|
||
例如“更新大陆两台 worker”:
|
||
|
||
- 先跑公共预检
|
||
- 再更新 `mainland-worker-01`
|
||
- 成功后更新 `mainland-controller-01` 的 worker 部分
|
||
- 两边都成功后再做集群验证
|
||
|
||
有些步骤可以并行,有些必须串行。
|
||
|
||
所以正式设计应支持:
|
||
|
||
- `ops_job_steps`
|
||
- `depends_on_step_id`
|
||
- `retry_policy`
|
||
- `timeout_seconds`
|
||
- `rollback_step_id`
|
||
|
||
---
|
||
|
||
## 八、节点不再是“机器”,而是“受控资源”
|
||
|
||
最高级方案里,要把节点建模成受控资源,而不是一堆 IP。
|
||
|
||
每个节点建议有:
|
||
|
||
- `node_code`
|
||
- `region`
|
||
- `role`
|
||
- `capabilities`
|
||
- `labels`
|
||
- `deploy_channel`
|
||
- `agent_version`
|
||
- `reachable`
|
||
- `maintenance_mode`
|
||
- `effective_worker`
|
||
- `hybrid_worker`
|
||
- `current_release`
|
||
- `desired_release`
|
||
|
||
这样调度器才能按资源能力派发任务。
|
||
|
||
---
|
||
|
||
## 九、Node Agent 应该怎样设计
|
||
|
||
这是整套方案最关键的一环。
|
||
|
||
### 1. 连接模式
|
||
|
||
首选:
|
||
|
||
- Agent 主动连海外控制面
|
||
- 长轮询或 WebSocket
|
||
|
||
不推荐以 SSH 为主链路。
|
||
|
||
### 2. Agent 的职责边界
|
||
|
||
Agent 不负责“决策”,只负责:
|
||
|
||
- 执行
|
||
- 回传
|
||
- 保持本机状态一致
|
||
|
||
### 3. Agent 的本地能力
|
||
|
||
Agent 至少应内置这些执行器:
|
||
|
||
- `systemd executor`
|
||
- `release executor`
|
||
- `shell executor`
|
||
- `log collector`
|
||
- `diagnostics collector`
|
||
- `config renderer`
|
||
|
||
### 4. Agent 的安全限制
|
||
|
||
Agent 必须执行白名单动作。
|
||
|
||
不能允许控制面下发任意 shell 就直接执行。
|
||
|
||
正确方式是:
|
||
|
||
- 控制面发 `action + payload`
|
||
- agent 解析成受控执行
|
||
|
||
例如:
|
||
|
||
- `service.restart` -> `systemctl restart xxx`
|
||
- `logs.collect` -> 收集指定日志源
|
||
|
||
shell executor 只能是受限兜底能力,且必须带审批和审计。
|
||
|
||
---
|
||
|
||
## 十、发布系统必须独立出来
|
||
|
||
终局方案里,发布不应该再依赖 git 工作区。
|
||
|
||
建议正式设计为:
|
||
|
||
### 1. Release Object
|
||
|
||
每个发布包都应有:
|
||
|
||
- `release_id`
|
||
- `version`
|
||
- `commit_sha`
|
||
- `build_time`
|
||
- `artifact_url`
|
||
- `checksum`
|
||
- `migration_version`
|
||
- `rollback_to`
|
||
|
||
### 2. 节点上的目录规范
|
||
|
||
```text
|
||
/opt/domaincheck/releases/<version>/
|
||
/opt/domaincheck/current -> /opt/domaincheck/releases/<version>/
|
||
/opt/domaincheck/shared/
|
||
```
|
||
|
||
### 3. 更新流程
|
||
|
||
1. 下载发布包
|
||
2. 校验 checksum
|
||
3. 解压到新目录
|
||
4. 渲染配置
|
||
5. 停服务
|
||
6. 切 `current`
|
||
7. 启服务
|
||
8. 做健康检查
|
||
9. 失败回滚
|
||
|
||
这才是正式运维。
|
||
|
||
---
|
||
|
||
## 十一、日志体系必须分层
|
||
|
||
如果日志不分层,后期还是会被日志量拖死。
|
||
|
||
### 1. Event 事件流
|
||
|
||
默认长期保留,体量小。
|
||
|
||
包含:
|
||
|
||
- 服务启动/停止
|
||
- 任务开始/结束
|
||
- 检测阶段切换
|
||
- 代理异常
|
||
- DB/Redis 异常
|
||
- 第三方依赖异常
|
||
|
||
### 2. Job Log 任务日志
|
||
|
||
和 `ops job` 绑定。
|
||
|
||
用于看某次动作:
|
||
|
||
- 执行了什么
|
||
- 返回了什么
|
||
|
||
### 3. Runtime Log 运行日志
|
||
|
||
业务服务自身日志。
|
||
|
||
默认不全量常驻上传,只做:
|
||
|
||
- 游标读取
|
||
- 按需拉取
|
||
- 临时全量回传
|
||
|
||
### 4. Diagnostics Bundle 诊断包
|
||
|
||
故障时一键采集:
|
||
|
||
- env 摘要
|
||
- systemd 状态
|
||
- 关键日志
|
||
- cluster snapshot
|
||
- sync summary
|
||
- release info
|
||
|
||
---
|
||
|
||
## 十二、Codex 的最高级接管方式
|
||
|
||
你说的“海外 Codex 作为智能驾驶员”,最高级不是让 Codex 直接 SSH。
|
||
|
||
最高级方式是:
|
||
|
||
### 1. Codex 是 Planner + Operator
|
||
|
||
Codex 拿到的是:
|
||
|
||
- 控制面所有 API
|
||
- 节点状态
|
||
- ops jobs
|
||
- 结构化日志
|
||
- 发布记录
|
||
|
||
然后它只做两类事:
|
||
|
||
- 分析
|
||
- 创建标准 `ops job`
|
||
|
||
### 2. Codex 不直接绕过控制面
|
||
|
||
Codex 不应该:
|
||
|
||
- 直接登录每台机器
|
||
- 直接手搓 root 命令
|
||
- 直接破坏审计链
|
||
|
||
它应该永远走控制面 API。
|
||
|
||
### 3. Codex 的价值
|
||
|
||
它的价值不是“替代平台”,而是:
|
||
|
||
- 自动读状态
|
||
- 自动识别问题模式
|
||
- 自动建议动作
|
||
- 必要时自动创建低风险 job
|
||
- 把复杂联调变成结构化流程
|
||
|
||
---
|
||
|
||
## 十三、没有 Codex 时也必须完整可用
|
||
|
||
这点非常关键。
|
||
|
||
最终平台不能依赖 Codex 才能工作。
|
||
|
||
没有 Codex 时,后台也必须能:
|
||
|
||
- 纳管节点
|
||
- 发布更新
|
||
- 一键重启
|
||
- 一键巡检
|
||
- 一键采日志
|
||
- 一键采诊断包
|
||
- 查看执行结果
|
||
|
||
Codex 只是锦上添花,不是唯一入口。
|
||
|
||
---
|
||
|
||
## 十四、最高级方案里的安全体系
|
||
|
||
正式版必须加入:
|
||
|
||
### 1. RBAC
|
||
|
||
区分:
|
||
|
||
- 观察员
|
||
- 运维员
|
||
- 发布员
|
||
- 超级管理员
|
||
|
||
### 2. 审批流
|
||
|
||
高风险动作必须审批:
|
||
|
||
- 批量更新
|
||
- controller 重启
|
||
- 清理数据
|
||
- 回滚生产版本
|
||
|
||
### 3. Policy Engine
|
||
|
||
可以内置规则:
|
||
|
||
- 正在跑检测的 worker 禁止强更
|
||
- 大陆 controller 每次只能更新 1 台
|
||
- `busy` 节点默认拒绝重启
|
||
|
||
### 4. Secrets 管理
|
||
|
||
不把所有 SSH 密钥和密码散落到脚本里。
|
||
|
||
正式版建议独立 secrets 管理,例如:
|
||
|
||
- Vault
|
||
- 或最少做控制面统一加密存储
|
||
|
||
---
|
||
|
||
## 十五、这套方案为什么是“后续最少返工”的
|
||
|
||
因为它不是按“当前临时联调”设计,而是按“节点继续增长、功能继续增加、Codex 持续接管”设计。
|
||
|
||
它天然支持:
|
||
|
||
- 节点从 3 台扩到 30 台
|
||
- 从手工联调升级到一键部署
|
||
- 从后台按钮升级到 Codex 自动驾驶
|
||
- 从局部脚本升级到平台化运维
|
||
|
||
也就是说:
|
||
|
||
> 这是终局骨架,不是过渡补丁。
|
||
|
||
---
|
||
|
||
## 十六、我给你的最终建议
|
||
|
||
如果按最高级、最优秀、后续最少反复修改的标准来做,路线应该明确成:
|
||
|
||
1. 海外主机做唯一控制面
|
||
2. 一切动作先建模成 `ops job`
|
||
3. 节点统一由 `node-agent` 执行
|
||
4. 发布统一走 release 包,不走 git pull
|
||
5. 日志统一做事件流 + 任务日志 + 诊断包分层
|
||
6. Codex 只通过控制面 API 接管,不绕过控制面
|
||
7. SSH 只保留 bootstrap 与救援,不做日常主链路
|
||
|
||
这套方案里,`ops job` 就是整个系统的“运维订单”和“执行凭证”。
|
||
|
||
它不是附属品,而是整套平台的中心对象。
|
||
|
||
---
|
||
|
||
## 十七、终局不是“一份大文档”,而是 7 份冻结 contract
|
||
|
||
真正能让这套体系后续少返工的,不只是理念对,而是:
|
||
|
||
> 概念层有总架构,执行层有正式 contract。
|
||
|
||
最终至少要冻结 7 份正式 contract:
|
||
|
||
### 1. `ops_job_contract`
|
||
|
||
建议以后直接以 [ops_job_contract.md](/www/wwwroot/getDomain/docs/schemas/ops_job_contract.md:1) 为正式母本。
|
||
|
||
约束:
|
||
|
||
- `ops job` 如何创建
|
||
- 如何审批
|
||
- 如何取消
|
||
- 如何派发
|
||
- 如何承诺 job / step / event 结构
|
||
|
||
它定义的是:
|
||
|
||
> 一切正式运维动作的执行订单模型
|
||
|
||
### 2. `ops_agent_protocol`
|
||
|
||
约束:
|
||
|
||
- Node Agent 如何注册
|
||
- 如何心跳
|
||
- 如何拉任务
|
||
- 如何回传事件
|
||
- 如何回传交付队列快照
|
||
|
||
它定义的是:
|
||
|
||
> 节点怎样成为“可托管执行器”
|
||
|
||
### 3. `ops_driver_contract`
|
||
|
||
约束:
|
||
|
||
- `overview.driver_recommendations`
|
||
- `driver-feed`
|
||
- `codex-brief`
|
||
- `driver-actions.preview/resolve/execute`
|
||
- `activity-stream`
|
||
|
||
它定义的是:
|
||
|
||
> 海外控制面、CLI、Codex 驾驶员如何共享同一套判断与动作入口
|
||
|
||
### 4. `ops_playbook_contract`
|
||
|
||
约束:
|
||
|
||
- playbook catalog
|
||
- preview
|
||
- execute
|
||
- playbook run
|
||
- playbook events
|
||
|
||
它定义的是:
|
||
|
||
> 多步标准作业怎样从“按钮集合”升级成正式编排对象
|
||
|
||
### 5. `release_hub_contract`
|
||
|
||
约束:
|
||
|
||
- Release
|
||
- Rollout
|
||
- Launchpad
|
||
- Default Rollout Gate
|
||
- Default Rollout Execution
|
||
|
||
它定义的是:
|
||
|
||
> 发布到底能不能发、该怎么发、先灰哪一台、失败怎么停
|
||
|
||
### 6. `ops overview / inspection / delivery queue` 收口 contract
|
||
|
||
这块现在虽然散落在 `overview`、`inspection`、`activity-stream`、`delivery-queue` 里,但终局一定要收成稳定协议。
|
||
|
||
建议以后直接以 [ops_observability_contract.md](/www/wwwroot/getDomain/docs/schemas/ops_observability_contract.md:1) 为正式母本。
|
||
|
||
至少要固定:
|
||
|
||
- 执行现场分组:
|
||
- `dispatch_active_nodes`
|
||
- `recent_only_nodes`
|
||
- `standby_nodes`
|
||
- `load_syncing_nodes`
|
||
- 巡检收口:
|
||
- 最近 `health.snapshot`
|
||
- 最近 `logs.collect`
|
||
- 最近 `diagnostics.collect`
|
||
- 回执队列治理:
|
||
- 节点级摘要
|
||
- `head_only` 头部记录
|
||
- `flush / replay / discard`
|
||
|
||
它定义的是:
|
||
|
||
> 海外控制面如何真正看懂现场,而不是只看到几条状态字串
|
||
|
||
### 7. `ops_stack_diagnosis_contract`
|
||
|
||
建议以后直接以 [ops_stack_diagnosis_contract.md](/www/wwwroot/getDomain/docs/schemas/ops_stack_diagnosis_contract.md:1) 为正式母本。
|
||
|
||
至少要固定:
|
||
|
||
- `stack_status`
|
||
- `issues`
|
||
- `next_step`
|
||
- `recommended_actions`
|
||
- `quick_commands`
|
||
- `focus_ref`
|
||
|
||
它定义的是:
|
||
|
||
> 海外单脑控制面的第一现场总检入口,页面、CLI、Codex 都必须先从这里起步
|
||
|
||
所以总架构文档的职责不是把所有字段都写死,而是明确:
|
||
|
||
- 哪 7 份 contract 才是后续实现的正式母本
|
||
- 页面、CLI、Codex 都只能复用这些 contract
|
||
- 不允许再额外衍生第 8 套逻辑
|
||
|
||
并且这 7 份 contract 以后不该只存在于文档目录里,还要进入统一 registry:
|
||
|
||
- `GET /api/v1/ops/contracts`
|
||
- `GET /api/v1/ops/contracts/{contract_key}`
|
||
|
||
这样海外控制面、CLI、Codex 驾驶员才能按同一份 contract graph 导航,而不是继续靠人脑记“哪份协议在哪个 md 里”。
|
||
|
||
这一步非常关键,因为一旦没有 contract 冻结,你后面就会再次回到:
|
||
|
||
- 页面自己猜
|
||
- CLI 自己拼
|
||
- Codex prompt 自己解释
|
||
- 节点 agent 再走一套临时语义
|
||
|
||
那“单脑控制面”就又会退化成“多脑拼接系统”。
|
||
|
||
---
|
||
|
||
## 十八、单脑控制面的日常闭环应该固定成 6 段
|
||
|
||
你后面不应该再按“这次故障怎么处理”临时想流程,而应该把日常路径固定成下面 6 段。
|
||
|
||
### 1. 接管
|
||
|
||
- 签发 token
|
||
- 生成 bootstrap plan
|
||
- 节点注册
|
||
- 节点心跳进入托管目录
|
||
|
||
这里的目标不是“节点能连上”,而是:
|
||
|
||
> 节点成为正式受控资源
|
||
|
||
### 2. 验收
|
||
|
||
- 执行 `onboarding.acceptance`
|
||
- 必要时追加 `inspection.standard`
|
||
- 确认:
|
||
- service topology 正确
|
||
- agent 在线
|
||
- delivery queue 正常
|
||
- 巡检结果可回看
|
||
|
||
这里的目标不是“接进来就算完”,而是:
|
||
|
||
> 接入后立刻进入正式运维
|
||
|
||
### 3. 观察
|
||
|
||
- 看 execution scene
|
||
- 看 inspection overview
|
||
- 看 activity stream
|
||
- 看 delivery queue
|
||
|
||
如果现场异常,优先动作应固定成:
|
||
|
||
- 开关键日志回传
|
||
- 跑标准巡检
|
||
- 处理死信 / retrying
|
||
|
||
而不是重新 SSH 上去抓一遍日志。
|
||
|
||
### 4. 发布
|
||
|
||
- 看 Release Launchpad
|
||
- 看 Default Rollout Gate
|
||
- 先 worker canary
|
||
- 再批次推进
|
||
- 异常即停
|
||
- 必要时回滚
|
||
|
||
这一步必须始终坚持:
|
||
|
||
- 节点不 `git pull`
|
||
- 发布只认 release artifact
|
||
- rollout 只认正式 gate
|
||
|
||
### 5. 故障
|
||
|
||
故障时优先路径应固定成:
|
||
|
||
1. `driver recommendation`
|
||
2. `activity-stream`
|
||
3. `playbook run detail`
|
||
4. `delivery queue`
|
||
5. `inspection / diagnostics`
|
||
|
||
也就是说,先走:
|
||
|
||
> 结构化现场收口
|
||
|
||
再决定是否需要更重动作。
|
||
|
||
### 6. 救援
|
||
|
||
只有下面场景,才进入 SSH Rescue:
|
||
|
||
- Node Agent 没注册成功
|
||
- Node Agent 已失联
|
||
- release 切换中断,当前目录损坏
|
||
- systemd / Python 运行环境坏到 agent 无法自救
|
||
|
||
而且即使进入救援,也应该做到:
|
||
|
||
- 仍生成正式 `ops job`
|
||
- 仍记录执行人、目标节点、动作来源
|
||
- 仍把结果写回控制面审计链
|
||
|
||
这就是“单脑控制面”的关键边界:
|
||
|
||
- 日常动作走标准 contract
|
||
- 标准动作走 agent / playbook / rollout
|
||
- 救援动作才进入 SSH
|
||
|
||
这样以后新增机器、换地域、换发布流程,都只是替换某一层执行器,不需要重写整个体系。
|