阶段十五:AgentMeshOS 多边缘、Tailnet 中继与网络态势韧性整改
阶段状态:已完成并归档
计划状态:已完成
当前工作包:无;P15-5 已完成并归档
📌 结论摘要
P15 在 P14 搜索试点完成后原地叠加,不创建平行计划体系。目标是让公网 Console 不再只依赖 MM 单台 Edge,同时把 Tailnet 的中继层从单一 region 900 扩展为 region 900 至 903,并把 Peer Relay 作为独立路径纳入网络态势。依据是 docs/plans/state.json、现有 DERP Map、Headscale policy、节点权威登记表、#topology 只读快照和 P15 已批准范围;影响是 Edge、DERP 与 Peer Relay 必须分权实现、分项验收,任何一项未取得现场证据都不能写成完成。
本计划的上线顺序为:先完成 P15-0 基线与门禁,再完成 P15-1 拓扑契约,随后建设 P15-2 多个 DERP/Peer Relay 和 P15-3 三台 Edge,最后执行 P15-4 DNS 控制器与 P15-5 总验收。公网切换必须等三台 Edge 全部通过,不以“进程 active”或“DNS 可解析”替代真实的 TLS、回源、浏览器和回退验收。
2026-10-03 实施回读(时点记录):P15-0 至 P15-3 已完成;MM、d02、DD、dog-public 的 Peer Relay 已统一为 UDP 40000 且无静态公网端点,Headscale relay grant 与节点登记表 SHA-256 一致;DERP region 900、901、902、903 均已真实建立连接。101 的 AliDNS 写凭据已就绪,ensure-records 当前幂等回读为 13 条候选、DERP 与 cloud-origin 记录;edge.yohan.fun 在该时点指向 MM。d02、DD、dog-public 的 Nginx、证书链、/verify 回源和核心域名回源均已从各自公网 IP 强制 SNI 回读通过。P15-4 的 101 控制器随后安装为 30 秒 systemd timer;该时点尚未执行真实切流,后续切流、自动切换和回切结果见下方复核记录。RR/MM 整机硬故障演练仍需维护窗口。
2026-10-03 自动切流复核:控制器在 09:37:53 CST 因 MM 的 101/RR 双视角连续三次一致失败,自动把活动候选从 edge-mm 切到 edge-d02,状态中的 last_reason=automatic_after_consistent_failure、last_known_good=edge-mm。自动切换后下一轮评估为 failures=0,未因递归 DNS 的旧 MM 缓存继续级联到 DD。演练结束后已执行 rollback,权威 A 恢复 MM 当前运行时地址。
2026-10-03 整机硬故障与 RR 冷启动修复:MM 内核 panic 后,101/RR 双视角连续三次一致失败,控制器真实切到 edge-d02;随后 rollback 回 MM。RR 内核 panic 后公网 SSH 约在 11:04:37 至 11:07:26 不可达,恢复时暴露出四个控制面冷启动根因:Tailnet 恢复使用依赖 RR 自身回源的 https://mesh.yohan.fun,形成登录循环依赖;私有回源 staged 配置缺失后符号链接悬空;Docker 早于 100.64.0.1 就绪,Console/Docs/Status/Runtime 因 Cannot assign requested address 退出;站点部署脚本从正在故障的 docs.yohan.fun 获取清理脚本且无条件拉取镜像,无法在冷启动时自愈。修复后 Tailnet 登录改用本机 http://127.0.0.1:39088,一次性 auth key 通过 0600 临时文件传入;私有回源有 /backup/agentmeshos/reboot-resilience/last-known-good 自动恢复;Docker 增加 Tailnet 就绪 ExecStartPre;站点部署优先使用本机清理脚本并在镜像已存在时跳过拉取。RR 恢复后公网 console/mesh/docs/status/cloud、systemd 失败单元和容器健康均已完成回读。
🧾 计划状态
| 项目 | 当前值 | 依据 |
|---|---|---|
| 当前阶段 | P15 | docs/plans/state.json |
| 阶段状态 | 已完成并归档 | 用户已批准并按 P15 实施完成 |
| 计划状态 | 已完成 | 工作包、契约、门禁和回退边界已冻结 |
| 当前工作包 | 无;P15-5 已完成并归档 | 真实切流、回切、观察者故障、自动切换、MM/RR 整机硬故障、RR 冷启动修复、AAAA 删除/恢复、IPv6 客户端复核和远端发布门禁均已通过 |
| 上一阶段 | P14 已完成并归档 | OmniRoute 搜索 MCP 双监听和三工具主链路可用 |
| 生产边界 | RR 只保留控制面 | RR 不承担公网 Edge、DERP 或 Peer Relay |
🧱 技术栈与架构选型
Edge、DERP 和 Peer Relay 是三个正交能力。Edge 负责公网 DNS、TLS、Nginx 与回源;DERP 负责 Tailnet 在无法直连时的官方中继;Peer Relay 是普通 Tailnet 节点通过 --relay-server-port 提供的中继能力,由 Headscale 的 tailscale.com/cap/relay grant 精确授权。三者可以部署在同一公网节点上,但不能因为同机就合并健康结论。
| 候选 | Edge | DERP | Peer Relay | 结论 |
|---|---|---|---|---|
| MM | 当前主 Edge | region 900 | UDP 40000 | 保留并删除静态公网端点表达 |
| d02 | 建设候选 | region 902 | UDP 40000 | 与 DD、dog-public 同步建设 |
| DD | 建设候选 | region 901 | UDP 40000 | 先做 Cloudreve 与端口冲突门禁 |
| dog-public | 建设候选 | region 903 | UDP 40000 | 保留宝塔、Nginx、Shadowsocks Rust 现状 |
| RR | 排除 | 排除 | 排除 | 只保留 Headscale、Runtime 和控制面 |
Headscale 继续是 Tailnet 控制面,但不是业务高可用替代品。RR 离线后,已有 Tailnet 会话和 DERP 路径可能继续工作,但新节点注册、ACL 更新和 DERP Map 下发仍依赖 RR。公网 Console 在 MM 或活动 Edge 故障时,恢复依赖 Edge DNS 切换,不依赖 Peer Relay。
🎯 目标、成果与验收契约
| 工作包 | 目标 | 验收依据 |
|---|---|---|
| P15-0 | 完成 P14 收口、任务叠加和资格矩阵 | 已完成:state.json、归档清单、节点端口与资源只读登记一致 |
| P15-1 | 修正网络态势字段、拖动、分道和能力徽标 | 已完成:采集器、Gateway、域名详情、浏览器契约和聚焦回归通过 |
| P15-2 | 扩展 region 900 至 903 与 Peer Relay | 已完成:四区 DERP 连接、Peer Relay 服务列表和精确 ACL 已验证;region 900 已改用 MM 专用 derp-mm.yohan.fun |
| P15-3 | 建设三台同源 Edge | 已完成:证书链、核心域名回源、端口和重启持久性证据已建立 |
| P15-4 | 101 控制 DNS,RR 只读监督 | 已完成:真实 MM → d02 切流、核心域名验证和回切均通过,执行锁与活动地址状态一致 |
| P15-5 | 测试、发布、真实切换和回退 | 已完成并归档:观察者故障、自动切换、回退、stale-DNS、DERP 域名解耦、MM/RR 整机硬故障、RR 冷启动修复、AAAA 删除/恢复、IPv6 客户端复核和远端发布门禁均已通过 |
拓扑快照继续使用 agentmeshos.network-topology/v1。节点新增 display_alias、capabilities、relay_region_id、peer_relay_port、edge_domain 和 derp_domain;链路新增 peer_relay 路径类型。别名最多 4 个 ASCII 字符或 3 个中文字符,完整名称保留在节点下方和详情面板。节点详情固定展示 Edge 域名和 DERP 域名,避免把长域名塞进节点圆圈;浏览器布局仍只保存在 agentmeshos.topology.layout.v1,不把位置写入服务端。
Dashboard 画布使用 1200x720 逻辑空间,节点拖动边界为 x=42..1158、y=42..650。普通连线使用 2px,选中线为 3px,流动层为 1px,可见线与流动层使用 vector-effect: non-scaling-stroke,点击热区继续 18px。浏览器契约同时断言可见线与透明热区的计算样式,防止路径颜色再次回写到点击热区。Console 的 CSS 引用使用构建内容哈希,防止生产继续缓存旧样式。同一节点对的链路必须使用稳定分道,DERP 与 Peer Relay 不得合并成同一类型。
🧩 分布式底座接入声明
- 接入结论:接入。
- 使用层:Network、Compute、Observability 和 docs-governance。
- Scheduler:Nomad 仍是唯一任务调度器;DNS 控制器和巡检 timer 不是调度器。
- Compute:RR、101、102 现有职责不变;d02、DD、dog-public 按 Edge 画像逐台门禁。
- Storage:不迁移 Cloudreve 数据,不复制业务后端,不在仓库写入 DNS 凭据。
- Credentials:AliDNS 写凭据只存在 101 的 root-only
0600文件;RR 不保存写凭据。 - Lifecycle:控制器和 timer 不是任务审批对象,任务状态不设置人为过期时间。
- Evidence:端口、证书、DNS、健康、故障和 rollback 证据必须来自现场。
🛠️ 工作包与依赖
P15-0 已读取节点权威登记表、DNS、端口、Headscale policy、当前 DERP Map、证书和业务占用,形成机器可校验能力矩阵。资格不满足的节点保持 blocked 并记录原因,不为了凑齐三台 Edge 放宽端口或资源边界。2026-10-03 现场门禁为:MM 可用内存 614 MiB、根盘余量 6.3 GiB;d02 为 1429 MiB、22.5 GiB;DD 为 1325 MiB、884 GiB;dog-public 为 2619 MiB、19 GiB。四台候选的 443/tcp、39478/udp、40000/udp 均未发现冲突。
P15-1 已改仓库代码并以现有只读快照为唯一数据源。P15-2 在 MM、DD、d02、dog-public 上使用同源官方 derper;稳定域名使用 derp-mm、dd、d02、dog,443/TCP 由 Nginx 承接,39478/UDP 由官方 derper STUN 承接。region 900 至 903 均已通过 tailscale debug derp 建立真实连接。Peer Relay 使用 40000/UDP,MM、d02、DD、dog-public 的 RelayServerStaticEndpoints 均已清空;服务列表返回 100.64.0.3/5/6/9,无活动 session 时按“服务已发布、当前无连接需求”显示 healthy,而不是误报故障。
P15-3 建设 d02、DD、dog-public 的同源 Nginx、ACME、防火墙、SSH 双入口、健康端点和核心域名回源。核心域名为 mesh/cloud/auth/console/docs/status/api/omni/nomad/ai。三台节点 nginx -t 通过,443/tcp、39478/udp、40000/udp 在监听;Let's Encrypt 证书覆盖 10 个核心域名和本机 DERP 域名。以各自公网 IP 固定 SNI 回读时,mesh/auth/console/api/nomad 返回 302,cloud/docs/status/ai 返回 200,omni 返回 307。cloud-origin.yohan.fun 指向 DD,www.threedogs.vip 仍单独保留证书和跨厂商 DNS API 门禁。
P15-4 使用 edge-mm/edge-d02/edge-dd/edge-dog.yohan.fun 作为稳定候选,edge.yohan.fun 是唯一活动入口;10 个核心域名均为指向 edge.yohan.fun 的 CNAME。101 以本地和 RR 双视角检查,只有连续三次一致失败后才调用 AliDNS 基础 OpenAPI。健康探测使用 mesh.yohan.fun 作为稳定 TLS/HTTP 身份,并强制连接到候选 IP,避免把未签发 edge-*.yohan.fun SAN 误判为候选故障。账号拒绝 60 秒 TTL,活动记录和候选记录统一使用 600 秒。控制器已修正候选短名解析、TLS SNI、RR stdin、首次状态身份、权威活动地址回读和执行锁竞争。真实切流后 10 个核心域名在 d02 回读通过;随后 rollback 回 MM,旧 TTL 退净后权威记录和核心域名恢复 MM 当前运行时地址。切流前回退包为 /root/.codex/backups/p15-4-cutover-20261003T010701Z。控制器现已把 A/AAAA 作为同一活动记录集处理,切换 d02/DD 时删除 AAAA,切换 MM/dog 时恢复或更新 AAAA。
2026-10-03 额外修复:mesh.yohan.fun 原先只在 IPv4 监听,IPv6 被默认站点接管后返回错误证书,导致 MM 和 dog 的 Tailscale 登录失败。MM 已追加 IPv6 80/443/quic 监听并 reload,MM、dog 恢复为 BackendState=Running;仓库新增 agentmeshos-mm-edge-ipv6-guard.sh 和负向回归,防止 Nginx 模板重建后再次丢站。
2026-10-03 DERP 准入修复:d02、DD、dog-public 的 Nginx 首版只代理 /derp,遗漏了 derper 的 -verify-client-url 所请求的 /verify。现场表现为本机 127.0.0.1:39479/verify 返回 200,但公网 DERP 域名 /verify 返回 404,agentmeshos-derp-edge 持续记录 admission controller: 404 Not Found,RR 对 d02 region 902 报健康告警。现在 DERP vhost 显式把 POST /verify 回源到主节点私有网关 100.64.0.1:39200,固定 Host: mesh.yohan.fun;部署脚本增加真实 /verify 探测门禁,缺少该路径时直接阻止 apply。修复后四个 region 的 tailscale debug derp 均建立连接,RR Health=[],拓扑恢复 33 healthy / 0 unknown。
2026-10-03 拓扑线宽与域名回读:用户看到的粗线根因是 18px 透明点击热区也被路径颜色类命中,后面的 .topology-link--* 规则覆盖了 transparent,因此 .375px 可见线并未成为用户实际看到的粗线。修复后路径颜色只作用于 .topology-link,浏览器契约要求热区 stroke=rgba(0,0,0,0);节点详情继续显示 Edge 域名、DERP 域名、DERP Region 和 Peer Relay 端口。生产 Console sha-e253297 的 styles.css SHA-256 为 0f6f5a5c1c5002d1bf0c00e57aafc268178575118f032f3cc2d4b3e8913e4117。
2026-10-03 DNS 控制器锁修复:此前 systemd 使用外部 flock,而手工执行的 show/check/switch/rollback 不共享同一排他锁,存在定时评估与手工切换并发覆盖状态的窗口。控制器现在自行持有 root-only /run/agentmeshos-edge-dns-controller.lock,所有子命令进入前均做非阻塞排他锁;状态新增 active_address,回退同时恢复候选和实际地址。101 已安装与仓库一致的 SHA-256 471f9f330337b2e37faa29e20a049fdc0c137f9b850747c286ec4a26c126d804,事件 30 秒 timer 已恢复 enabled/active,最近多轮评估均为 failures=0。
2026-10-03 定时锁竞争防复发:真实运行发现健康探测单轮约 14 秒,旧的 OnUnitActiveSec=30s 会与手工 show/check/switch 争抢执行锁,使 timer 当轮以 lock_busy 失败。systemd service 现使用 evaluate --defer-lock-busy,锁被手工操作占用时明确输出 edge_dns=deferred reason=lock_busy 并以成功状态让出本轮;timer 改为 OnUnitInactiveSec=30s,只在前一轮完成后重新计时。安装测试同时门禁 service 和 timer 两处配置,真实锁竞争回归证明自动评估退出码为 0,手工操作仍返回 lock_busy 并拒绝并发写。
2026-10-03 活动地址探测修复:控制器改为先读取 AliDNS 权威 A 记录或状态中的 active_address,再强制探测该候选 IP;旧版本通过公共 DNS 主机名探测,解析缓存可能仍返回切换前的 MM,导致已切换后的健康判断失真。回归测试覆盖“当前活动 d02 时必须探测 1.0.0.1 而不是再次使用无地址主机名”,并保留未知活动地址的直接探测路径。
2026-10-03 拓扑候选对等修复:生产快照中 dog-public 有 public-three-dogs 公网 HTTPS 和 public-ssh-dog-public 公网 SSH,而 d02 没有到 GW/edge 的边,根因是采集器缺少 d02 的公网 HTTPS 端点与 SSH 别名。现在 PUBLIC_HTTPS_ENDPOINTS 使用真实的 https://d02.yohan.fun/__edge/health 探测 d02,SSH_PATH_ALIASES 增加 d02,并在浏览器契约中固定候选 Edge 必须按真实能力显示公网 HTTPS、公网 SSH 和独立分道。MM 同样补入真实的 https://derp-mm.yohan.fun/__edge/health,与 public-ssh-mm 形成两路径;Three Dogs 的 www.threedogs.vip 业务探测继续保留,不把不存在的业务链路补到 d02。
2026-10-03 域名语义复核:网络态势新增可展开的域名与中继说明,分别列示活动 Edge、四个候选 Edge、十个核心公网入口、DERP region 900 至 903 和 cloud-origin 的用途。复核发现 mesh.yohan.fun 曾同时是核心公网 CNAME 和 region 900 DERP 域名,自动切换后会跟随 edge.yohan.fun 改变物理落点。该耦合现已通过 MM 专用 DERP 域名整改消除,历史状态不再作为当前风险描述。
2026-10-03 专用 DERP 域名解耦:新增 derp-mm.yohan.fun,AliDNS 权威 A/AAAA 均只指向 MM;MM 使用现有 acme.sh 3.1.6 以 HTTP-01 webroot 签发单域名证书并安装到宝塔证书目录,续期 cron 已执行 --cron 空跑且确认下一次续期为 2026-12-01T18:03:38Z。/__edge/health 返回 derp-mm,POST /verify 回源 Headscale;RR 的 /etc/headscale/derp-mm.yaml 已将 region 900 hostname 改为新域名,文件 SHA-256 从 31a2975b...e2e0 变为 3df32942...1f6f,headscale configtest 和受控重启通过。101、RR 的 tailscale debug derp 900 均成功建立 DERP connection 并返回 IPv4 STUN 响应;mesh.yohan.fun 继续只承担核心公网入口和 Headscale 身份,不再决定 region 900 的物理落点。
2026-10-03 AAAA 双栈切换收口:控制器已实现“候选缺少公网 IPv6 时删除 edge AAAA、目标候选具备 IPv6 时更新或补建 AAAA、回切恢复 last-known-good IPv6”的确定性路径,并在 API 失败时自动回滚 A 与 AAAA。edge-dns-controller-test.py 已用假客户端覆盖 d02 删除 AAAA、DD 无 IPv6、切换 dog 补建 AAAA、回切 d02 删除 AAAA、稳定回切 MM 恢复 AAAA、A 或 AAAA 更新失败后双栈恢复,以及非法 IPv6 拒绝;101 实装脚本与仓库源码 SHA-256 均为 7f954523c9c966d4f30c326d9b9ce7e4a30f08f97eb4e4b191f469ebc57fd5bb。真实 MM → d02 切换后 show 回读 active_ipv6_address=null,rollback 后恢复 MM A/AAAA;递归 DNS 的旧 AAAA 仍会按既有 600 秒 TTL 自然退净,不能把缓存未过期误报为控制器失败。
2026-10-03 IPv6 客户端最终复核:受控切到 d02 后,223.5.5.5 的公共递归答案在第 29 轮等待时退净旧 MM AAAA;此时 curl -4 访问 console.yohan.fun 返回 302 且落点为 d02 运行时公网 IPv4,严格 curl -6 以退出码 7 失败,证明客户端不再命中已失效的 MM IPv6。随后 rollback,223.5.5.5 与 1.1.1.1 均恢复为 MM 当前运行时 A/AAAA,timer 恢复 enabled/active。公网地址属于运行时数据,不写入仓库。
P15 已完成并归档。MM/RR 整机硬故障已经真实执行,RR 恢复后暴露的四个冷启动根因已完成代码修复、提交 7125931、Actions/101 Runner/RR 生产部署和现场回读;P15-5 的发布门禁已经闭环。多 Edge、DERP 和 Peer Relay 只提高入口与中继冗余,不复制 RR 上的 Console、Auth、API 和 Runtime 后端,因此 RR 后端整机不可用时,完整控制台登录仍会中断;该缺口不在归档范围内追补,已经转入 P16 控制面后端冗余。
🧪 测试与回退
拓扑测试必须覆盖别名长度、完整标签、Edge/DERP 域名说明、画布边界、刷新恢复、自动布局、可见线与热区分层、多线分道、Peer Relay 筛选和敏感字段泄漏负向回归。采集器与 Gateway 要拒绝非法别名、非法域名、未知能力、非法 region、伪 Peer Relay 和敏感字段。
DERP 要分别验证 region 900、901、902、903 的 debug derp 和客户端连接;region 900 还必须验证独立域名、独立证书、续期、Headscale 重启和 DERP map 回读。Peer Relay 要验证服务列表、活动会话、精确 ACL、无静态公网端点、单节点失效和重启恢复。DNS 控制器要验证正常、缺凭据、API 401、非法 IPv4/IPv6、连续失败、证据冲突、A/AAAA 切换、回切、回滚和部分写入后的双栈恢复。三台 Edge 要分别验证 SSH 双路径、Nginx -t、证书链、核心域名回源、浏览器登录和重启恢复。
回退分为四层:Edge 配置返回 last-known-good;DNS 控制器使用 last-known-good 和 rollback;DERP/Peer Relay 按区域独立停用,不关闭其他 region;发布回退使用提交、Action、101 Runner 和 RR 镜像的上一次成功点。任何回退都不得删除凭据、业务数据或历史归档。
⚠️ 未决项 / 需要用户决策
| 事项 | 当前事实 | 下一步 |
|---|---|---|
| AliDNS 写凭据 | 凭据、ensure-records、真实切流、自动切流和回切均已完成;当前权威 A/AAAA 为 MM |
保持 30 秒评估、stale-DNS 回归和 rollback 路径 |
| 三台 Edge 资格 | 资源、磁盘、Nginx、证书链和核心域名回源通过 | 保持重启与长期健康证据,不通过时继续自动排除 |
| DERP region 900 至 903 | region 900 已改用 derp-mm.yohan.fun,四区均真实连接,Headscale 已下发四区 |
保持逐区故障隔离、证书续期和重启恢复证据 |
| Edge IPv6 切换 | 控制器已通过单测、真实切流/回切和公共递归 TTL 退净后的 IPv4/IPv6 客户端复核;回滚后 MM A/AAAA 已恢复 | 保持双栈状态回读;若要缩短 600 秒切换窗口,需另行评估全候选 IPv6 或更低 TTL 的 DNS 产品 |
| RR/MM 整机硬故障演练 | MM panic 后 Edge 自动切换与回滚通过;RR panic 后公网入口真实中断并恢复,四个冷启动根因已修复和回读 | 已归档;后续控制面备用在 P16 中原地叠加,不重新打开 P15 |
| Console 后端冗余 | Edge、DERP、Peer Relay 均不复制 RR 上的 Console、Auth、API 和 Runtime 后端;RR 主机不可用时完整登录仍中断 | 已转入 P16;不要用继续增加 Edge 的方式冒充控制面后端高可用 |
www.threedogs.vip |
跨厂商 DNS 与证书自动续签未闭环 | 单独门禁;未通过不纳入 Edge 高可用 |