手里 VPS 一多,麻烦事就来了:哪台机器磁盘快满了?哪个应用半夜挂了?哪个域名的证书还有几天过期?以前我是哪台出问题才去看哪台,直到 2026 年 10 月 12 日那天,一台 VPS 磁盘被日志写满、直接把网站服务拖垮,我才决定:必须搞一套统一监控。
这是系列文章的第一篇,先讲技术路线——我为什么选了 Beszel + Uptime Kuma + Portainer 这三个工具,它们各自负责什么,整体架构长什么样。后面五篇分别是每个工具的部署实录,跟着做就能复刻。
先说需求:我要监控什么
当时我的家底是 4 台 VPS(博客主机、RackNerd 1G、Bandwagon、Dedirock),每台上面都跑着几个 Docker 应用,还有好几个域名。需求拆开其实就四句话:
- 服务挂了要第一时间知道(网站打不开了、SSH 连不上了);
- 磁盘/内存/CPU出问题前能预警(别再重演磁盘写满拖垮服务);
- HTTPS 证书、域名快到期了要提醒(过期了网站直接变红);
- 容器要能统一看、统一管(哪台机器跑了什么容器,一眼看清)。
再加一个硬性要求:告警必须能推到手机上。监控配得再全,告警只躺在网页仪表盘里没人看,等于没配。
为什么是这三个工具
市面上的方案我捋了一遍,最后定了下面这个组合,理由是:全部开源免费、全部 Docker 一键部署、对只有几台机器的个人用户足够轻。
- Beszel(https://github.com/henrygd/beszel)——看机器内部:每台 VPS 的 CPU、内存、磁盘、流量曲线,外加这台机器上跑了哪些容器。Agent 装到每台机器上,数据汇总到一个 Hub 里看。
- Uptime Kuma(https://github.com/louislam/uptime-kuma)——从外部盯服务活没活:网站 HTTP 是否 200、服务器 22 端口通不通、证书还有几天到期、域名还有几天到期。挂了就告警。
- Portainer CE(https://www.portainer.io)——管容器:四台机器的容器、镜像、日志、重启更新,在一个页面里点点鼠标就能操作,不用每台都 SSH 上去敲命令。版本建议用最新版,我部署时服务端是 2.45.2(2.45.2 及以上都行),注意 Agent 镜像的 tag 必须和服务端版本号对上。
三者分工一句话:Beszel 看机器 inside,Uptime Kuma 从外面敲门,Portainer 负责动手管。Prometheus + Grafana 那套也强,但对个人小集群来说太重了,配起来劝退小白,所以没选。
总体架构
三个服务全部装在博客主机(跑博客的那台 VPS)上,用一个 docker-compose 一把拉起。网络上做了关键隔离:
- 三个容器只监听 127.0.0.1,端口不直接暴露到公网;
- 用博客主机上现成的 LDNMP Nginx 做反代,对外只开三个子域名,全部 HTTPS:
monitor.nettodata.com→ Beszel(本机 8090)status.nettodata.com→ Uptime Kuma(本机 3001)manage.nettodata.com→ Portainer(本机 9000)
- 四个 VPS 上各装一个 Beszel Agent(systemd 服务,监听 45876),只和 Hub 单线联系;
- 告警统一走 Bark 推送到 iPhone 通知栏(安卓可用 Server酱推微信,原理一样)。
画成图就是这样:
┌─────────────┐ Agent(45876) ┌──────────────────────────────┐
│ VPS 2/3/4 │◄─────────────────│ 博客主机 (VPS 1) │
│ (被监控) │ 只收指标 │ ┌─────────┐ ┌──────────────┐ │
└─────────────┘ │ │ Beszel │ │ Uptime Kuma │ │
│ │ Hub │ │ (对外探测) │ │
┌─────────────┐ HTTP/TCP探测 │ └─────────┘ └──────────────┘ │
│ 你的网站/服务 │◄────────────────│ ┌──────────┐ │
└─────────────┘ │ │Portainer │ │
│ └──────────┘ │
│ ▲ Nginx 反代 (443 HTTPS) │
└──┼────────┬────────┬─────────┘
│ │ │
monitor. status. manage.
(Beszel) (Kuma) (Portainer)
└────────┴────────┘
│
Bark 推送 → 手机
告警阈值是怎么定的
阈值太敏感会狼来了,太迟钝等于没有。我定的规则如下(括号里是理由):
- 磁盘:使用率 > 80% 预警、> 90% 严重、> 95% 紧急(10 月 12 日那次就是磁盘 100% 引发的连锁故障,这项最敏感);
- CPU / 内存:持续 10 分钟 > 90% 才告警(瞬时 spike 不告,避免误报);
- 服务 Down:连续 2 次探测失败才告警(防网络抖动);
- 证书:到期前 30 天 / 14 天 / 7 天三级提醒;
- 域名:到期前 60 天 / 30 天 / 14 天 / 7 天提醒;
- Agent 失联:超过 5 分钟按宕机处理。
两个安全设计
监控面板本身也是攻击面,部署时顺手做了两件事:
- 面板不直接暴露端口:全部走 Nginx 反代 + HTTPS + 登录密码,容器端口只绑 127.0.0.1;
- Agent 独立 Key:每台机器的 Beszel Agent 用独立密钥,Hub 的数据要备份——Hub 丢了,所有 Agent 得重新注册一遍。
还有一个单点风险要如实说明:监控和被监控跑在同一台 VPS 上。如果博客主机整台挂了,监控自己也发不出告警。所以还需要一个独立的免费外部哨兵,每隔几分钟 ping 一下监控域名、ping 不通就告警——这部分还没部署,列在待办里,后续单独写一篇。
下一篇
下一篇《多 VPS 统一监控(二):Beszel(一)Hub 部署》讲 Hub 的 Docker 部署、Nginx 反代 + HTTPS 的全过程。