跳转至

主机重启恢复设计

目标

任意单节点重启不得使其余节点永久离线;主节点恢复后,Headscale、Tailnet、Nomad、系统云盘和控制台应自动恢复,无需人工改 hosts、临时反代或手工启动容器。公网入口使用稳定逻辑身份,具体边缘主机可替换。

根因

原路径让 MM 的 mesh.yohan.fun 经 Tailnet 回源主节点 100.64.0.1:39200。主节点重启时 Tailnet 地址尚未恢复,MM 无法回源 Headscale;其他节点又必须访问 MM 上的 mesh.yohan.fun 才能恢复 Tailnet,构成控制面循环依赖。MM 的 BaoTa Nginx 也未作为独立 systemd 单元启用,重启后可能不启动。

选型

方案 可维护性 部署复杂度 性能 学习成本 扩展性 结论
仅给现有服务增加 Tailnet 等待 中 低 无影响 低 低 不能打破回源循环,不采用
新建第二套 Headscale 低 高 增加同步与故障面 高 低 会产生控制面状态分叉,不采用
MM 直连主节点 bootstrap 加 Tailnet 就绪加载器 高 中 仅启动期一条控制面回源 中 高 采用
失败后无限重启 Nginx、Nomad 或容器 低 低 增加无效重试和日志噪声 低 低 不采用

运行契约

  1. 当前边缘节点承担公网入口,BaoTa Nginx 使用独立 systemd 单元自启动;系统身份仍是 edge.yohan.fun,不绑定某一台边缘主机。
  2. 当前边缘节点对 mesh.yohan.fun 在启动期经主节点公网 bootstrap 回源;该 bootstrap 只允许受控 edge 快照解析出的公网地址,只代理 Headscale 协议和经 A-Auth 管理员校验的 Headplane /admin,不暴露 Nomad、Docker 或业务端口。
  3. 主节点 BaoTa Nginx 先运行 Tailnet listener 清理器、再做配置校验并启动 bootstrap;100.64.0.1 缺失时必须移除私有 39200 配置,不能让残留监听器阻断公网 bootstrap。
  4. 主节点若已保存的 Tailnet 状态明确为 NeedsLogin 或 NoState,才由 root-only 恢复服务向本机 Headscale 申请不可复用、5 分钟有效的一次性注册键;恢复服务每次启动都强制执行 tailscale set --accept-dns=false --accept-routes=false,注册显式保留既有 Exit Node 宣告并使用 --accept-dns=false,系统级应用、主机默认路由和主机 DNS 不得由 Tailnet 接管。密钥仅存在进程内存,不写入项目、日志或长期配置。其他状态不得自动重注册,保留给故障调查。
  5. Tailnet 地址 100.64.0.1 出现后,加载私有 39200 回源配置并 reload,然后启动 Nomad 和 Runtime。Runtime 恢复时必须检查 Docker 专用网络附着;若此前因 Tailnet 端口绑定失败而丢失网络端点,重新附着固定私网地址后再验证 loopback 健康端点。主节点与 101/102/103 的 Nomad 均只等待 Tailnet IPv4 出现后启动;不等待已退役的数据库、文件系统或预拉取镜像。Cloudreve 位于 dd,按其自身容器健康恢复,不作为 Worker 启动前置条件。

验收

受控重启时每台机器逐台执行,确认 Tailnet 注册、SSH、Docker 健康、Nomad、mesh.yohan.fun、Console、系统云盘和告警恢复;不得同时重启多个节点。主节点演练还必须覆盖“Tailnet listener 配置残留但地址未出现”的 bootstrap 降级路径、NeedsLogin/NoState 的一次性恢复路径,以及重注册后 accept-dns=false、accept-routes=false、宿主公网默认路由和宿主公网 DNS 仍有效。

已知恢复入口

每台 Linux 非 NAS 主机必须同时保留物理或公网入口与 Tailnet 入口;任一入口不得依赖另一入口、Exit Node、项目代理或项目服务。若某个 Worker 已启动但 Tailnet 尚未恢复,可由已登记的独立管理路径登录并在本机执行 systemctl restart tailscaled,然后继续验收。不得为了单机故障放开密码登录、静默接受未知主机密钥或移除双通道边界。