ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

硬件资源监控实战:从指标口径到采集、告警与排障

硬件资源监控实战:从指标口径到采集、告警与排障

硬件资源监控这四个字,听着像是运维圈的老生常谈,但真正把它做扎实的团队并不多。我见过太多机房里跑着漂亮的仪表盘,CPU、内存、磁盘、网络四条曲线一应俱全,可真到业务卡顿、接口超时的时候,盯着满屏的绿色还是找不出问题在哪。问题不在于有没有装监控,而在于监控的口径、采集的粒度、指标背后的语义有没有想明白。硬件资源监控说白了就是给机器做体检:心跳、血压、血糖、体温,每一项都得有明确的参考区间,还得知道异常时该往哪个科室送。

这篇内容适合三类人看:一是刚开始接手一批服务器、需要从零搭一套监控的同学;二是已经在用现成方案,但总觉得告警不准、面板不好用的朋友;三是被"内存还剩 30% 却 OOM 了"这类问题折磨过、想搞清楚底层逻辑的开发者。我会从指标口径讲起,一路讲到采集部署、数据建模、告警设计和排障实录,中间穿插可以直接抄的配置和踩过的坑,尽量让不同基础的读者都能拿走点东西。

1. 监控口径:先想清楚要回答什么问题

动手装 agent 之前,有一件事比选工具重要得多——确定每个指标到底在回答什么问题。同样是"CPU 使用率",有人算的是 1 减空闲率,有人算的是 1 减空闲再减 steal,还有人在容器里拿 cgroup 的 quota 做分母。口径不统一,跨机器对比就是自欺欺人,告警阈值也没法收敛。我一般会先画一张表,把"业务方会问的问题"和"对应的指标口径"一一对应起来,然后再去谈工具选型。

1.1 一次误判引出的教训:free 内存不等于可用内存

早些年我在一个项目里被内存告警坑过一回。当时规则写得很朴素:free命令输出的 free 列低于总内存的 10% 就报警。结果那台机器上跑着一个读多写少的缓存服务,内核把大量空闲页拿去做了 page cache,free列常年个位数,告警一天响几十次,值班的同学后来干脆把这个规则静音了。真正出事那天,反而是物理内存真的被吃光,没人看。

后来我们把口径换成了MemAvailable。这个值内核会综合考虑可回收的 page cache、slab 可回收部分,给出一个"在不触发交换的前提下,还能给新进程用多少内存"的估计。用MemAvailable / MemTotal做分母,阈值设在 15%,误报立刻掉了下来。这个教训很典型:监控指标要贴近内核的真实语义,而不是命令输出的字面含义。

我把常用内存指标的语义整理成了下面这张表,方便对照着选:

指标含义适用场景坑点
MemTotal物理内存总量容量规划内核保留部分已扣除
MemFree完全未使用的页参考值长期偏低属正常现象
MemAvailable可分配给新进程的估计值内存告警主力指标内核 3.14 之前无此字段
Buffers/Cached块设备缓存与页缓存分析缓存占比不能直接算作"被占用"
SwapUsed交换分区使用量性能劣化预警云主机常无 swap
Slab内核对象缓存排查内核态内存泄漏需区分可回收与不可回收

还有一点容易忽略:MemAvailable是一个估算值,在内核版本较老的机器上可能缺失或者不准。遇到这种情况,一个折中做法是用MemFree + Buffers + Cached再乘一个保守系数,虽然粗糙,但比直接看MemFree靠谱得多。这类细节不写进文档,换个新人接手就会重新踩一遍。

1.2 四层指标模型:够用、在用、将尽、变坏

指标一大堆,怎么组织才不乱?我的习惯是按"时间紧迫度"分四层,从下往上分别是:够用(容量)、在用(利用率)、将尽(饱和度)、变坏(错误与延迟)。这个分法借鉴了业界常用的 USE 方法论思路,但对硬件资源做了一点本地化调整。

容量层回答"还有多少余量",比如磁盘剩余空间、内存总量、网卡带宽上限。这一层变化慢,采集间隔可以放宽到 60 秒甚至更久,适合做趋势和扩容决策。

利用率层回答"当前用了多少",CPU 使用率、内存占用比例、磁盘 IO 带宽占用都属于这一层。它是大家最熟悉的一层,也是最容易产生误判的一层——利用率高不等于有问题,短时冲高更是常态。

饱和度层回答"有没有排队",这是我认为最有价值、却最常被忽略的一层。CPU 的 run queue 长度、磁盘的 IO 等待队列、内存的换页频率、网卡的丢包计数,都属于饱和度指标。一台机器 CPU 利用率 95% 但 run queue 一直是 1,说明它忙而有序;另一台 CPU 利用率只有 60%,run queue 却排到 8,那才是真出问题了。

错误层回答"有没有坏",包括网卡错误包、磁盘重映射扇区、内存 ECC 纠错计数、风扇转速异常等硬件级信号。这一层的数据往往来自传感器和 SMART,采集频率低但极有价值,很多硬件故障提前几周就有征兆。

四层模型的好处是,排查问题时有了固定的下钻顺序:先看错误层有没有硬故障,再看饱和度层有没有排队,然后看利用率层的具体分布,最后回到容量层判断是不是该扩容。顺序反了,就容易在利用率曲线上反复纠结,浪费时间。

1.3 采集间隔怎么定:精度、开销和存储的三方平衡

采集间隔这个参数,新手常拍脑袋定 10 秒,觉得越密越准。实际上它直接决定了三件事:单点抖动能不能被看清、采集链路的开销有多大、存储要准备多少容量。

先说精度。要算一个 5 分钟窗口的平均 CPU 使用率,按 15 秒采集能拿到 20 个点,按 60 秒采集只有 5 个点。5 个点算出来的平均值,遇到瞬时尖峰时误差可能到十几个百分点。我的经验是:业务关键指标 15 秒,硬件容量类指标 60 秒,传感器类 300 秒,三档足够覆盖绝大多数场景。

再说开销。每个采集点都是一次系统调用加一次序列化,虽然单次成本很低,但乘上机器数和指标数就不一样了。粗算一下:一台机器上 800 个活跃指标,15 秒采集一次,一天就是 800 × 5760 = 460 万个样本。采集端 CPU 占用大概在单核的 1%~3%,看起来不多,但如果这台机器本身已经跑在 90% 利用率上,这 3% 就是压垮骆驼的稻草。所以高负载机器上我会适当放宽采集间隔,或者把部分低频指标拆到独立周期。

最后是存储。这个后面第 3 章会详细算,这里先给个结论:15 秒采集、30 天保留、200 台机器的规模,压缩后的时序数据大概在 60~80 GB 这个量级,准备一块 200 GB 的盘加定期备份,基本够用。

注意:改采集间隔属于会改变历史数据可比性的操作,最好在监控系统上线初期就定好,中途调整会导致同一指标前后两段的曲线形态不一致,做趋势对比时容易误判。

2. 采集层部署:从裸机到容器的落地路径

口径定完,接下来是采集层。这一层的核心任务是把机器上的原始计数器变成带标签的时序点,稳定地送出去。说起来简单,但部署形态一多,问题就冒出来了:物理机、虚拟机、容器、Serverless,每种形态暴露指标的方式都不一样,采集器的位置和权限也不同。

2.1 三类采集方案的对比与取舍

市面上常见的采集方式基本可以归成三类:主机代理(agent 常驻进程)、无代理远程采集(SSH 或带外管理接口)、以及借道已有的系统接口(比如内核暴露的 procfs、sysfs,或者带外管理卡的 IPMI 接口)。三者不是互斥关系,实际项目里往往是组合使用的。

方案优点缺点适合场景
主机代理常驻指标全、实时性好、可自定义需要逐台部署、占用少量资源自有服务器、虚拟机集群
远程无代理不需装软件、审计友好指标少、频率受限、连接开销大第三方托管设备、合规敏感环境
系统接口直读零依赖、数据最原始需要自己写解析逻辑定制化嵌入式、特殊硬件
带外管理接口硬故障可见、操作系统挂了也能采频率低、接口兼容性参差电源、温度、风扇、RAID 状态

我个人的默认组合是:主机代理负责操作系统层指标,带外管理接口负责硬件健康层指标。两者覆盖的故障域不重叠,操作系统层看不到电源模块故障,带外接口也看不到进程级的 CPU 分布,互补性很强。

至于具体用哪个开源组件,选择其实不少。主机指标采集这一块,node_exporter 的覆盖面最广,配合 Prometheus 生态用起来最顺手;如果团队更习惯传统监控体系,Zabbix 的 agent 也很成熟,模板丰富;追求轻量和自定义的话,telegraf 的插件机制很灵活,输入输出两端都能换。我的建议是别在这上面纠结太久,先把一套跑通,指标口径对了,换工具的成本其实不高。

2.2 单机 agent 的部署与关键配置

部署这一步,我用得最多的是"二进制加 systemd"的方式,比容器化部署少一层网络和权限的折腾,排障时也直观。下面是一份可以直接改改就用的 systemd 单元配置,重点在资源限制和重启策略上:

[Unit] Description=Host Metrics Agent After=network-online.target Wants=network-online.target [Service] Type=simple User=metrics ExecStart=/usr/local/bin/host-metrics-agent \ --collectors=cpu,mem,disk,net,filesystem,load,systemd \ --interval=15s \ --listen=:9100 Restart=always RestartSec=5 # 给自己留一条活路,别把被监控的机器拖垮 CPUQuota=15% MemoryMax=256M Nice=10 IOSchedulingClass=idle [Install] WantedBy=multi-user.target

配置里有几个点值得展开说。CPUQuota=15%和MemoryMax=256M是自我保护,agent 本身出 bug 内存泄漏时,systemd 会把它干掉重启,而不是让它把整台机器拖死。Nice=10让采集进程在 CPU 竞争时主动让路,IOSchedulingClass=idle让它的磁盘读取走空闲优先级,避免采集动作本身干扰业务 IO。这几行加起来不到十个字符的成本,但在高负载场景下能救你一命。

采集器的启动参数里,--collectors这个白名单也很关键。默认全开的采集器会去读一堆你根本不关心的指标,比如各种冷门文件系统、无线网卡、蓝牙设备,白白消耗资源。我一般只开真正需要的几类,然后按季度回顾一次,把没人看的采集器关掉。

部署完之后一定要验证,不能只看进程活着。验证分三步:一是本地curl一下暴露端口,看输出里有没有关键指标名;二是从采集端查一下目标是否up;三是拿几个已知值做交叉验证,比如top里看到的 CPU 空闲率和监控面板上的数字大致对得上。第三步最容易被跳过,但它能抓出"采集器读错了 cgroup 路径"这类隐蔽问题。

2.3 容器与 cgroup 场景的额外坑

容器化部署现在太普遍了,但容器里的硬件资源监控,坑比裸机多得多。第一个坑是指标来源混淆:容器里读/proc/meminfo拿到的是宿主机数据,不是容器的 limit;读cgroup下的文件才是容器视角。很多采集器默认行为是读 procfs,在容器里跑出来的数字全是宿主机的,看着正常实则完全错误。

第二个坑是 cgroup 版本差异。cgroup v1 和 v2 的文件路径、字段名、统计口径都不一样,同一个采集器在不同内核版本的节点上可能给出不同结果。混合集群里我一般会在部署时显式指定 cgroup 版本,或者干脆选一个两种都支持得比较好的采集器版本。

第三个坑是 CPU 的 throttling。容器设置了 CPU limit 之后,一旦超限,内核会把进程节流,cpu.stat里的nr_throttled和throttled_time会持续增长。这两个指标业务方几乎从不关注,但它们是"容器明明 CPU 利用率不高、接口却变慢"的头号嫌疑人。我把这两项做成了固定面板,配合告警规则:nr_throttled在 5 分钟内增长超过阈值就提醒,比事后猜原因高效得多。

# cgroup v2 环境下快速确认是否发生节流 cat /sys/fs/cgroup/<容器路径>/cpu.stat # 输出示例: # nr_periods 12450 # nr_throttled 1873 # throttled_usec 98200000

上面这段输出说明在 12450 个调度周期里有 1873 个周期发生了节流,比例接近 15%,这个容器明显被 CPU limit 卡住了。业务侧感受到的就是"偶发卡顿",而宿主机的整体 CPU 曲线可能只有 40%,两边对不上,不查 cgroup 根本定位不到。

还有一个容易被忘掉的地方:容器里的磁盘指标。容器共享宿主机的块设备,但文件系统使用率可能因为挂载了独立的卷而与宿主机不同。我见过监控面板上显示磁盘还有 60% 空间,容器却因为写入层耗尽报了错的情况,原因就是只看了宿主机的根分区,没看容器的可写层。

3. 数据建模:命名、标签与容量估算

采集链路通了,数据开始往时序库里灌,这时候最先暴露的问题往往不是查不到,而是查得太慢、存得太贵。根源基本都在指标建模上。标签设计不合理造成的基数爆炸,是时序监控里最典型也最致命的性能陷阱。

3.1 指标命名与标签设计,避开高基数陷阱

时序数据库的索引结构决定了它对标签的组合非常敏感。每多一个标签值,就可能多出一条独立的序列。有些标签天然只有几个值,比如instance、device、mountpoint,影响可控;有些标签则近乎无限,比如请求 ID、用户 ID、文件路径、容器 ID,一旦误加进标签,序列数会瞬间爆炸。

我踩过最惨的一次,是在磁盘监控里把"挂载点"直接当成了标签。单机看着没事,可集群里有几千个临时挂载点,每次任务运行都会创建和销毁,序列数在一天之内涨到了六位数,查询延迟从毫秒级掉到十几秒,最后靠手工清理加改标签才缓过来。

命名上我坚持两条约定。第一条是单位写进指标名,_bytes、_seconds、_ratio、_total后缀不能省。这一条看着繁琐,实际救过很多次命——曾经有个面板把字节数当成百分比展示,横向对比时差点得出"磁盘使用率 800%"的荒谬结论。第二条是计数器与瞬时值区分清楚,只增不减的用_total后缀,采集端算增量,存储端存原始值;瞬时值直接存当前读数,不做增量处理。混用这两类指标,后面算rate或者delta时会得到完全不讲道理的结果。

下面是一份我常用的标签命名规范,可以直接拿去当团队约定:

标签名取值示例基数估计是否适合做标签
instance10.2.3.4:9100与机器数同阶适合
devicesda、nvme0n1个位数到几十适合
mountpoint/、/data、/var/lib通常十几个适合,但需限定范围
jobhost-metrics个位数适合
container_id64 位哈希极高且随时变动不适合,移到日志
request_idUUID无限严禁
file_path任意路径极高严禁

另外有个实践细节:临时挂载点、动态创建的卷,最好在采集端就过滤掉,别让它们进库。过滤在哪里做有讲究——采集端过滤成本最低,但会丢失信息;存储端过滤灵活,但已经把数据写进去了。我一般选采集端过滤,规则写成配置,需要时改一行就能放开。

3.2 保留策略与容量估算实录

容量估算是很多人拍脑袋的环节,报上去的存储采购量要么严重超标,要么上线一个月就写满。其实公式很简单,难的是把参数估准。我按一个具体场景算一遍:200 台机器,每台 800 个活跃序列,15 秒采集一次,保留 30 天。

每天的样本数 = 200 × 800 × (86400 / 15) = 200 × 800 × 5760 ≈9.2 亿个样本。

存储空间看压缩效率。现代时序库普遍用类似 Gorilla 的压缩算法,时间戳做差分编码,浮点值做异或编码,实际下来每个样本大约 1~2 字节。取 1.5 字节的中间值:9.2 亿 × 1.5 ≈1.4 GB/天。

30 天保留就是 42 GB 左右。再算上索引、倒排表、以及 20% 的碎片冗余,实际准备60~80 GB比较稳妥。如果还要保留 90 天的降采样数据(按 5 分钟粒度),大概再加 5 GB 左右。

规模序列数采集间隔天增量30 天保留建议预留
小型20 台 × 50030 秒约 0.5 GB15 GB30 GB
中型200 台 × 80015 秒约 1.4 GB42 GB80 GB
大型1000 台 × 100015 秒约 8.6 GB260 GB450 GB

估算出来只是第一步,上线后一定要做一次实测校准。方法很简单:统计库里 24 小时的实际增量,和估算值对一下就知道了。差距超过 50% 的话,要么是序列数估少了,要么是有指标基数异常增长,两种情况都值得查一查。

3.3 面板编排:从"能看"到"能定位"

面板做得好不好,有个很朴素的判断标准:看到告警之后,能不能在三次点击内定位到根因。很多面板做成了指标陈列馆,一层层往下滚,每一屏都塞满曲线,看完还是不知道该干什么。

我的编排逻辑是三层结构。第一层是全局概览,只放聚合指标和异常机器列表,目的是"知道哪里出问题了",不做深入分析。第二层是单机详情,把 CPU、内存、磁盘、网络四组曲线放在一屏,配上饱和度指标,目的是"确认问题严重程度和影响面"。第三层是专项分析,比如磁盘 IO 的具体设备、网络的具体接口、容器的 cgroup 数据,按需展开。

配色和坐标轴也有讲究。同一含义的曲线在不同面板里要用同一颜色,CPU 就固定一种色,内存固定另一种,别每个面板换一套,看久了脑子会乱。多条曲线放一起对比时,务必统一 Y 轴量纲,把百分比和绝对值画在同一张图上,是最常见的误导来源。

还有一个细节:在面板上标注关键事件。扩容、发版、配置变更,这些事件和曲线放在同一个时间轴上,很多"说不清原因的性能波动"一眼就能对上号。这个做法成本极低,但对排障效率的提升非常明显。

4. 告警设计:阈值、斜率与风暴抑制

告警是整个监控体系里最容易失控的部分。规则写少了,出事没人知道;规则写多了,天天响,最后所有人都学会了忽略。中间这条缝很窄,得靠对业务的理解去填。

4.1 静态阈值之外,斜率与基线告警

静态阈值最简单,也最容易误报。比如"磁盘使用率超过 85% 告警",对一台日志量稳定的机器合理,对一台每天凌晨跑批处理、临时写满到 90% 的机器就是纯噪音。

我一般会根据业务特征选三种模式之一。第一种是持续时长阈值,比如 CPU 使用率超过 85% 且持续 10 分钟,把瞬时抖动过滤掉,这一招能砍掉大半误报。第二种是斜率告警,关注变化速度而不是绝对值,硬盘每天涨 2% 和每小时涨 2%,紧迫程度完全不同,用deriv或者线性预测把"还能撑多久"算出来,比看当前值有用得多。第三种是基线告警,用同时间段的历史数据做对比,适合有明显周期性的业务,比如白天高夜间低的系统。

下面这张表是我常用的阈值起点,注意这只是起点,上线后必须按实际分布调整:

资源指标阈值建议持续时间备注
CPU使用率85%10 分钟高并发场景可放宽
CPUrun queue 长度每核 25 分钟比使用率更能反映排队
内存Available 占比低于 15%10 分钟比 free 准确
内存换页速率持续大于 05 分钟出现即说明压力大
磁盘使用率85%30 分钟结合增长率一起看
磁盘剩余可用时间少于 7 天1 小时按斜率预测
磁盘IO await超过 50ms10 分钟需按设备类型调整
网络丢包率0.1%5 分钟硬件问题的重要信号
硬件温度厂商阈值 -5℃5 分钟不同机型差别大

表格里最后一行要特别说明。温度阈值绝对不能照抄,同一型号的 CPU 在机架不同位置、不同风道环境下差异能有十几度。正确做法是查设备厂商给出的规格书,再留 5 度余量,然后观察一周实际曲线做微调。我见过直接套用 80 度的规则,结果夏天整机房一起报警的场面。

4.2 告警规则的写法与验证

规则写完之后,一定要做验证,这是最容易被跳过的一步。验证不是看规则语法对不对,而是看它在真实场景下会不会按预期触发、会不会误触发。

我常用的验证方法有两种。一种是历史回放:把规则套在最近一个月的历史数据上跑一遍,看看会触发多少次。如果一个月触发上百次,基本可以判定这条规则没法用。另一种是人为构造,比如临时把磁盘写满、把 CPU 打高,观察告警是否在预期时间内触发、通知是否正确送达、恢复后是否正确解除。这两步做完,规则的可靠性会有质的提升。

规则里还有个细节是分组和聚合。同一个原因引发的多条告警要能合并,比如一台机器下线,可能同时触发采集中断、指标缺失、心跳超时三条告警,如果分别发给不同的人,就是三份重复劳动。我在规则层做统一分组,把同一实例、同一告警类型的通知收敛成一条。

# 告警规则片段:内存可用率过低 - alert: HostMemoryAvailableLow expr: | (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) < 0.15 for: 10m labels: severity: warning team: infra annotations: summary: "实例 {{ $labels.instance }} 可用内存低于 15%" detail: "当前可用率 {{ $value | humanizePercentage }},请检查是否存在内存泄漏或缓存配置过大"

这段规则里,for: 10m就是前面说的持续时长过滤,少了这一行,瞬时波动会天天报警。severity和team两个标签是为了后续的分级路由,不同级别走不同的通知渠道和响应时限。annotations里的模板别写得太笼统,"内存低了"这种描述对值班同学毫无帮助,要写清楚"当前值是多少、下一步该查什么"。

4.3 告警风暴的抑制、分组与值班体验

告警风暴这件事,经历过一次就忘不掉。某次网络设备抖动,几百台机器的采集同时中断,五分钟内手机上收到上千条通知,等风平浪静再去翻,真正的根因早被淹没了。

治理思路分三层。第一层是抑制,上游故障时屏蔽下游衍生告警,比如机架交换机不可达时,该机架下所有机器的心跳告警全部静默,只保留一条汇总通知。第二层是聚合,把同一类型、同一时间窗内的告警合并成一条,通知里列出受影响实例数量和代表性样本。第三层是分级,把告警分成"需要立刻处理"、"工作时间处理"、"仅记录"三档,只有第一档走电话和即时消息,其余走邮件或者工单。

值班体验这块,我特别想提一点:每条告警都应该附带处置建议。不是那种"请检查系统状态"的废话,而是具体到"先执行什么命令、看哪个指标、常见原因有哪几种"。这条建议可以写在规则注释里,也可以链接到内部文档。它的价值在于,凌晨三点被叫醒的人,脑子是懵的,有明确指引和没有指引,处理时间能差出好几倍。

还有个小技巧:给告警加上静默到期时间。临时维护、压测、迁移期间手动静默,一定要填到期时间,别设成永久。我见过太多"临时静默"半年后被忘掉,结果真出事时那条规则形同虚设。

5. 常见问题排查实录

监控系统本身的故障,往往比被监控对象的故障更难发现,因为它一旦失准,你连判断依据都没有了。这一章挑几个我实际处理过的典型问题,把排查路径和判断依据写清楚。

5.1 典型故障速查表

现象可能原因快速验证方法处理方向
面板全绿但业务报卡顿指标覆盖不全或口径错误手动登录机器看实际负载补采集项、修正口径
单机指标断档采集器崩溃或网络不通本地访问暴露端口是否正常查进程日志、网络策略
指标值明显偏小容器内读到了宿主机数据对比 cgroup 与 procfs 数值切换采集数据源
查询越来越慢标签基数爆炸统计各标签的取值数量删高基数标签、加过滤
磁盘告警后自动恢复inode 耗尽后又被清理查看 inode 使用率而非容量清理小文件、调整策略
时间轴出现空洞采集端与存储端时间不同步对比两端系统时间偏差统一时间源
告警反复触发解除阈值卡在临界值附近看历史曲线的分布区间加滞回区间或改斜率告警

表格里"磁盘告警后自动恢复"这一条值得多说两句。磁盘空间耗尽有两种形式:容量耗尽和 inode 耗尽。后者在监控面板上常常显示"空间还剩一大半",但实际上已经无法创建新文件。排查时用df -i看 inode 使用率,如果某个分区的小文件特别多,比如缓存目录、会话目录、临时文件目录,很容易先把 inode 用光。这类问题只能靠补充 inode 指标来提前发现,光看容量永远看不到。

5.2 采集链路自身的开销与自我保护

采集器本身也是有成本的,这个成本在低负载机器上感知不到,在高负载机器上会被放大。我遇到过一台机器,业务进程 CPU 已经占满,采集器还在以 10 秒间隔全量采集,两边互相抢资源,形成恶性循环,最后业务超时、监控数据也不准。

处理这类问题有几个手段。一是动态降频,当检测到系统负载超过阈值时,自动把采集间隔从 15 秒放宽到 60 秒,牺牲精度换稳定性。二是资源硬限制,就像第 2 章 systemd 配置里写的那样,用 cgroup 给采集器设上限,超了就限制,不能影响业务。三是减少采集项,把冷门指标关掉,尤其是那些需要遍历大量目录的采集器,比如递归统计文件数量的,成本极高收益极低。

还有一个容易被忽略的点:采集器的日志。默认配置下很多采集器会把每次采集失败都打一条日志,网络抖动时日志能在一小时内涨到几个 GB,反过来把磁盘写满。上线前一定要把日志级别调到 warn 以上,并配置日志轮转。

注意:给采集器设资源限制时,别设得太紧。CPU 配额过小会导致采集超时,表现出来是"数据时有时无",反而更难排查。建议先观察一周实际占用,再在峰值基础上留 50% 余量。

5.3 时间不同步、数据断点与补采

时间这件事,在单机上看不出问题,一旦跨机器对齐就全是问题。采集端和存储端的时钟偏差超过一个采集周期,写入的数据点就会乱序,查询时出现锯齿状的曲线,或者干脆被丢弃。我遇到过一台虚拟机的时钟漂移了四十多秒,它上报的数据在全局视图里永远"迟到",做同比对比时怎么算都对不上。

标准做法是全线统一时间源,采集端、存储端、展示端都指向同一组时间服务,并且开启周期性校时。上线后加一条监控规则:检测各节点与基准时间的偏差,超过 1 秒就告警。这条规则平时几乎不响,响了就是真问题。

数据断点的处理要区分两种情况。如果断点来自采集器重启或者网络抖动,通常几十秒内自动恢复,不需要特殊处理,查询时用rate之类的函数能自然平滑掉。如果断点是持久的,比如某台机器换了 IP 但采集配置没更新,那就得靠"目标存活检测"来发现——每个采集目标都要有一条独立的存活指标,断档超过阈值就报警。

补采这件事,我的看法是能不补就不补。时序数据补采的复杂度和风险都不低,容易造成重复写入或者时间戳冲突。更实际的做法是接受这段数据缺失,在面板上做个标注说明原因,把精力放在防止下次断档上。除非是合规审计要求完整数据,否则不建议为此投入太多工程成本。

6. 几条从实战里磨出来的心得

6.1 让每个指标都有主人

监控系统最大的浪费,不是存储空间,而是那些没人看、没人认领的指标。它们持续消耗采集资源和存储,出问题时又没人能解释含义。我现在的做法是给每类指标标注负责人,季度回顾一次,把连续三个月无人查询的指标下线。这个机制推行起来有点阻力,但坚持两三个季度之后,监控系统的信噪比会有明显改善。

配套的一个动作是给告警规则也标主人。规则的所有者要对误报负责,这比任何流程规范都管用。

6.2 小规模起步的推荐路径

如果让我从零给一个小团队搭硬件资源监控,我会这么排优先级:第一周把 CPU、内存、磁盘容量、磁盘 IO、网络这五类基础指标采起来,做一屏总览;第二周补上饱和度和错误层指标,把告警规则写到能用的程度;第三周做面板下钻和事件标注;硬件传感器和带外管理接口放到最后,等基础链路稳定了再接入。

这个顺序的道理是:先解决"知道有没有问题",再解决"知道问题在哪",最后才是"提前发现问题"。很多团队一上来就追求全量采集和智能预测,结果基础指标的口径都是错的,上层做得再花哨也没有意义。

最后分享一个小习惯:每隔一段时间,我会随机挑一台机器,不看监控面板,凭经验判断它当前的负载状况,然后再打开面板对答案。对不上的时候,往往就是监控盲区所在。这个方法有点笨,但比任何指标审计都直接。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进