玩自托管的朋友,应该都有过这种经历:手底下三台机器、五台机器,每天都在盯着温度、磁盘、进程看。每次开机第一件事就是开一堆终端,SSH到每台机器上去敲命令,敲完就忘,下次又得重新敲。OpenRig就是为了解决这个局面做的一个开源小工具——它用一套轻量的Web仪表盘,把每台主机的实时状态聚合到同一个页面,温度、负载、磁盘、内存、在线状态一目了然,配好脚本之后还能自己生成监控指标。项目本身很小,装起来也就一条命令的事,适合家庭实验室玩家、渲染农场管理员、工作室网管,以及所有嫌重型监控方案太麻烦的人。
这套东西的核心思路很简单:被监控的主机上跑一个轻量Agent,定时把数据推到服务端,服务端负责存储、展示和告警。没有消息队列、没有微服务、没有若干数据库。整个后端是一个单一二进制文件,前端是一个不依赖构建工具的简单页面。所以它能跑到树莓派、软路由、老笔记本这种低配设备上,也可以管几十台机器。下面我就把整个项目从设计到部署,再到我踩过的坑,完整写一遍。
1. 为什么我会做OpenRig:自托管监控的几个痛点
1.1 从折腾SSH到想做仪表盘
最早我管理三台机器的方式,是给每台机器写好一个固定的Shell脚本,每天手动跑一遍,输出CPU温度、硬盘健康度、内存占用。脚本本身没问题,但问题在于"看"的过程。每次都要一个终端一个终端地连上去,明明只是想知道"有没有哪台温度偏高",却要把所有机器的输出从头到尾扫一遍。等机器数量涨到七八台的时候,这个动作基本就变成了负担。
我试过很多现成方案。Grafana加Prometheus加node_exporter确实强大,数据密度高、可视化也漂亮,但配置成本和学习曲线放在那儿,光是搞懂promql怎么写就要几天。它更像一个为专业监控场景设计的瑞士军刀,而我只想快速回答"今天这几台机器是否正常"。
1.2 我眼中的"够用就好"
OpenRig从一开始就明确了一件事:不做全功能监控平台,只做一个能让人坚持用下去的轻量系统。我把"够用"定义成三条标准。
第一,部署时间控制在五分钟以内。我不希望用户在搭建监控系统这件事上花的时间比监控本身还多。第二,资源占用低。目标是一台树莓派上既能跑服务端,又能干别的事,空闲内存最好不超过100MB。第三,扩展要容易。用户不需要理解一套复杂的插件机制,只要会写一个能输出JSON的脚本,就能把自己关心的任何指标加进去。
有些朋友可能觉得这套逻辑太简陋。但说实话,对于几台到几十台机器的规模,我们需要的不是百分之百的指标覆盖率,而是一个可持续运转的观测窗口。当你打开仪表盘,发现所有主机都在线、温度曲线平稳、没有告警跳出,这就是监控系统最大的价值。
2. 整体架构与核心设计取舍
2.1 客户端-服务端模型,为什么不用无代理方案
设计监控系统时,第一步是决定数据采集方式。我调研过无代理方案:通过SNMP去读设备状态、通过SSH远程执行命令。SNMP在交换机、打印机这类网络设备上是主流选择,但对于普通PC和服务器,它能拿到的信息太有限,CPU使用率、进程列表、传感器温度这些常见指标,很多设备根本不提供标准OID。SSH远程执行命令倒是灵活,但每次采集都要建立连接、做认证,频率高了既慢又容易把被监控机器搞出大量认证日志。
所以OpenRig选择了有代理模型。每台被监控主机运行一个Agent进程,Agent自己负责采集本机数据,然后通过HTTP推送到服务端。这样做有几个实打实的好处:端口只需要服务端开一个,被监控主机不需要暴露任何入站端口,不容易成为攻击面;采集频率和采集内容完全由Agent控制,动态增加指标也不需要动服务端;还有,Agent可以离线缓存数据,等网络恢复后再补报,无代理方案很难实现这一点。
2.2 技术选型:只选节省运维时间的
服务端我选Go来写。核心考量是部署便利性:Go编译出来是静态二进制,丢到服务器上就能跑,连依赖都不用装。对于一台可能还要跑数据库、Web服务器、其他业务的老机器,能少一个运行时就是少一个坑。Agent端我只保留一个轻量的C语言实现和一个Python实现,Python那边方便用户嵌入自己的采集逻辑,C版本则用于低配设备和容器环境。
前端没有引入Vue或者React工程,因为对于这种以图表展示和列表刷新为主的页面,原生JavaScript配合Chart.js已经足够了。少一层构建工具就少一层维护负担,升级依赖、修复构建问题这一整套流程在小项目里都是纯成本。
数据存储用的是SQLite,很多人在这一步会质疑。其实根据我的实测,一台机器即使每三十秒上报十条指标,一天的数据量也就几十MB。几十台机器、保留三十天,SQLite完全扛得住。定期跑一次清理,把超过期限的数据删除,或者降采样聚合,写入和查询都不会有瓶颈。真要到了上万台设备那种量级,再考虑换时间序列数据库也不迟,OpenRig的数据模型设计也保证了迁移成本不会高。
2.3 指标模型:像Prometheus,但砍掉一半复杂度
接入过Prometheus的人都知道labels的概念非常好用,但PromQL的查询语法对于普通用户来说门槛不低。OpenRig简化了这套模型:每个指标由核心字段(主机名、指标名、值、时间戳)加一组可选的键值对标签组成。采集端上报数据时已经附带标签,服务端存储时原样记录,前端通过下拉框筛选特定标签组合。
打个比方,Prometheus像是一套完整的编程语言,而OpenRig只保留了常用的那几个函数:按时间范围取平均值、最大值、最新值,以及按标签分组聚合。基本覆盖了日常监控的绝大多数需求。
采集扩展我设计成了"脚本调用"形式。Agent定时执行一个或多个外部命令,标准输出如果是合法JSON,就自动解析为指标数据。例如用户想监控一个目录的大小,只需要写一个打印JSON的Shell脚本或Python脚本,然后告诉Agent每十分钟跑一次。不用编写插件、不用重新编译、不用重启Agent,脚本更新了下次执行自然生效。
3. 从零部署OpenRig:5分钟跑通最小系统
3.1 准备环境和解压部署包
部署过程我尽量压到最简。服务端支持两种启动方式,任选其一。
第一种是Docker方式,适合已经装了Docker的环境:
mkdir -p /opt/openrig/data docker run -d --name openrig-server \ -p 8080:8080 \ -v /opt/openrig/data:/data \ openrig/server:latest第二种是二进制方式,适合不想引入容器的情况:
wget https://example.com/openrig-server-linux-amd64.tar.gz tar xf openrig-server-linux-amd64.tar.gz ./openrig-server --data /opt/openrig/data --bind 0.0.0.0:8080启动之后,第一次访问会要求创建管理员账号。这里有个细节:默认绑定的是0.0.0.0:8080,意味着局域网内所有人都有可能访问这个端口。如果你不想让别人看到你机器的监控数据,就一定要在初始化后开启访问密码,或者把--bind改成127.0.0.1再在前面挂一层反向代理。
注意:Docker映射端口时,建议只把你需要的端口暴露出去。生产环境里更稳妥的做法是让Docker容器使用
host网络,或者直接用二进制方式部署,这样服务端不需要额外维护NAT映射关系。
3.2 在受管主机上注册并上报数据
服务端起来之后,下一步是把每台被监控主机接入进来。后台有一个"添加主机"入口,会生成一次性注册链接,在目标主机上执行:
curl -fsSL http://10.0.0.2:8080/install.sh | bash -s -- --token 一串一次性Token这条命令会下载Agent、写入systemd服务配置并启动,整个过程大约十几秒。你也可以选择纯手动方式:在受管主机上安装Agent二进制,然后执行:
openrig-agent --server http://10.0.0.2:8080 --token 一串一次性Token注意这里传的是服务端的内网地址。如果服务端部署在公网且没有配置HTTPS,那Token被截获的风险会比较高,建议在受控环境下使用。
Agent启动后会在后台每三十秒上报一次本机的基础指标:CPU使用率、内存占用、磁盘空间、网络流量、整机温度(如果系统支持)。你可以在服务端页面看到在线状态立即变成"在线",大约一分钟内仪表盘上开始出现第一波数据。
3.3 快速验证数据是否入库
如果页面没有出现数据,通常需要先确认是不是真的入库了。服务端安装目录下有一个metrics.db的SQLite文件,你可以直接查询:
SELECT hostname, metric, value, ts FROM metrics ORDER BY ts DESC LIMIT 10;能看到最近十条记录,说明链路是通的。如果查询不到数据,优先检查Agent进程状态和日志:
systemctl status openrig-agent journalctl -u openrig-agent -f日志里通常直接写了HTTP上报失败的原因,最常见的是URL拼错、Token过期或服务端防火墙把8080端口挡了。
3.4 仪表盘和告警的基本配置
数据进来之后,默认的仪表盘就能展示实时数值了。页面下方有"主机列表",点击任意主机可以看到该主机的全部指标时间曲线。
OpenRig的告警规则配置页支持三种逻辑条件:指标值超过阈值、指标值低于阈值、主机持续离线。每套规则都可以设置"连续多少次才触发",这是为了过滤瞬时抖动。
一个温度告警的例子:
- 指标名:
cpu_temp - 条件:
> 90 - 连续次数:
3 - 通知渠道:Webhook
当CPU温度连续三次采集都超过90度,才会触发告警。如果中间出现一次80度,计数会清零重来。这个机制能在很大程度上避免没必要的打扰。
4. 我在实际部署中踩过的坑
4.1 Linux读取温度信息的权限问题
我最初在一台装了新版Ubuntu的NUC上测试,Agent报上来的cpu_temp一直是空的。排查了半天,发现原因很简单:普通用户执行sensors命令时没有权限读取传感器数据,Agent默认也不是以root身份运行的。
解决办法有几个方案。如果只是想快速验证,可以把Agent的systemd单元改成User=root,但我不建议长期这样干,毕竟监控进程拥有root权限的本身就属于安全隐患。更好的做法是把传感器读取权限加到用户组:
sudo usermod -aG openrig openrig-agent-user sudo chmod g+r /sys/class/hwmon/hwmon*/temp*_input前一种方案适用于测试环境,后一种方案相对安全一些,但不同硬件平台的sysfs路径并不一致,所以还是要根据实际环境做调整。这类"周围都正常、就是没数据"的问题,最考验排查耐心。
4.2 时间不同步导致数据乱序
有段时间我的仪表盘上曲线图经常出现"时间倒挂"和锯齿状跳动,看起来像数据错了,实际是好几台机器的系统时间都偏移了。Docker容器默认使用的UTC时区不会改变系统时间,但如果你在KVM虚拟机或某些轻量云主机上跑,宿主机时间不准是完全可能的事。
给所有受管主机安装chrony并启用网络时间同步之后,这类问题基本绝迹:
sudo apt install chrony sudo systemctl enable --now chronyd还要顺手检查一下时区。OpenRig展示时间默认用的是浏览器本地时区,但如果服务端本身时间是UTC,而你在东八区,看曲线的时候总会觉得晚八个小时。建议所有主机都统一成UTC,时区转换交给页面处理,会省心很多。
4.3 网络抖动造成告警风暴
另一个让我印象深刻的坑是告警风暴。某一天凌晨,一台交换机因为固件问题导致整个网段大面积丢包,几十台Agent纷纷上报失败,离线告警在十分钟内刷了上百条。这种告警对值班的人没有任何帮助,反而会让真实的故障被淹没在噪音里。
我后来给"离线告警"加了一个"确认时长"参数:某台主机失联后,必须持续超过五分钟才算离线。同时把"连续次数"机制应用到所有告警规则上。另外还引入了一个简单粗暴的"告警收敛"策略:同一个规则触发的告警,在十五分钟内只通知一次,除非状态恢复后再次触发。这套组合下来,告警量明显下降,而真正的故障(比如某台主机断电)并不会被漏掉。
4.4 数据库无限膨胀
起初为了图省事,原始数据不分时间范围一直存。跑了两个月,SQLite文件膨胀到好几个GB,查询响应从毫秒级变成秒级,整个页面都开始卡。后来我做了分级存储:
- 原始数据保留72小时,用于出图和短期分析
- 五分钟聚合数据保留三十天,用于日常趋势查看
- 小时级聚合数据保留一年,用于长期容量规划
这个策略对小型自托管场景非常合适。聚合数据是通过一条SQL语句在后端定时任务里完成的,粒度丢失也完全可以接受。做监控的人最容易犯的错,就是在不了解自己真实需求的情况下,把数据全量保存,最后被数据本身压垮。
5. 常见问题与排查思路速查表
下面这个表格是几个高频问题的排查路径,基本覆盖了部署初期80%的情况。
| 症状 | 可能原因 | 处理方式 |
|---|---|---|
| Agent启动后立即退出 | Token无效或已被使用 | 在服务端后台重新生成Token,确认Token只使用一次 |
| 页面显示离线,但Agent进程存在 | Agent上报地址不不能访问 | 在受管主机上执行curl测试服务端地址和端口 |
| 某些指标在页面上为空 | 采集脚本权限不足 | 检查Agent运行用户是否具备读取对应系统信息的权限 |
| 曲线正常但数值明显偏高/偏低 | 采集脚本单位换算错误 | 在页面查看该指标的原始值,与本地手动执行结果对比 |
| 告警触发次数非常多 | 阈值设置过小或连续次数为1 | 适当提高阈值,并把连续次数改为2-3次 |
| 访问页面很慢 | 查询范围过大或数据未清理 | 升级到最新版,配置好数据保留策略 |
| 磁盘告警误报 | 监控了临时文件挂载点 | 在采集器配置中排除容器运行时目录 |
| 升级后历史数据丢失 | 数据目录未正确挂载 | 确认Docker挂载卷和--data参数指向原来的目录 |
排查时记得先看最基础的链路:Agent是否运行、上报是否成功、服务端是否入库。大多数人遇到的都是一层简单的配置问题,不需要一上来就怀疑代码有Bug。
6. 扩展:让OpenRig融入你的自动化体系
6.1 Webhook把告警推到工作群
默认的告警通知只会在服务端界面顶部弹红条,真正有运营价值的是把它推到消息群里。OpenRig的告警规则里可以配置Webhook地址,触发时 POST 一条固定格式的JSON。我自己的做法是接了一个群机器人的接口,晚上温度超过阈值时直接发到值班群里。这个改动只需要在后台填一个URL,不需要改代码,效果却非常明显。
6.2 开放API做联动自动化
监控不只是为了看,更是为了自动响应。OpenRig的服务端暴露了简单的REST API,如果你愿意的话,可以自己做一个自动化联动:
- 某台主机连续离线超过十分钟,就把这台机器的流量调度到其他节点
- 磁盘剩余空间低于某个百分比时,自动触发打包清理脚本
- CPU温度持续过高时,把某个高负载进程降级
这些联动动作不要放在Agent里,Agent的职责就是上报,业务逻辑统一放在有API调用能力的调度端。我这边就用了一个cron脚本定时拉取API,发现异常再执行外部命令,逻辑简单、出错容易定位,也不容易影响监控链路本身。
6.3 保留数据和跨系统迁移
如果你后面想接入更完整的监控体系,OpenRig支持把聚合数据以CSV格式导出,也允许把原始指标以remote-write方式推到Prometheus。做了这一步之后,既保留了轻量仪表盘的日常体验,又能让更重的分析任务走专业平台,两边数据可以相互验证。我个人建议等数据量确实大到SQLite吃不住的时候再做迁移,否则这套轻量方案已经足够让你的机器管理效率提升一大截。
最后再分享一个经验:别想着一步到位把监控系统设计得无比庞大,先让最简单的指示灯亮起来,再慢慢加指标、加规则,最后你会发现,真正让你安心的是那个每晚都能正确报平安的界面。