Linux服务器如何设置异常告警?CPU、内存和磁盘监控方案

监控系统搭起来之后,真正决定它有没有用的是告警。很多团队的经历是:一开始很开心地配了几十条规则,结果每天几百条通知,值班的人看两天就全部静音,出问题时反而没人发现。告警的价值不在于数量,而在于"该响的时候响,不该响的时候安静"。

这篇文章不讲怎么装监控软件,而是讲怎么定阈值、怎么分级、怎么防抖、怎么发通知、怎么收敛,最后落到"如何避免告警疲劳"这个所有运维团队早晚都要面对的问题。核心观点是:阈值不该拍脑袋定死,而要结合基线;告警要分级,不同级别走不同通道;通知要防抖,瞬时尖峰不该吵醒人。这些原则在 Zabbix、Prometheus、云监控里是通用的,理解了就能迁移。

阈值不该拍脑袋:先建立基线

新手最常见的做法是把阈值写成固定值:CPU 超过百分之八十告警、内存超过百分之九十告警。听起来合理,实际会踩两类坑。

第一类坑是误报。业务本身就是 CPU 密集型,比如视频转码、编译服务,正常工作时 CPU 长期在百分之九十以上。固定百分之八十的阈值会让它天天报警,而实际上它一切正常。反过来,一台平时 CPU 只有百分之五的机器,突然涨到百分之四十也未必有问题,但固定阈值不会告警。

第二类坑是漏报。磁盘每天增长百分之一,从百分之五十到百分之九十要四十天,固定百分之九十的阈值只在最后几天才响,留给处理的时间很短。

正确做法是先观察"正常是什么样",建立基线。用一周到两周的监控数据看每个指标的日周期和夜周期规律:工作时间高、夜间低是常态;月末业务高峰会有一波抬升。基线清楚后,阈值就可以定在"明显偏离基线"的位置,而不是一个绝对数字。

具体手段上:

  • 用趋势而非瞬时值。CPU 用"持续五分钟均值超过基线的一点五倍"比"瞬时超过百分之八十"更稳。
  • 用相对变化。某台机器的网络流量突然是日常峰值的五倍,比绝对带宽数字更有告警意义。
  • 结合容量预测。磁盘用"剩余可用天数少于七天"比"使用率超过百分之九十"更早预警。用 predict_linear() 这类函数可以算趋势。

下面给出几个经验参考区间,注意这是经验值,必须结合自家基线微调:

指标 一般观察 需要关注 需要告警
CPU 使用率 长期低于基线 持续高于基线 1.5 倍 持续 5-10 分钟高于基线 2 倍
内存 available 高于总量 20% 低于总量 15% 低于总量 10% 或 swap 持续增长
磁盘使用率 低于 70% 70%-85% 高于 85% 且趋势上涨
负载 低于核心数 接近核心数 持续高于核心数 2 倍
磁盘 await SSD < 5ms 5-20ms 持续高于基线数倍

记住一点:内存要看 available 而不是 used,磁盘要看剩余天数而不只是百分比,负载要和核心数对比。这些在前面的文章里都讲过,定阈值时同样适用。

告警分级:P0 到 P3

所有告警一个优先级,等于没有优先级。分级的意义是让值班的人一眼知道"现在要不要马上爬起来处理"。一个实用的四级模型:

级别 含义 响应要求 通知方式 例子
P0 业务已中断 立即,分钟级 电话 + 短信 + 群 核心服务不可用、数据库宕机
P1 业务受损风险高 尽快,小时级 短信 + 群 磁盘将满、主从延迟大
P2 指标异常,暂未影响 当天内处理 群消息 + 邮件 CPU 持续偏高、证书临近过期
P3 提醒类 择期处理 邮件 / 看板 日志出现少量错误、磁盘用量超 70%

分级的关键是从业务影响出发,而不是从技术指标出发。同样是 CPU 高,承载核心交易的服务是 P1,开发测试机是 P3。落地时把级别和通知通道绑定:P0 才会打电话,P2 只发到群里,这样才不会半夜被非关键问题吵醒。

防抖:让告警别那么"敏感"

瞬时尖峰几乎必然存在:备份脚本跑一下、日志轮转、定时任务启动,都会让 CPU 或磁盘 IO 短暂飙升。如果每次都告警,规则就没法用。防抖手段主要有三种。

Prometheus 用 for。 规则里写:

groups:
  - name: host-alert
    rules:
      - alert: HighCpuUsage
        expr: |
          100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 85
        for: 10m                    # 持续 10 分钟才触发
        labels:
          severity: P2
        annotations:
          summary: "{{ $labels.instance }} CPU 持续偏高"
          description: "CPU 已持续 10 分钟超过 85%,当前值 {{ $value | printf \"%.1f\" }}%"

for: 10m 表示表达式连续十分钟为真才真正触发。这样瞬时尖峰不会告警,只有真正的持续异常才会响。这是最重要的一条防抖手段。

Zabbix 用表达式或多次触发。 前面讲过用 min() 加时间窗口或 #3 计数:

min(/web-01/system.cpu.util,10m)>85

或者干脆在触发器里用 avg,让瞬时值被平均掉。

恢复条件单独定义。 触发和恢复用不同的阈值,形成"迟滞":触发用百分之八十五,恢复用百分之七十五。这样避免数值在阈值附近来回抖动导致"触发—恢复—再触发"的告警风暴。

# 触发
min(/web-01/system.cpu.util,10m)>85
# 恢复
max(/web-01/system.cpu.util,10m)<75

通知渠道怎么选

渠道 到达速度 适合级别 注意事项
邮件 慢,易被淹 P2、P3 适合留痕和日报,不适合紧急
企业微信 / 钉钉 / 飞书群 快 P1、P2 群里消息多易被忽略,可 @ 到人
短信 快 P0、P1 有费用,按量计
电话语音 最快 P0 成本高,只给最关键的规则
Webhook / 工单 中 P1-P3 自动开工单,便于跟踪闭环

落地时的一个常见结构:P0 走电话加短信加群,P1 走短信加群,P2 只进群和邮件,P3 只发邮件或只上日报。企业微信、钉钉都有群机器人 Webhook,配置简单,是中小企业最实用的通道——前面 Zabbix 的 Webhook 媒体类型、Grafana 的 Contact point 都可以直接接。

通知内容要包含足够信息,否则收到消息还要登录服务器查半天:主机名或实例、指标当前值、阈值、发生时间、可能的处理动作。比如"web-01 磁盘 /data 使用率 88%,预计 5 天后写满,请清理日志",比"磁盘告警"有用得多。

告警收敛与抑制

规则一多,一个根因会引发一串告警:网络断了,导致几十台机器上的服务全部报不可用,几百条通知同时涌来。这叫告警风暴,必须做收敛和抑制。

抑制(Inhibition):当某个高优先级告警已经触发时,抑制由它引起的低优先级告警。比如"机房网络不可达"触发后,抑制该机房所有主机的服务不可用告警。Alertmanager 里用 inhibit_rules 配置:

inhibit_rules:
  - source_matchers: [severity="P0"]
    target_matchers: [severity=~"P1|P2"]
    equal: [instance]              # 同一实例上,P0 抑制 P1/P2

分组(Grouping):把同一类告警合并成一条通知。Alertmanager 的 group_by: [alertname, instance] 可以让十台机器的同类告警合并成一条,而不是刷十次屏。

去重(Dedup):同一告警在未恢复前反复触发,只发一次。

静默(Silence):计划内维护(比如今晚做升级)提前设置静默窗口,期间不告警,避免维护操作触发一堆无意义通知。这比临时关规则安全,因为它会自动过期。

这些机制组合起来,才能把每天几百条通知压到真正需要关注的几条。判断标准很简单:一周内有多少条告警是你看到后"什么都不用做"的?如果比例超过一半,说明规则该收敛了。

避免告警疲劳的几条实操建议

每条规则都要有明确的处理动作。 建规则前先问:收到这条告警,我具体要做什么?如果答不上来,这条规则大概率是噪音。

定期回顾和清理规则。 每月看一次告警统计:哪些规则从没触发过(可能阈值太松或没用),哪些天天触发但没人处理(要么阈值不对,要么该关掉)。让规则集保持"每一响都有意义"。

区分"告警"和"看板"。 不是所有异常都要推送。P3 类指标放看板里,需要时自己看,不主动打扰。只有需要人立即行动的才叫告警。

值班轮换和升级机制。 单人长期盯告警会疲劳。多人轮值,并设置升级路径:P0 五分钟没人认领就升级给二级负责人。工具上 Alertmanager 支持 repeat_interval 做重复提醒,Grafana 和云监控也有类似机制。

把处理结果沉淀下来。 每次告警处理完,把原因和解决办法记进知识库(这一点会在后面的知识库文章里展开)。这样同类告警再次出现时,处理时间会越来越短。

常见问题

磁盘告警阈值定多少合适?

不要只看百分比。建议双条件:使用率超过百分之八十五,且用 predict_linear 预测七天内有写满风险的优先告警。分区大小不同阈值也应不同,小分区(比如 /boot)更要盯紧。关键是日志、数据、系统分区分开设定,不要一个阈值套所有挂载点。

怎么确定 CPU 阈值是基线的一点五倍还是两倍?

看业务对延迟的敏感度。对延迟敏感的服务(比如 API 网关、数据库),一点五倍就该关注;批处理、离线计算类,两倍甚至更高都可以接受。用一周数据画出正常波动范围,取明显超出上沿的位置即可,没必要追求精确。

告警发出去没人处理怎么办?

先检查是不是噪音太多导致被忽略。然后引入分级和升级机制:P0 必须有认领,未认领自动升级。同时明确值班职责,把"收到告警要做什么"写进 SOP。技术手段解决不了习惯问题,但噪音少了,人自然会认真看。

云服务器上的告警和自建监控冲突吗?

不冲突,可以叠加。云厂商的监控对底层(宿主机、网络)更敏感,自建监控对应用层更灵活。建议底层用云监控兜底,应用和业务指标用自建监控,两边的告警都收敛到同一个通知通道里,避免多入口造成混乱。

总结

  • 阈值要基于基线,不能用固定数字拍脑袋,优先用趋势、相对变化和容量预测来判断。
  • 告警分 P0 到 P3 四级,从业务影响出发分级,级别决定通知通道,P0 才打电话。
  • 防抖靠 for、时间窗口聚合和迟滞恢复阈值,让瞬时尖峰不告警,持续异常才告警。
  • 通知渠道按紧急程度分层:邮件留痕、群消息日常、短信电话只给最关键的。
  • 收敛和抑制是必需品:分组、去重、抑制、静默,把告警风暴压成几条可行动的消息。
  • 避免告警疲劳的根本办法是让每条规则都有对应动作,并定期清理无用规则。