阶段十六:控制面后端冗余与断网只读控制台
状态:已完成并归档
P16 已完成 102 只读备用控制面、Auth 一致性快照与会话连续性、Console/API Gateway 只读备用、Edge 本地主备回退、101 单观察者安全路径、RR 整机重启与故障恢复演练。当前生产仍由 RR 保持唯一控制面写权威,102 只提供明确标识的只读降级服务;P17 已切换为“后续阶段待新增需求评审”占位。
📌 结论摘要
- P16 的真实目标不是把 RR 做成双活,而是在 RR 后端不可用或整机短时不可达时,让活动 Edge 仍能把只读请求送到 102,用户至少能够登录验证、查看网络态势、节点状态、告警和最近一次权威快照。
- 102 的 Auth 使用 RR Auth SQLite 的一致性快照,快照包含
PRAGMA quick_check、Schema、账号/API Key 计数和 SHA-256 校验;服务使用同一AUTH_SESSION_SECRET,但写操作统一返回503 standby_readonly_write_rejected。 - 102 的 Console、API Gateway 和回源网关均健康;活动 Edge 的
console/auth/api主 upstream 仍为 RR,102 作为backup,只对连接错误、超时及 HTTP500/502/503/504回退。 - 101 继续承担 DNS 控制器主观察者;RR 不可达时允许单观察者路径,但必须同时具备活动 Edge 连续失败证据和 101 本地管理路径正常证据;证据冲突、凭据缺失或 API 错误继续 fail closed。
- RR 已执行一次真实整机重启演练。重启前后
boot_id发生变化,Tailnet、Docker、Console、Auth、API Gateway、私有回源和关键业务容器均完成恢复回读。 - 本阶段不把 102 变成第二 Runtime、第二调度器或第二写控制面;Nomad 仍是唯一任务调度器,Runtime、Nomad、Cloudreve 和 OmniRoute 写事务仍由既有生产权威负责。
🧾 状态变化
| 项目 | 归档时状态 | 证据 |
|---|---|---|
| P16 阶段状态 | 已完成并归档 | 生产部署、管理员会话回读、Edge 回退、RR 重启和故障恢复均已完成 |
| P16-0 | 已完成 | 冻结只读备用边界、RPO/RTO、回退层级和故障事实 |
| P16-0A | 已完成 | RR、MM、DD、d02、dog-public 的 Exit Node 能力基线、Headscale 路由和重启持久性通过;默认均不使用 |
| P16-0B | 已完成 | MM 核心域名 IPv6 vhost、证书、SNI 与 Home 经 MM Exit Node 的回归修复完成 |
| P16-1 | 已完成 | Auth 快照、同一会话密钥、102 备用 Auth、只读写拒绝与 RR 会话跨节点验证通过 |
| P16-2 | 已完成 | 102 Console、API Gateway、回源网关、只读拓扑快照和健康检查通过 |
| P16-3 | 已完成 | Edge 主备 upstream、HTTP 500/502/503/504 回退、故障恢复和回退验证通过 |
| P16-4 | 已完成 | 101 单观察者安全路径、DNS 状态、非法候选、凭据缺失和回退测试通过 |
| P16-5 | 已完成 | RR 整机重启、损坏快照负向回归、生产容器恢复和最终发布门禁完成 |
🧱 生产边界
| 层 | 生产事实 | 明确边界 |
|---|---|---|
| Network | MM、d02、DD、dog-public 已承担 Edge 候选;RR 不承担 Edge | Edge 只负责入口与回源,不能替代后端控制面 |
| Compute | 102 运行只读备用容器和现有 OmniRoute;RR 运行权威 Runtime 与 Bridge | 102 不提交 Nomad Job,不复制 Runtime 写库 |
| Storage | RR Auth SQLite 单向快照;102 保存只读副本和 last-known-good | 不反向覆盖 RR,不直接复制正在写入的 WAL 数据库 |
| Observability | 备用页面与 API 返回 standby_readonly、read_only、快照年龄和来源 |
超过新鲜窗口必须显示 stale 或 unavailable,不伪装实时 |
| Credentials | 会话密钥、快照和 Edge 回源配置保存在 root-only 0600 边界 |
密钥、Token 和私钥不进入仓库、日志、前端或普通回复 |
| Lifecycle | 快照、last-known-good、Edge upstream 和 DNS 状态均可回退 | 回退不删除 RR 主库,不改变 Runtime、OmniRoute 或 Cloudreve 数据 |
🔌 故障路径
正常路径为:
RR 后端不可用但 Edge 可达时,console/auth/api 按受控策略变为:
该回退只保护只读控制面。已有 Tailnet 直连可以在短时间内继续工作,但新注册、ACL 变更、Headscale 管理和所有生产写入仍依赖 RR;DERP 和 Peer Relay 不能替代 Console/Auth/API 后端高可用。
🧪 生产验收证据
| 验收项 | 结果 |
|---|---|
| 101 控制面备用同步 timer | agentmeshos-control-plane-standby-sync.timer 为 active,最近触发时间已回读 |
| 101 安装版与仓库哈希 | 同步脚本安装版与仓库 SHA-256 一致 |
| 102 容器 | agentmeshos-auth-site-standby、agentmeshos-console-site-standby、agentmeshos-api-gateway-standby、agentmeshos-standby-origin-gateway 均 healthy |
| 备用服务端口 | Auth 39150、Console 39110、API 39120、备用回源网关 39210 均返回 HTTP 200 |
| 只读写拒绝 | 密码、API Key 和告警生命周期写请求均返回 503 standby_readonly_write_rejected |
| 合法会话读取 | 合法 standby 会话可读取 /__agentmeshos/session、Console 首页、app.js 和拓扑 API |
| 会话密钥 | RR 与 102 的 AUTH_SESSION_SECRET SHA-256 一致 |
| Edge 回源 | MM、d02、DD、dog-public 的主 upstream 为 RR,备用 upstream 为 102,回退判据包含 HTTP 500 |
| RR 重启 | RR boot_id 从旧值切换到新值,关键容器恢复 healthy,公网和私有路径回读通过 |
| 损坏快照 | 负向回归返回非零且 last-known-good 保持不变 |
| DNS 控制器 | 当前活动 MM、dry-run、缺凭据、非法候选和单观察者路径均有现场回读 |
| 本地门禁 | Runtime、Auth、Gateway、Console、拓扑、DNS、standby、计划状态、文档清单和严格 MkDocs 构建通过 |
⚠️ 残余风险
| 风险 | 当前事实 | 后续处理 |
|---|---|---|
| RR 仍是写权威 | 102 只提供只读降级,不能创建任务、修改密码、撤销 Key 或管理 Nomad | 保持双活写边界不开放;写能力恢复仍以 RR 为准 |
| 快照存在时间窗 | RPO 目标为不超过 5 分钟,实际取决于 timer、SSH 和发布状态 | 继续监控 timer、快照年龄、last-known-good 和失败隔离 |
| Edge 回退不是全站高可用 | 只覆盖 Console、Auth、API;其他域名继续 fail closed | 新增需回退的域名必须单独评审,不扩大盲目回退 |
| RR 稳定性 | RR 经历真实 panic 和整机重启,仍需持续观察内存、Swap、OOM 和失败单元 | 异常作为新的运维事件处理,不重新打开 P16 |
| 外部漂移 | DNS、Edge、证书、Tailnet 路径和凭据均可能变化 | 任一触发条件变化后重新执行 Edge、DNS、会话和回读验收 |
🔁 回退点
- Edge 模板恢复单 RR upstream,并重新执行
nginx -t与 reload。 - 停止 102 的备用 Console、Auth 和 API Gateway 容器。
- Auth 与拓扑快照恢复上一版 last-known-good。
- DNS 控制器恢复只读双视角模式或最新 last-known-good 状态。
- RR 主库、Cloudreve、Runtime、OmniRoute 和 Nomad 生产数据不得被备用节点覆盖。
P16 的归档依据是 P16 计划、生产命令回读、scripts/ci/run-local-tests.sh 和提交后的 post-push-verify。只有远端提交、Actions、101 Runner 和 RR 生产回读全部通过,P16 才在发布门禁中正式关闭。