Beszel 运维手册
覆盖 Beszel 上线后的日常巡检、备份恢复(含 integrity_check 演练)、阈值告警创建与触发实测、节点扩缩容、升级回滚与七类故障排查实录——全部操作已在 Ubuntu 22.04(Beszel 0.21.0)实测验证。
Beszel 运维手册
> 目标:覆盖 Beszel 监控平台上线后的日常巡检、备份恢复、告警管理、节点扩缩容、升级回滚与故障排查——所有命令与输出均已在 Ubuntu 22.04 服务器(Beszel Hub/Agent 0.21.0,Docker 29.8.1)实测验证。
一、环境信息
本手册所有操作在以下环境实测完成(数据采集时间 2026-10-17):
- 操作系统:Ubuntu 22.04.4 LTS(x86_64)
- Beszel Hub:henrygd/beszel:latest(实测 0.21.0),端口 8090,数据目录
/opt/data/beszel - Beszel Agent:henrygd/beszel-agent:latest(实测 0.21.0),端口 45876
- 编排目录:
/opt/data/beszel-lab(compose.yml、.env,见《Beszel Docker Compose 部署指南》) - 接入节点:beszel-agent-node1(本机)、beszel-agent-node2(第二节点,45878 端口)
- 演示管理员:admin@quzuo.net(认证 Token 获取方式见第二章,不落明文)
后续所有 API 命令依赖登录 Token,统一用以下方式取得(每节示例中的 $TOKEN 均指它):
TOKEN=$(curl -s -X POST http://localhost:8090/api/collections/users/auth-with-password \
-H 'Content-Type: application/json' \
-d '{"identity":"admin@quzuo.net","password":"q1w2e3r4"}' \
| python3 -c "import sys,json;print(json.load(sys.stdin)['token'])")
实测无输出(变量赋值),可用 echo ${#TOKEN} 验证长度:
echo ${#TOKEN}
实测输出:
224
二、日常巡检
日常巡检的目标是四件事:服务活着、版本正确、节点在报数、数据在落盘。以下四项各给一条命令与实测输出,建议纳入每日巡检清单。
2.1 服务运行状态与版本
cd /opt/data/beszel-lab && docker compose ps --format 'table {{.Name}}\t{{.Status}}'
实测输出:
NAME STATUS
beszel-0.21.0-agent Up 15 minutes
beszel-0.21.0-hub Up 15 minutes
curl -s http://localhost:8090/api/beszel/info -H "Authorization: $TOKEN"
实测输出:
{"key":"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIPLUxo4t9n4W86eZ4QBzKgtWQhl3namsh5kaWcBHD8j","v":"0.21.0","cu":false}
判读:两个服务 Up、v 为预期版本即通过;key 字段可顺便与 .env 中 Agent 配置的公钥核对(防私钥误换,见 7.1 节)。
2.2 节点在线状态
curl -s 'http://localhost:8090/api/collections/systems/records?perPage=5&fields=name,status,updated' \
-H "Authorization: $TOKEN" | python3 -m json.tool --no-ensure-ascii
实测输出:
{
"items": [
{
"status": "up",
"name": "beszel-agent-node2",
"updated": "2026-10-17 11:35:31.412Z"
},
{
"status": "up",
"updated": "2026-10-17 11:35:29.582Z",
"name": "beszel-agent-node1"
}
],
"page": 1,
"perPage": 5,
"totalItems": 2,
"totalPages": 1
}
判读:status 应全为 up;updated 与当前时间差超过 1 分钟即说明上报停滞(正常每分钟写入新统计记录)。
2.3 指标采集时延
curl -s 'http://localhost:8090/api/collections/container_stats/records?perPage=1&sort=-created&fields=created' \
-H "Authorization: $TOKEN"
实测输出:
{"perPage":1,"totalItems":117,"totalPages":117,"items":[{"created":"2026-10-17 11:35:29.582Z"}],"page":1}
判读:最新记录 created 距今应在 1 分钟内(采集周期为 1 分钟);totalItems 持续增长说明历史数据正常入库。
2.4 数据目录容量
du -sh /opt/data/beszel/ && ls -la /opt/data/beszel/data.db*
实测输出(运行数小时后):
2.5M /opt/data/beszel/
-rw-r--r-- 1 root root 790528 10月 17 19:20 /opt/data/beszel/data.db
-rw-r--r-- 1 root root 32768 10月 17 19:35 /opt/data/beszel/data.db-shm
-rw-r--r-- 1 root root 1734552 10月 17 19:36 /opt/data/beszel/data.db-wal
判读:SQLite 数据库极小(2 台节点、2 个统计集合,数小时约 2.5 MB),按本机 30 个 Docker 统计对象 + 分钟粒度估算,一年量级仍在数十 MB,磁盘压力可忽略;巡检时确认 -wal 文件随运行增长属正常(检查点机制自动合并)。
三、备份与恢复
3.1 备份范围
全部持久化状态都在 Hub 数据目录 /opt/data/beszel(挂载自宿主机),包括主库 data.db、连接 Agent 的 SSH 私钥 id_ed25519、辅助库 auxiliary.db 与通知数据 .notify/。私钥丢失会导致所有 Agent 拒绝连接(7.1 节),因此备份必须包含整个目录。Agent 侧无状态,无需备份。
3.2 备份实测(tar 打包)
tar czf /opt/data/quzuo/beszel-lab/beszel-backup-$(date +%Y%m%d).tar.gz -C /opt/data beszel/
确认备份包:
ls -la /opt/data/quzuo/beszel-lab/beszel-backup-*.tar.gz
实测输出:
-rw-r--r-- 1 root root 401774 10月 17 19:36 /opt/data/quzuo/beszel-lab/beszel-backup-20261017.tar.gz
tar tzf /opt/data/quzuo/beszel-lab/beszel-backup-20261017.tar.gz
实测输出:
beszel/
beszel/.keep
beszel/id_ed25519
beszel/data.db-shm
beszel/data.db-wal
beszel/auxiliary.db
beszel/data.db
beszel/.notify/
要点:包内 data.db-wal 是运行中数据库的未合并写入,必须连同主库一起备份(本命令 tar 的是运行中目录,天然包含);如需绝对一致的快照,可先 docker compose stop hub 再打包。
3.3 恢复演练实测
恢复 = 停 Hub → 解包覆盖数据目录 → 起 Hub → 校验。先在临时目录演练解包与库完整性校验:
mkdir -p /tmp/beszel-restore-test && tar xzf /opt/data/quzuo/beszel-lab/beszel-backup-20261017.tar.gz -C /tmp/beszel-restore-test
python3 -c "
import sqlite3
con = sqlite3.connect('/tmp/beszel-restore-test/beszel/data.db')
print('integrity_check:', con.execute('PRAGMA integrity_check').fetchone()[0])
print('systems:', con.execute('SELECT COUNT(*) FROM systems').fetchone()[0])
print('users:', con.execute('SELECT COUNT(*) FROM users').fetchone()[0])
con.close()"
实测输出:
integrity_check: ok
systems: 2
users: 1
判读:integrity_check: ok 表示备份中的库完整可用,系统与用户记录齐全。真实恢复时执行 docker compose stop hub → rm -rf /opt/data/beszel && tar xzf <备份包> -C /opt/data → docker compose start hub,随后按 2.1/2.2 节复查版本与节点状态即可。
3.4 定时备份
crontab 追加一行(每日 03:30 打包到备份目录,保留策略由备份盘容量决定):
crontab -l 2>/dev/null; echo '30 3 * * * tar czf /data/backup/beszel-backup-$(date +\%Y\%m\%d).tar.gz -C /opt/data beszel/'
⚠️ 注意:
date +%Y%m%d在 crontab 中%必须转义为\%(crontab 把裸%当换行),否则该行会被截断、备份静默失败。
四、监控告警
4.1 告警能力总览
Beszel 内置基于阈值的告警:对每个节点可按指标类型设置阈值,越限并持续指定分钟数后触发,通过页面通知或 SMTP/Webhook 外发。
💡 技术拓展:监控告警的判定方式不止「静态阈值」一种。常见方式对比——
方式 原理 优点 缺点 静态阈值 指标超过固定值即告警 简单直观、可预期 阈值需人工维护,易误报/漏报 同比/环比 与历史同期或前 N 分钟对比 自适应业务波动 冷启动期不准 异常检测 统计/ML 模型判定偏离 免维护阈值 黑盒、调参成本高 黑盒拨测 从外部定期探测服务可用性 直接度量用户体验 看不到内部指标 Beszel 实测提供静态阈值 + 持续时长(
min字段)组合,属于第一类;对轻量自托管场景够用,复杂告警需求可把 Webhook 对接 Alertmanager 等外部系统再加工。
4.2 告警规则类型与字段
规则类型为固定枚举(0.21.0 实测从数据字典读出):Status、CPU、Memory、Disk、Temperature、Bandwidth、GPU、LoadAvg1、LoadAvg5、LoadAvg15、Battery、ContainerHealth、SystemdFailed、CPUIOWait、CPUSteal、NetworkMonitorLoss。
字段说明(实测 schema):
| 字段 | 类型 | 必填 | 含义 |
|---|---|---|---|
name | 枚举 | 是 | 告警指标类型(上表枚举之一) |
value | 数字 | 否 | 触发阈值(如 CPU 百分比、Disk 百分比;Status 不需要) |
min | 数字 | 否 | 持续分钟数:越限持续该时长才触发 |
system | 关联 | 是 | 所属节点记录 ID |
user | 关联 | 是 | 归属用户 ID(接收告警通知的用户) |
triggered | 布尔 | 自动 | 当前是否处于触发态 |
唯一约束:(user, system, name) 组合唯一——同一用户对同一节点的同一指标只能建一条规则。
4.3 创建告警规则实测
为 node1 创建 Memory 告警(阈值 90%、持续 5 分钟):
curl -s -X POST http://localhost:8090/api/collections/alerts/records \
-H "Authorization: $TOKEN" -H 'Content-Type: application/json' \
-d '{"name":"Memory","value":90,"min":5,"system":"u3q4gtml3pv3us0","user":"egb5322xmdbhc47"}'
实测输出:
{"collectionId":"elngm8x1l60zi2v","collectionName":"alerts","created":"2026-10-17 11:38:46.512Z","id":"w2b6oozxh5cks5t","min":5,"name":"Memory","system":"u3q4gtml3pv3us0","triggered":false,"updated":"2026-10-17 11:38:46.512Z","user":"egb5322xmdbhc47","value":90}
查询规则清单与触发态:
curl -s 'http://localhost:8090/api/collections/alerts/records?perPage=10&fields=name,value,min,triggered,created' \
-H "Authorization: $TOKEN" | python3 -c "import sys,json; [print(i) for i in json.load(sys.stdin)['items']]"
实测输出:
{'triggered': True, 'created': '2026-10-17 08:14:32.254Z', 'min': 0, 'name': 'CPU', 'value': 1}
{'triggered': False, 'created': '2026-10-17 11:38:46.512Z', 'min': 5, 'name': 'Memory', 'value': 90}
⚠️ 注意(实测踩坑):创建规则时两个字段极易写错——
user必须用当前 Hub 的用户记录 ID 且字段名是单数user(写成users数组返回 400);value必须是数字(写成字符串"85"同样 400,回显为{"data":{},"message":"Failed to create record.","status":400},不提示具体原因)。遇到 400 先核对这两处。
4.4 触发行为实测
实测一条低阈值 CPU 规则(阈值 1%、持续 0 分钟):创建于 08:14:32.254Z,13 秒后(08:14:45.636Z)即翻转为 triggered: true(本机 CPU 3.2% > 1%)——验证了「越限即触发」链路真实可用。min 字段生效时,需越限持续满指定分钟数才触发,实测 2.2 节的 Memory 规则(90%/5min)在内存 28% 时长期保持 triggered: false,未误报。
解除触发:指标回落到阈值以下并保持后,triggered 自动翻回 false;页面规则列表的铃铛图标同步消警。删除规则(实测删除一条 Status 规则,ID edz9mzic8yx5a1g):
curl -s -o /dev/null -w 'http_code=%{http_code}\n' \
-X DELETE http://localhost:8090/api/collections/alerts/records/edz9mzic8yx5a1g -H "Authorization: $TOKEN"
实测输出:
http_code=204
删除后复核清单,该规则已消失:
curl -s 'http://localhost:8090/api/collections/alerts/records?perPage=10&fields=name,value,triggered' \
-H "Authorization: $TOKEN" | python3 -c "import sys,json; [print(i) for i in json.load(sys.stdin)['items']]"
实测输出:
{'name': 'CPU', 'triggered': True, 'value': 1}
{'name': 'Memory', 'triggered': False, 'value': 90}
4.5 Status 告警的行为边界(实测)
Status 类型用于节点失联告警,实测发现一个重要行为:在节点已经处于 down 状态时新建 Status 规则,不会补触发(triggered 保持 false,等待状态恢复后再按「正常→失联」跃迁判定)。因此 Status 规则应在节点健康时预先创建,不要等故障来了再建。节点失联→恢复的完整演练实录见 7.7 节。
五、扩容缩容
5.1 扩容:新增被监控节点
以第二节点(主机名 agent2,监听 45878)为例。在被监控机器上按《Beszel Docker Compose 部署指南》4.1/4.4/4.5 节启动 Agent(KEY 填 Hub 公钥、PORT 填 45878),然后在 Hub 侧添加节点:
curl -s -X POST http://localhost:8090/api/collections/systems/records \
-H "Authorization: $TOKEN" -H 'Content-Type: application/json' \
-d '{"name":"beszel-agent-node2","host":"agent2","port":"45878","users":["egb5322xmdbhc47"]}'
实测输出:
{"id":"guzs42rlb9mshds","name":"beszel-agent-node2","host":"agent2","port":"45878","status":"pending"}
约 20 秒后验证上线:
curl -s "http://localhost:8090/api/collections/systems/records/guzs42rlb9mshds?fields=status,info.v" \
-H "Authorization: $TOKEN"
实测输出:
{"status":"up","info":{"v":"0.21.0"}}
实测经验:从 pending 到 up 约需 8~25 秒(Hub 周期性发起 SSH 连接);若持续 pending/down,按 7.1 节排查 KEY 与网络可达性。
5.2 缩容:摘除节点
摘除 = 删除 Hub 上的系统记录(可选:在被监控机器停掉 Agent 进程)。实测先建一条演示记录再摘除,完整呈现缩容闭环:
curl -s -X POST http://localhost:8090/api/collections/systems/records \
-H "Authorization: $TOKEN" -H 'Content-Type: application/json' \
-d '{"name":"beszel-agent-docdemo","host":"agent-demo","port":"45879","users":["egb5322xmdbhc47"]}'
实测输出:
{"id":"7w7qlumlwhetfic","name":"beszel-agent-docdemo","host":"agent-demo","port":"45879","status":"pending"}
摘除该记录:
curl -s -o /dev/null -w 'delete http_code=%{http_code}\n' \
-X DELETE http://localhost:8090/api/collections/systems/records/7w7qlumlwhetfic -H "Authorization: $TOKEN"
实测输出:
delete http_code=204
该节点的指标历史随级联删除一并清理。删除后核对剩余节点:
curl -s 'http://localhost:8090/api/collections/systems/records?perPage=10&fields=name,status' \
-H "Authorization: $TOKEN" | python3 -c "import sys,json; [print(i['name'], i['status']) for i in json.load(sys.stdin)['items']]"
实测输出:
beszel-agent-node2 up
beszel-agent-node1 up
⚠️ 注意:实测中曾把 Hub 专用网络上的节点摘除,但该 Agent 仍挂在网络上,导致
docker compose down报Network ... Resource is still in use(见 7.4 节)。缩容时先docker network disconnect或直接停容器再删记录。
六、升级与回滚
6.1 升级流程
Beszel 升级 = 拉新镜像 → 重建容器 → 核对版本。数据在宿主机目录,重建不影响:
cd /opt/data/beszel-lab && docker compose pull
实测输出:
Image henrygd/beszel-agent:latest Pulling
Image henrygd/beszel:latest Pulling
Image henrygd/beszel:latest Pulled
Image henrygd/beszel-agent:latest Pulled
cd /opt/data/beszel-lab && docker compose up -d --force-recreate
实测输出:
Container beszel-0.21.0-hub Recreated
Container beszel-0.21.0-agent Recreated
Container beszel-0.21.0-agent Starting
Container beszel-0.21.0-hub Starting
Container beszel-0.21.0-agent Started
Container beszel-0.21.0-hub Started
核对版本与数据完好:
curl -s http://localhost:8090/api/beszel/info -H "Authorization: $TOKEN"
实测输出(重建后):
{"key":"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIPLUxo4t9n4W86eZ4QBzKgtWQhl3namsh5kaWcBHD8j","v":"0.21.0","cu":false}
系统记录与告警历史重建后全部保留(实测 systems 2 条 up、alerts total: 1,命令与输出见《Beszel Docker Compose 部署指南》5.2 节,本机复核一致)。
💡 说明:Agent 升级需逐台把新镜像拉到对应机器并重建 Agent(多节点时在各节点分别执行 pull 与重建,每台单独操作);Hub 全局一个,重建即全局生效。0.21.0 实测 Hub 与 Agent 版本需保持一致,升级后按 2.2 节确认所有节点
info.v为新版本。
6.2 回滚方案
回滚 = 把镜像标签固定回旧版本再重建。编辑 compose.yml 把 henrygd/beszel:latest 与 henrygd/beszel-agent:latest 改为上一版本的语义化标签(如 henrygd/beszel:v0.21.0),然后:
cd /opt/data/beszel-lab && docker compose pull && docker compose up -d --force-recreate
再用 6.1 节的 info 接口核对 v 已回到旧版本。两处实测注意:
- 国内镜像加速源可能未同步历史版本标签,实测拉取
v0.21.0时返回:
Error response from daemon: error from registry: denied
解决:重试、更换加速源或直连 Docker Hub(见 7.5 节)。
- 回滚前先按第三章做一次备份——跨版本回滚如遇数据结构变更,可直接回退到升级前状态。
七、故障排查手册
本章收录实测环境出现过的全部故障与处置实录,按现象索引。
7.1 节点状态 down,Agent 日志 Invalid SSH key
现象:Hub 页面节点持续 down,Agent 日志出现:
2026/10/17 11:17:03 WARN Invalid SSH key addr=172.31.0.2:48742
定位:Agent 端 KEY 与 Hub 当前公钥不匹配(Hub 重装、数据目录更换或 id_ed25519 被误删重生后必然发生)。
解决:从 Hub 重新取公钥(2.1 节 info 接口的 key 字段),更新 Agent 的 KEY 环境变量后重建 Agent。实测修复后 Agent 日志恢复:
2026/10/17 08:28:45 INFO SSH connected addr=172.31.0.2:45290
7.2 API 返回 401
现象:curl /api/beszel/info 返回:
{"data":{},"message":"The request requires valid record authorization token.","status":401}
解决:0.21.0 该接口需认证。按第一章方式取 $TOKEN 后重试,加 -H "Authorization: $TOKEN"。
7.3 Hub 日志 Error getting container stats
现象(实测三类,均为个别统计对象的瞬态错误):
ERROR Error getting container stats err="infallible_lichterman - bad memory stats - see https://github.com/henrygd/beszel/issues/144"
ERROR Error getting container stats err="container stats request failed: 404 Not Found"
WARN Bad network delta container=surreal-curl-helper
结论:第一条对应内核未提供有效 memory 统计(cgroup 差异,官方 issue #144),第二条对应统计瞬间容器已退出,第三条为网络计数增量异常。实测均不影响其他对象采集——同时刻 Docker 统计仍有 30 个对象正常入库。无需处理。
7.4 docker compose down 报网络被占用
现象:
Network beszel-lab_beszel-net Removing
Network beszel-lab_beszel-net Resource is still in use
定位:该网络上还有不属于本编排的容器(本文实测是排障用的第三只 Agent)。
解决:docker network inspect beszel-lab_beszel-net 查看占用者,逐一 docker stop 或 docker network disconnect 后重试;或保留网络仅 docker compose stop。该保护行为防止误删他人网络,属预期设计。
7.5 镜像拉取 denied / 502
现象:实测拉取非 latest 标签时加速源返回:
Error response from daemon: error from registry: denied
解决:重试(实测数分钟后同一源拉 latest 成功)、更换加速源或直连 Docker Hub。升级操作前建议先手动 docker pull 验证标签可得。
7.6 页面无温度数据
定位:运行环境(虚拟机/受限环境)内无 hwmon 传感器设备。
解决:按部署指南 8.3 节挂载宿主机传感器目录并设置 SYS_SENSORS。实测开启后指标记录出现温度字段:
{"t":{"coretemp_package_id_0":45.5}}
真机(裸金属)部署一般无需任何配置。
7.7 节点失联与恢复演练实录
注入:停掉第二节点 Agent,观察 Hub 判定:
docker stop beszel-0.21.0-agent-node2
实测输出:
beszel-0.21.0-agent-node2
等待约 70 秒后查询节点状态:
curl -s 'http://localhost:8090/api/collections/systems/records?perPage=5&fields=name,status,updated' \
-H "Authorization: $TOKEN" | python3 -c "import sys,json; [print(i['name'], i['status'], i['updated']) for i in json.load(sys.stdin)['items']]"
实测输出:
beszel-agent-node2 down 2026-10-17 11:40:31.543Z
beszel-agent-node1 up 2026-10-17 11:40:29.589Z
实测结论:Agent 停止后约 1 分钟内 Hub 将节点判为 down(失联判定周期分钟级),其余节点不受影响。
恢复:
docker start beszel-0.21.0-agent-node2
等待约 40 秒后复查:
curl -s 'http://localhost:8090/api/collections/systems/records?perPage=5&fields=name,status' \
-H "Authorization: $TOKEN" | python3 -c "import sys,json; [print(i['name'], i['status']) for i in json.load(sys.stdin)['items']]"
实测输出:
beszel-agent-node2 up
beszel-agent-node1 up
节点自动回归 up,期间历史数据不丢(失联时段仅缺数,不产生空洞补齐)。配合 4.2 节的 Status 规则,这一跃迁会触发失联告警——但注意 4.5 节实测结论:规则须在健康时预先创建。
八、常见问题(FAQ)
Q1:巡检发现某节点一直 pending,怎么排查?
按顺序核对三处:Agent 进程存活(对应机器上 docker compose ps)、Agent 端口对 Hub 可达(在 Hub 侧执行 curl -s --max-time 3 telnet://<节点IP>:45878 或 telnet 测试)、KEY 与 Hub 公钥一致(7.1 节)。三者都正常仍在 pending,重启 Agent 后观察 1 分钟。
Q2:告警触发后如何确认通知已外发?
先确认规则 triggered: true(4.3 节查询),再检查用户通知渠道配置(页面后台 Notifications 设置 SMTP/Webhook)。实测 API 层面 triggered 翻转即代表告警事件成立,外发失败常见原因是 SMTP 凭据错误,查看 Hub 日志 docker logs beszel-0.21.0-hub | grep -i notify 定位。
Q3:数据目录磁盘增长过快怎么办?
先 du -sh /opt/data/beszel/(2.4 节)确认量级;实测本场景增长主因是 Docker 统计对象多的机器分钟级入库。Beszel 页面后台可设置数据保留时长(Settings → 数据清理),按需缩短保留期;同时核对 -wal 文件是否异常巨大(正常随检查点合并回落)。
九、参考链接
- 官方文档首页:https://www.beszel.dev
- 官方入门指南:https://www.beszel.dev/guide/getting-started
- GitHub 仓库:https://github.com/henrygd/beszel
- 部署步骤与镜像说明:见《Beszel Docker Compose 部署指南》
- 架构与选型说明:见《Beszel 介绍与选型指南》
- 相关文档:《Uptime Kuma 运维手册》《Alertmanager Docker Compose 部署指南》《Grafana 配置参数详解》