跳转至

设备与 Agent 统一管理

一、项目目标

设备一多,操作就会散:Agent 分散在各台机器上,服务只能从某台本机连上,想知道任务进度得逐台登录。

这一页的做法是四层各挑一个组件拼起来:组网 + 会话常驻 + 统一控制台 + 通知,把「人现在在哪」和「要操作哪台机器」解耦。每层为什么这样选,见 Agent 平台部署。

层次 目标 验收方式
基础 任意两台设备之间可直接互通,不依赖第三方中转 两台设备互 ping 延迟在个位毫秒级
基础 没有客户端的设备(打印机一类)也能被访问 从另一台设备能打开该设备的管理页面
会话 关掉终端窗口后,里面的任务继续跑;换台设备能重新接管 断开后重连,任务仍在,还能看到期间的新输出
统一 一个界面能看到所有设备与上面的 Agent,不用逐台 SSH 打开控制台能看到设备列表与状态
通知 任务结束时能收到通知,通知渠道只有一个 只留一个渠道,仍能收到
可交接 设备与 Agent 的清单是一份可读的文件,新人照着能理解全貌 新人读完清单能说出每台机器上有什么

不做的事:跨实验室的联邦组网;把内网服务暴露到公网。

二、环境

2.1 需要什么

需要 说明
至少两台设备 一台始终在线,一台可移动。只有一台设备验证不了任何东西
每台设备的管理员权限 装客户端、改路由都要
一个组网账号 免费额度够个人与小团队规模使用
一个可用的内网网段 只有要覆盖装不了客户端的设备时才需要
统一的设备命名 先定好名字再接入,改名比接入麻烦
前置知识 知道 IP、端口、子网是什么意思;不了解就先看学习

容易卡住的两处:设备名没定好就开始接入;只有一台设备就想验证「任意两台互通」。

2.2 设备角色

做法不绑定具体型号,按角色准备设备:

角色 特征 在方案里承担的作用
常驻主机 一直在线的 Windows 主机 日常操作面、控制台、部分 Agent
移动笔记本 会换网络、会关机 随身接入,要求到哪里都能连回来
GPU 服务器 Linux,有显卡 跑重任务
通用服务器 Linux,长期在线 跑自托管服务
移动设备 手机、平板 装客户端当终端用,也可以作为被管理对象
无客户端设备 打印机一类装不了客户端的设备 只能靠子网路由访问,见 3.3
边缘设备 算力有限的小设备 跑轻量 Agent 与采集

无客户端设备是很多方案的盲区:能装客户端的设备都好办,装不了的那些必须靠「把整个网段通告出去」解决。

2.3 用到的工具

层 工具 装在哪
L0 组网 Tailscale 每台设备
L1 会话常驻 herdr 每台要跑 Agent 的机器
L2 统一控制台 Agents Anywhere,自托管 一台常驻服务器
L3 通知 一个 IM 机器人 + 一个自建推送服务 服务器与手机

选型理由与放弃过的方案见第六节。

2.4 设备清单

设备一多,靠记忆管不住。做法是维护一份清单文件(例如 fleet.yaml),记录设备、上面的 Agent、暴露的服务与约定;清单进版本控制,凭据不进。

version: 1
session_manager: herdr
tailnet: <组网标识>

network:
  provider: tailscale
  server_subnet_router:
    advertise_routes: [<内网网段>]     # 由哪台机器通告
  rules: [...]

devices:
  <设备名>:
    display_name: <显示名>
    os: <系统>
    location: <位置,泛化为「实验室/机房」>
    addresses: { lan: <内网IP>, tailscale: <组网IP> }
    agents:
      - id: <Agent 标识>
        kind: <类型>
        launch: <启动命令>
        session: agent-<设备名>-<用途>
    runtime: { docker: <有/无>, node: <有/无> }
    known_issues: [...]

exposed_web_uis:
  - device: <设备名>
    name: <服务名>
    url: <组网内地址>
    auth: <认证方式>

invariants:      # 不变量:违反这些的改动一律不合并
  - Agent 必须跑在 herdr 会话里
  - 面向组网的服务只绑组网地址,不绑 0.0.0.0
  - IM 机器人只保留一个
  - 每台设备独立 SSH 密钥
  - 设备或 Agent 有变动,先改本文件

把不变量放进清单,是因为写在另一份文档里的约定不会被遵守:改设备时一定会打开的是这份清单。

命名约定:会话 agent-<设备名>-<用途>;Agent 标识 <角色>-<编号>;设备名用统一前缀加角色,不用人名(人会更替,设备还在)。命名整齐的价值在控制台里体现——看到一堆会话时能立刻知道哪个是干什么的。

三、复现步骤

这一节按分阶段最小可验证组织:每一步都能独立跑通并判定成功,再进下一步。命令里的主机名、地址、网段一律用占位符。

3.1 创建网络

  1. 在组网服务上建一个网络,拿到网络标识。
  2. 每台设备装客户端,按系统选一种:
# Windows(winget 官方包)
winget install --id Tailscale.Tailscale -e --accept-package-agreements --accept-source-agreements
# Linux(官方安装脚本)
curl -fsSL https://tailscale.com/install.sh | sh
# Arch / WSL
sudo pacman -S --needed tailscale

Windows 上客户端不在 PATH 里,要么用全路径调用,要么自己加进 PATH。这是第一次用最容易迷惑的一点。

  1. 第一台设备上线,确认这台设备出现在网络里:
sudo tailscale up --hostname=<设备名> --ssh
tailscale status

3.2 给网络添加设备

接入第二台设备之后,才能验证「任意两台互通」。

# Windows
& "C:\Program Files\Tailscale\tailscale.exe" up --hostname=<设备名>
# Linux 服务器(同时作为子网路由器)
sudo tailscale up --hostname=<设备名> --ssh --advertise-routes=<内网网段>
# WSL
tailscale up --hostname=<设备名> --accept-routes --accept-dns=false

接入时就用最终名字,不要留着默认主机名。加完用 tailscale status 确认列表里有这台设备,再用 tailscale ping 看延迟:

tailscale ping <设备名>

延迟是个位毫秒,说明打洞成功。延迟从个位跳到一百毫秒以上,说明链路掉到中转了,先看是不是有别的 VPN 客户端抢了路由。

3.3 覆盖装不了客户端的设备

打印机一类设备装不了客户端,要把该设备所在的网段通告出去。以下三件事必须同时成立,缺一件就静默不生效、不报错:

在哪做 做什么
网段所在的服务器 打开 IP 转发
组网控制面 批准这条路由通告
每台要访问该网段的客户端 启动时加 --accept-routes
# 服务器端:开转发并持久化
printf 'net.ipv4.ip_forward=1\nnet.ipv6.conf.all.forwarding=1\n' | sudo tee /etc/sysctl.d/99-tailscale.conf
sudo sysctl -p /etc/sysctl.d/99-tailscale.conf

只通告不批准,或者客户端没加 --accept-routes,都不会报错,只是不通。更完整的说明见 Tailscale 组网。

3.4 让任务不随窗口结束

每台要跑 Agent 的机器装会话管理器:

herdr                     # 启动或接入本机后台会话
herdr --remote <主机>     # 跨机接管

Agent 一律在这个会话里启动,会话名按 2.4 的约定写。判断标准很简单:关掉所有终端窗口,第二天回来任务还在。

3.5 一个界面看所有设备与 Agent

按项目官方文档用 Docker 自托管一套控制台,不要用公共托管服务。装好后把各设备接进去,控制台里应该能看到设备列表与各设备上的 Agent。

3.6 通知只留一个渠道

配一个 IM 机器人加一个自建推送服务。渠道只留一个:先接三个渠道的结果通常是没有任何人看。

3.7 验收判据

按阶段验收,不要看「装完了没」,看这几条:

① 两台设备互 ping,延迟是个位毫秒          → L0 打成
② 断网重连(关 WiFi 再开),设备自动回来    → L0 稳定
③ 从一台设备访问到无客户端设备的管理页       → 子网路由三件套齐了
④ 关掉所有终端窗口,第二天回来看任务还在     → L1 打成
⑤ 在控制台里看到全部设备,不用逐台 SSH      → L2 打成
⑥ 手机只留一个通知渠道,仍能收到任务结束通知 → L3 打成
⑦ 把清单文件给一个没参与的人读,
   他能说出每台机器上有什么                  → 可交接

第 ⑦ 条是这套做法真正的完成标准:前面六条说明「能跑」,第七条说明「别人能接手」。

四、成果

做完之后得到的是五样东西:

成果 形态
一张随时可达的设备网 任意两台设备直连互通,装不了客户端的设备也能访问
一批不会随窗口消失的任务 Agent 跑在会话里,换台设备可以接管
一个统一入口 控制台里能看到所有设备与 Agent,不用逐台 SSH
一条通知渠道 任务结束能收到通知,不需要盯着屏幕
一份可交接的清单 新人读完能说出每台机器上有什么

前四样决定这套做法能不能用,第五样决定换人之后这套做法还在不在。

五、已知问题

问题 表现 去哪看
子网路由静默不通 已通告已批准,仍然连不上 3.3 的三件套
延迟突然变高 从个位毫秒跳到一百毫秒以上 Tailscale 组网
服务端口冲突 症状出现在完全无关的服务上 端口占用导致同域名本机访问 404
连接器报记录被占用 The local Connector record is busy,重试无效 Agent 平台部署
组网客户端与其他 VPN 抢路由 打洞失败,流量走中转 Tailscale 组网

相关