Files
hoelee-blog/src/content/posts/zh/one-prometheus-for-unraid-synology-and-a-vps.md
T
hoelee e8c5124db1
Deploy / build (push) Successful in 28s
Add 4 monitoring posts (EN + ZH): smartctl exit 32, Grafana no-data variable, percentage alert thresholds, one Prometheus for 3 hosts
Backdated into the 2026-03-25 -> 2026-09-04 archive gap (pubDate 2026-04-14/05-17/06-24/07-29)
with updatedDate 2026-09-29 holding the real date, so sitemap lastmod stays honest.
Custom OG + banner per post, hire CTA, language switch verified.
2026-09-29 01:37:23 +08:00

7.6 KiB
Raw Blame History

title, description, pubDate, updatedDate, category, tags, ogImage, banner, draft
title description pubDate updatedDate category tags ogImage banner draft
用一个 Prometheus 监控 unRaid、群晖 NAS 和 VPS:我做错的四件事 三台主机、一个 Prometheus、一个 Grafana:覆盖矩阵、把同一个 NAS 卷算成三次的"总容量",以及那台完全不导出 CPU 频率的虚拟机。 2026-07-29 2026-09-29 case-studies
prometheus
grafana
unraid
synology
dsm
cadvisor
monitoring
homelab
/og/one-prometheus-for-unraid-synology-and-a-vps.png /banners/one-prometheus-for-unraid-synology-and-a-vps.png false

为什么这件事重要

当一台家用服务器在跑别人的网站、邮件和文件时,它就不是玩具了。糟糕的一周和糟糕的一个月之间,差别通常只是你多早发现:一块出现重分配扇区的盘、一个只剩 20 GB 的卷、一台被宿主机饿死的虚拟机、一个夜里重启四次的容器。

我有三台机器——unRaid(日常主力)、群晖 NAS(存储与服务)和 VPS(对外)——以及三套各自都不知道它们在干什么的方式。这篇文章讲它们如何变成一块屏,以及我路上做错的四件事——其中三个你也会踩。

架构

一个 Prometheus 加一个 Grafana,跑在永不关机的那台机器上。每台被监控主机跑两个 exporter:

机器 主机指标 容器指标 抓取路径
unRaid node_exporter (:9100) cAdvisor (:8080) 直连
群晖 DSM node_exporter (:9100) cAdvisor (:8082) 局域网
ServerHosh VPS node_exporter (:9100) cAdvisor (:8081) VPN 隧道 + nginx stream 中转

node_exporter 与 cAdvisor 不是替代关系——这是最容易搞错的一点。 node_exporter 看的是主机:CPU、内存、网络、磁盘、文件系统、温度;它对 cgroup 一无所知,说不出是哪个容器吃掉了内存。cAdvisor 只看容器。想要主机健康和按容器记账,两个都得跑;少一个,那个洞会在几个月后表现为一次无法解释的负载高峰。

错误一:cAdvisor 里那些"不是容器的容器"

我的容器规则开始对不是容器的东西告警。cAdvisor 会为 systemd slice 和整机 cgroup 导出序列——其中一条没有名字的序列报告了约 58 GB 的"内存使用",却没有对应的容器。那就是整台主机,被描述成了一个容器。

修法是加一个过滤条件,但你得先知道要写它:

# container metrics: anything with a name, and only that
container_memory_working_set_bytes{job=~"cadvisor.*", name!=""}

少了 name!="",一条"容器内存超过 10 GB"的规则会对主机自己告警。

错误二:我的"总容量"是虚构的

聚合面板好看,但就是错的。原因:同一个文件系统会在指标里出现多次。

  • 在 NAS 上,主卷是 /volume1,而 /opt 是同一个 btrfs 文件系统,只是换了个挂载点。
  • 在 unRaid 上,同一个 NAS 卷又以 CIFS 挂载成 /mnt/remotes/<nas>_ActiveBackup。
  • unRaid 的 /var/lib/docker 是那个池的子卷,而 /mnt/ssd 已经代表过同一个池——同样的字节,第二个身份。

所以朴素的 sum(node_filesystem_size_bytes) 报出了我并不存在的容量。诚实的写法是明确列出什么算数据存储:

node_filesystem_size_bytes{
  mountpoint=~"/volume[0-9]+|/mnt/ssd|/mnt/disk[0-9]+",
  fstype!~"fuse.*|tmpfs|rootfs"
} or node_filesystem_size_bytes{job="vps-host", mountpoint="/"}

还有两条应该写进面板说明的诚实备注,因为没人能解释的数字比没有数字更糟:

  • 校验盘对内核不可见。 unRaid 的奇偶校验盘没有文件系统,所以从不出现在指标里——这个和是可用容量,不是硬盘数量。
  • 镜像会虚增裸和。 两块镜像 SSD 会各报一次自己的字节,和不是你能存的量。

还有那个以后一定会咬我的遗漏:unRaid 的 shfs 联合挂载(/mnt/user)报告 avail=0。把它算进"剩余空间低于 X"的规则里,就会产生一条永远无法解除的告警。

错误三:那台不导出 CPU 频率的虚拟机

为了算全家的"总 CPU 频率",我直接用 node_exporter 的 cpufreq collector。unRaid 和 NAS 都按核心报出了 node_cpu_scaling_frequency_hertz;VPS 什么都没有——它是 KVM 客户机,而客户机没有 /sys/devices/system/cpu/cpu0/cpufreq。这个指标在那里无法存在。

修法是 textfile collector:一个小脚本读客户机能看到的东西(/proc/cpuinfo),把 Prometheus 格式指标写进 node_exporter 会抓取的目录:

# /opt/node-exporter-textfile/cpu-mhz.sh — cron 每 5 分钟
awk -F: '
  /^processor/ { c = $2; gsub(/[ \t]/, "", c) }
  /^cpu MHz/   { f = $2; gsub(/[ \t]/, "", f); printf "node_cpu_mhz_current_hz{core=\"%s\"} %.0f\n", c, f * 1000000 }
' /proc/cpuinfo

配合:

command:
  - '--collector.textfile.directory=/textfile'
volumes:
  - /opt/node-exporter-textfile:/textfile:ro

两个刻意的决定:指标名故意不同于 node_exporter 自己的(用 node_cpu_mhz_current_hz,不用 node_cpu_scaling_frequency_hertz),这样万一以后宿主机暴露真实 cpufreq,不会出现重复序列冲突;仪表盘则显式合并两个来源:

sum(node_cpu_scaling_frequency_hertz or node_cpu_mhz_current_hz)

错误四:exporter 把容器名当成了主机名

仪表盘的主机下拉框里出现了 9f9afcccc962。那是个容器 ID:node_exporter 的 uname collector 读到的是进程自己的 UTS namespace,而容器的 hostname 默认就是它自己的 ID。指标没错,标签毫无意义。compose 里一行解决:

services:
  node_exporter:
    hostname: 2.hoelee.com   # otherwise `nodename` = the container ID

我下次会怎么做

  • 刻意把总览屏留到最后做。 "总容量是多少"这个问题会逼出全部去重工作;先做完三台主机面板再发现,就得在每个地方重做这个数字。
  • 一开始就给容器钉 hostname。 一行成本,省掉一个让人困惑的下拉框。
  • 假设每个虚拟化或家电式主机都会藏掉一类指标。 NAS 可能限制你的容器监控(DSM 的 Docker API 版本把我的 cAdvisor 钉在 v0.53.0——更新的版本要更新的 Docker API);虚拟机藏掉 cpufreq;路由器藏掉自己的 CPU。找缺口的方法是数你期待的东西,而不是相信"采集器成功了"。

结果

三台主机、7 个抓取目标、一个 Grafana、16 条告警规则,以及一块屏:47 个 CPU 核心 · 当前 158 GHz(标称上限 205 GHz)· 142 GB 内存 · 64 TB 存储 · 155 个运行中容器,并且每台机器克隆同一套主机/容器面板布局,三台读起来完全一致。告警进 Telegram 和邮件,Prometheus 保留 30 天。

最有用的产出不是仪表盘,而是重写存储规则那天触发的一条告警:一个只剩 21 GB 的 NAS 卷——它一直藏在"99% 满"的百分比阈值背后,而那个巨物早已变成背景噪声。

需要为你的业务做这个吗?

如果你有 NAS、VPS 和几台服务器,却没有一个地方能同时看它们,我可以帮你搭这样的自托管监控流水线——Prometheus + Grafana 覆盖你的机器,主机与容器指标,真正有意义的磁盘健康与容量规则,通知推到 Telegram 或邮件。

WhatsApp:+60 12-797 2969 · 邮箱:[email protected] · hoelee.com

网站设计与开发是我的主业;服务器加固与自托管基础设施是它的另一半。