feat: choose probe/agent links from the admin, fix the overview popover [CI]

The panel decides which probes link to which agents (probes dial out): an
auto-link setting plus per-pair manual overrides with a link matrix in the
admin, and the hovered overview card is lifted above its neighbours.
This commit is contained in:
justme committed 2026-10-06 23:22:45 +08:00
1 parent d449e50791
commit 6e945657c1
32 files changed
+788 -39

No files matched your search

+2
View File
@@ -137,6 +137,8 @@
| GET/PATCH | `/api/admin/settings` | 站点公开或私有、是否对访客显示构建信息(`site.show_build`)、保留期等 |
| GET | `/api/admin/build-info` | 后端和每个 Agent、Probe 的版本、tag、提交、构建时间、系统,以及节点宿主机更新器报告的更新状态(管理端「系统 → 版本」) |
| GET/POST | `/api/admin/releases` | CI 签名的发布清单:POST 登记(`{manifest, signature}`,面板不验签、原样转给在线的节点和之后连上的节点),GET 看每个组件最新的一份 |
| GET | `/api/admin/links` | 每一对(Probe,Agent)的线路开关:`linked`(最终结果)、`override`(手动设置,`null` 跟随自动连接)、`connected`,以及 `auto_link` |
| PUT | `/api/admin/links/{probe_id}/{agent_id}` | `{enabled: true|false|null}`:手动强制连或不连,`null` 取消手动设置;改完立即重新下发 |
| POST | `/api/admin/nodes/{id}/update` | 请求一个在线的 Agent 或 Probe 更新到它收到的清单(节点不在线返回 409) |
| GET/POST/PATCH | `/api/admin/users` | 首次启动时通过命令行或环境变量创建初始管理员 |
+33
View File
@@ -195,6 +195,38 @@ OpenWrt 默认不带 OpenSSL:`opkg install libopenssl3`(较新的快照和 2
这次试跑发现并修掉的问题:`hy2_ladder` 的阶梯按「块」而不是按「阶段」计算,真实的 Probe 把一个阶段切成几块,4 个阶段出了 7 步(模拟数据不切块,所以之前的测试没有发现);现在同一阶段的块先合并。␍
## 容器节点的运行(podman + systemd)
Agent 和 Probe 推荐在宿主机上用 root 的 podman 加 systemd 运行,这样宿主机更新器(下一节)才能重启它们。以 Agent 为例(Probe 把名字和目录换成 `monitor-probe`,配置文件换成 `probe.json`):
```ini
# /etc/systemd/system/monitor-agent-container.service
[Unit]
Description=Monitor Agent (podman)
After=network-online.target
Wants=network-online.target
[Service]
EnvironmentFile=/etc/monitor-update/agent.image # IMAGE=<仓库>@sha256:<digest>,更新器更新时改写它
Restart=always
RestartSec=5
TimeoutStopSec=30
ExecStartPre=-/usr/bin/podman rm -f monitor-agent
ExecStart=/usr/bin/podman run --rm --name monitor-agent --network host --read-only --security-opt no-new-privileges --cap-drop all -v /etc/os-release:/etc/os-release:ro -v /opt/monitor/etc:/etc/monitor:Z ${IMAGE}
ExecStop=/usr/bin/podman stop -t 20 monitor-agent
[Install]
WantedBy=multi-user.target
```
- **数据目录**(上面挂到容器 `/etc/monitor` 的 `/opt/monitor/etc`)归容器用户(UID/GID 1654),里面放 `agent.json`、身份目录(`fleet-enroll` 注册之后的 `agent-id/`),Probe 放 `probe.json` 和 `agents.json`。`agent.json` 里的 `fleet.identity_dir` 写容器里的路径(例如 `/etc/monitor/agent-id`)。
- **首次注册 Agent**:`podman run --rm --network host -v <数据目录>:/etc/monitor --entrypoint /usr/local/bin/fleet-enroll <镜像> --server https://<面板> --join <加入令牌> --name <名字> --identity-dir /etc/monitor/agent-id`,再写 `agent.json`。Probe:在管理端创建(或轮换密钥)之后下载 `probe.json`,放进数据目录。
- **拉取私有镜像**需要 Registry 的登录信息:用 `podman login --authfile /etc/monitor-update/registry-auth.json …` 生成一份只有 root 能读(600)的认证文件,更新器用它拉取,容器本身用不到。
- **挂载宿主机的 `/etc/os-release`(只读)**:节点读系统名展示在面板上,不挂的话读到的是镜像里的 Ubuntu。
- **ICMP 目标任务**要在 `podman run` 里加 `--cap-add NET_RAW`。
- **经隧道注册之后检查 Agent 的 `public_host`**:面板看到的来源地址是隧道的出口(通常是内网地址),要在管理端改成这台机器自己的公网地址(`PATCH /api/admin/agents/{id}`),Probe 才连得上。
- `packaging/compose/` 里的 compose 文件是不带宿主机更新器的简单方式:更新靠手动改版本再 `docker compose pull && up -d`,面板的更新按钮对它不起作用。
## 容器节点的更新(Agent、Probe)
面板通知、节点验签、宿主机更新,**面板即使被攻破也装不上假镜像**:
@@ -215,6 +247,7 @@ CI 构建并推镜像(Zot)──► ci/release-manifest.sh:对镜像 diges
- **镜像仓库、服务名、公钥都在本机配置里**,清单里写什么都不会改变拉取哪个仓库;清单被篡改、签名对不上、组件或仓库不符、`seq` 不比已安装的大(重放旧清单),都会被拒绝,状态是 `invalid`。
- **业务进程不能改二进制,也不执行命令**:它只能往 `update/` 里放清单和请求;状态在 root 拥有的 `update-status/` 里(只读)。
- **CI 的配置**:Woodpecker 密钥 `release_signing_key`(发布私钥,PEM)、`release_api_token`(面板的 API 令牌,作用域 `release`,只能登记清单);环境变量 `RELEASE_API_URL`(面板地址)。没有 `release_signing_key` 就只构建镜像、不发清单。
- **管理端**:「系统 → 版本」页显示最新发布的 tag、每个节点的更新状态(已是最新、有新版本、更新中、已回滚、清单无效),有新版本的节点有「更新」按钮,也可以「全部更新」。更新策略在节点本机配置:`/etc/monitor-update/<组件>.conf` 里 `POLICY=manual`(默认,等管理员请求)或 `auto`(验签通过就更新)。
- **发布公钥**在 `packaging/update/release-key.pub.pem`;私钥不入库,请离线备份。更换密钥:节点上换新公钥之后再用新私钥发布。
- 纯二进制的安装方式(`fleet-updater`、`fleet-release`,见 [fleet/update.md](fleet/update.md))还没有实现;容器方式优先。
+1
View File
@@ -55,6 +55,7 @@ Probe 启动
```
- 每个 Agent 通过自己的期望状态(`TaskSet.peers`)获得 Probe 的公钥,用来验证点对点会话的签名。
- **哪些 Probe 连哪些 Agent 由面板决定,始终是 Probe 主动拨出**:设置 `fleet.auto_link`(默认开)打开时,所有未吊销的 Probe 和所有 Agent 两两连;关闭时只连手动选中的。每一对还可以在管理端 Probe 页的「线路」矩阵里手动强制开或关(`PUT /api/admin/links/{probe_id}/{agent_id}`),手动设置优先于自动连接。结果同时用在 Probe 的 Agent 列表、Agent 的 `peers` 和线路目录(关掉的线路从总览里消失,历史数据还在)。
- 吊销 Probe:在面板上重新生成身份,旧公钥立即从所有 Agent 的期望状态中移除,旧会话随之断开。
## 4. Agent 本地配置(`/etc/monitor/agent.json`,面板无法修改)
+7 -1
View File
@@ -62,6 +62,8 @@
## F2 Fleet 更新(在 M6 之前)
> **状态**:容器节点(Agent、Probe)的更新已经实现并在线上验证过(签名发布清单、面板转发、宿主机更新器验签、按 digest 拉取、健康确认和回滚,见 [deployment.md](deployment.md) 的「容器节点的更新」)。**还没实现**:纯二进制安装方式的 `fleet-updater` 和 `fleet-release`、Windows 服务和 OpenWrt 的适配器、通道与灰度(现在由管理员在管理端手动选节点)、`POLICY=auto` 的线上验证。下面保留原来的完整设计。
- `Fleet.Update`、`fleet-updater`(systemd 与 Windows 服务适配器、健康信标、回滚、防回滚)、`fleet-release`(CI 签名)、`Fleet.Server.Releases`(通道、灰度、版本汇总)。
**验收**:
@@ -81,7 +83,11 @@
## 实现状态(后端与 Agent)
已实现并有自动化测试(287 个,另有 2 个跳过的测试,其中 1 个需要运行中 NativeAOT 产物):
已实现并有自动化测试(331 个,另有 2 个跳过的测试,其中 1 个需要运行中 NativeAOT 产物):
- **Probe 直连面板**:Probe 用自己的身份连 Backend(`probe.json` 里有 `server`),Agent 列表由面板作为期望状态 `probe_agents` 下发;Agent 不再中转列表和 Probe 的系统信息。
- **节点信息与构建信息**:系统、架构、国家和运营商(Backend 用来源地址查询,节点不访问外部服务)、版本、tag、提交和构建时间;展示端按 `site.show_build` 开关显示,管理端「系统 → 版本」看全部。
- **容器节点的更新**:CI 对镜像 digest 签名,面板转发,宿主机 `monitor-update` 验签、拉取、重启并在不健康时回滚;管理端有更新状态和按钮,CI 用只能登记清单的 `release` 令牌。
- **多 Probe**:Probe 身份由 Backend 生成(创建、轮换密钥、吊销、删除),一条线路是一对(Probe,Agent),Agent 为每个 Probe 会话各起一组流,数据按 `line:<probe_id>` 隔离;Agent 上报连着的 Probe(id、版本、远端地址、时间),管理端可以断开某个 Probe;吊销立即生效。
- **`tcp_bulk` 原语**:批量传输(fwd / rev、本地码率上限、两端的 tcp_info),评分用持续 1 秒的吞吐峰值。