结论:服务器资源监控告警设置的核心是「选对指标、定对阈值、分对级别、收敛到位」。CPU、内存、磁盘、IO、网络、服务存活按 P0~P3 分级,持续 5~10 分钟超阈值才触发,再配合抑制与静默规则避免告警疲劳。
服务器「挂了没发现」和「告警太吵被屏蔽」,是运维最常踩的两个极端。前者往往是因为只监控了「主机是否在线」,而忽略了磁盘将满、证书将过期、数据库连接池打满这类慢变量;后者则是因为把所有指标都设成「一超阈值就打电话」,最后值班人员把告警群静音,等于没有监控。本文给出一套可直接落地的服务器监控告警设置方案:指标清单、阈值建议、分级标准、Prometheus Alertmanager 配置、收敛抑制与值班升级,全部基于 Prometheus 2.53 + Alertmanager 0.27(截至 2026 年主流版本)。
服务器资源监控告警要监控哪些指标?
先给结论:一台服务器只需要盯住 7 类指标——CPU、内存、磁盘空间、磁盘 IO、网络、服务存活、证书到期。其余指标(如 TCP 连接数、进程数、文件句柄)作为排查时的辅助数据入库即可,不直接配告警,否则告警数量会失控。
告警指标选取与建议阈值表
| 指标类别 | 推荐 PromQL 表达式(node_exporter) | 建议阈值 | 持续时长 | 建议级别 | ||
|---|---|---|---|---|---|---|
| CPU 使用率 | 100 - (avg by(instance)(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) | > 85% | 10m | P2 | ||
| CPU 负载 | node_load5 / count by(instance)(node_cpu_seconds_total{mode="idle"}) | > 核数 × 1.5 | 10m | P2 | ||
| 内存使用率 | 100 * (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) | > 90% | 10m | P2 | ||
| 磁盘使用率 | `100 * (1 - node_filesystem_avail_bytes{fstype=~"ext4 | xfs"} / node_filesystem_size_bytes{fstype=~"ext4 | xfs"})` | > 85% | 5m | P2 |
| 磁盘将满预测 | `predict_linear(node_filesystem_avail_bytes{fstype=~"ext4 | xfs"}[6h], 4*3600) < 0` | 4 小时内写满 | 5m | P1 | |
| inode 剩余 | `100 * node_filesystem_files_free{fstype=~"ext4 | xfs"} / node_filesystem_files{fstype=~"ext4 | xfs"}` | < 10% | 5m | P2 |
| 磁盘 IO 利用率 | rate(node_disk_io_time_seconds_total[5m]) * 100 | > 90% | 15m | P2 | ||
| 网卡出带宽 | `rate(node_network_transmit_bytes_total{device!~"lo | veth.* | docker."}[5m]) 8` | > 带宽上限 × 80% | 10m | P1 |
| 主机存活 | up{job="node"} | == 0 | 1m | P0 | ||
| 服务存活(HTTP) | probe_success{job="blackbox-http"} | == 0 | 2m | P0 | ||
| 服务存活(端口) | probe_success{job="blackbox-tcp"} | == 0 | 2m | P1 | ||
| SSL 证书到期 | (probe_ssl_earliest_cert_expiry - time()) / 86400 | < 15 天 | 30m | P2 |
阈值不是拍脑袋定的,要注意三点:
- 使用率不等于异常。CPU 85% 对于一个跑批任务是正常的,对于一个 Web 前端就是异常,阈值要按角色分组(Web 节点、数据库节点、计算节点分开配)。
- 磁盘告警必须双保险。既配「已用 85%」,也配「4 小时内将写满」的线性预测,后者能救你于周末凌晨。
- 服务存活优先级最高。
up == 0只持续 1 分钟就报,而资源类指标要 5~15 分钟,因为资源抖动是常态,主机失联不是。
指标采集:先装好 node_exporter
# Ubuntu 24.04 LTS 部署 node_exporter 1.8(截至 2026 年稳定版本)
sudo useradd --no-create-home --shell /bin/false node_exporter
wget https://github.com/prometheus/node_exporter/releases/download/v1.8.2/node_exporter-1.8.2.linux-amd64.tar.gz
tar xzf node_exporter-1.8.2.linux-amd64.tar.gz
sudo cp node_exporter-1.8.2.linux-amd64/node_exporter /usr/local/bin/
sudo chown node_exporter:node_exporter /usr/local/bin/node_exporter
sudo tee /etc/systemd/system/node_exporter.service >/dev/null <<'EOF'
[Unit]
Description=Prometheus Node Exporter
After=network-online.target
[Service]
User=node_exporter
ExecStart=/usr/local/bin/node_exporter \
--collector.systemd \
--collector.processes \
--no-collector.wifi
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable --now node_exporter
curl -s http://127.0.0.1:9100/metrics | grep -E '^node_load5|^node_memory_MemTotal_bytes'端口 9100 不要对公网开放,只在安全组里放通 Prometheus Server 的内网 IP。
告警分级怎么做?P0~P3 的标准是什么
结论:按「影响面 + 是否需要人立即介入」分级。只有「业务已中断」或「即将中断且无法自愈」才配 P0,其余一律降级,否则 P0 会烂大街。
| 级别 | 定义 | 典型场景 | 通知方式 | 响应时限 |
|---|---|---|---|---|
| P0 | 业务中断或数据有丢失风险 | 主机失联、HTTP 探测失败、主库不可用 | 电话 + 短信 + IM @所有人 | 5 分钟内响应 |
| P1 | 即将中断,或核心指标严重劣化 | 磁盘 4 小时内写满、带宽打满、CPU 满载 15 分钟 | 电话 + IM 群 | 15 分钟内响应 |
| P2 | 需要关注但不紧急 | 内存 90%、证书 15 天内到期、IO 高 | IM 群 + 邮件 | 当班内处理(4 小时) |
| P3 | 提示/趋势类 | 周环比成本上涨、慢查询数上升 | 邮件日报 | 次日处理 |
分级落地的关键动作:
- 用
severity标签承载等级,路由(route)按 severity 分流到不同接收器,而不是靠人肉判断。 - P0 必须「双通道」:IM 群消息 + 电话外呼。只发 IM 的 P0 在夜间等于没发。
- P3 只进日报,绝不推送到群,这是控制噪声的第一道闸门。
- 每季度复盘一次:若某条 P0 连续 3 个月「触发后无需处理」,就降级为 P1 或删除。
Prometheus Alertmanager 告警规则怎么写
结论:规则文件(rules)负责「判定异常」,Alertmanager 负责「发给谁、怎么发」。两者必须分开管理,规则里只写表达式与标签,不写通知渠道。
告警规则 YAML 示例
# /etc/prometheus/rules/host.yml
groups:
- name: host-resource
rules:
- alert: HostDown
expr: up{job="node"} == 0
for: 1m
labels:
severity: critical # P0
team: ops
annotations:
summary: "主机失联:{{ $labels.instance }}"
description: "node_exporter 连续 1 分钟抓取失败,请检查主机、网络与 9100 端口。"
runbook: "https://wiki.example.com/runbook/host-down"
- alert: DiskWillFillIn4Hours
expr: predict_linear(node_filesystem_avail_bytes{fstype=~"ext4|xfs",mountpoint!~"/boot.*"}[6h], 4*3600) < 0
for: 5m
labels:
severity: warning # P1
team: ops
annotations:
summary: "磁盘将满:{{ $labels.instance }} {{ $labels.mountpoint }}"
description: "按当前写入速度,4 小时内将写满,立即清理或扩容。"
value: "剩余 {{ $value | humanize }} bytes"
- alert: HighCPUUsage
expr: 100 - (avg by(instance)(rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 85
for: 10m
labels:
severity: info # P2
team: ops
annotations:
summary: "CPU 使用率过高:{{ $labels.instance }}"
description: "CPU 使用率持续 10 分钟超过 85%,当前 {{ $value | printf \"%.1f\" }}%。"
- alert: SSLCertExpiringSoon
expr: (probe_ssl_earliest_cert_expiry - time()) / 86400 < 15
for: 30m
labels:
severity: info
team: ops
annotations:
summary: "SSL 证书即将过期:{{ $labels.instance }}"
description: "证书剩余有效期不足 15 天,请尽快续签。"写完必须自检语法,否则 Prometheus 加载失败会导致整个规则集不生效:
# 校验规则语法(promtool 随 Prometheus 一起安装)
promtool check rules /etc/prometheus/rules/host.yml
# 让 Prometheus 热加载配置(需启动时加 --web.enable-lifecycle)
curl -X POST http://127.0.0.1:9090/-/reload
# 在 UI 上确认规则已加载
curl -s http://127.0.0.1:9090/api/v1/rules | jq '.data.groups[].rules[].name'Alertmanager 路由与接收器配置
# /etc/alertmanager/alertmanager.yml
global:
resolve_timeout: 5m
smtp_smarthost: 'smtp.exmail.qq.com:465'
smtp_from: 'alert@example.com'
smtp_auth_username: 'alert@example.com'
smtp_auth_password: '替换为应用专用密码'
templates:
- '/etc/alertmanager/templates/*.tmpl'
route:
receiver: 'default-im'
group_by: ['alertname', 'instance', 'severity']
group_wait: 30s # 首次等待,攒一批再发
group_interval: 5m # 同组新告警合并间隔
repeat_interval: 4h # 未恢复告警的重发间隔
routes:
- matchers:
- severity="critical"
receiver: 'p0-phone'
group_wait: 10s
repeat_interval: 30m
continue: false
- matchers:
- severity="warning"
receiver: 'p1-im'
repeat_interval: 1h
- matchers:
- severity="info"
receiver: 'daily-mail'
group_wait: 5m
repeat_interval: 24h
receivers:
- name: 'default-im'
webhook_configs:
- url: 'http://127.0.0.1:8060/dingtalk/ops/send'
send_resolved: true
- name: 'p0-phone'
webhook_configs:
- url: 'http://127.0.0.1:8060/dingtalk/p0/send'
send_resolved: true
email_configs:
- to: 'oncall@example.com'
send_resolved: true
- name: 'p1-im'
webhook_configs:
- url: 'http://127.0.0.1:8060/dingtalk/ops/send'
send_resolved: true
- name: 'daily-mail'
email_configs:
- to: 'ops@example.com'
send_resolved: false
inhibit_rules:
# 主机已经失联时,抑制该主机上的一切资源类告警
- source_matchers: ['alertname="HostDown"']
target_matchers: ['severity="info"']
equal: ['instance']
# P0 触发时抑制同实例的 P1,避免刷屏
- source_matchers: ['severity="critical"']
target_matchers: ['severity="warning"']
equal: ['instance']校验与测试路由:
amtool check-config /etc/alertmanager/alertmanager.yml
amtool config routes test --config.file=/etc/alertmanager/alertmanager.yml \
severity="critical" instance="web-01:9100"
# 手动造一条告警,验证通知链路是否真的能收到
amtool alert add alertname=TestAlert severity=critical instance=web-01:9100 \
--alertmanager.url=http://127.0.0.1:9093告警怎么发到钉钉、企业微信和 Webhook
结论:Alertmanager 原生只支持邮件、Slack、Webhook;钉钉和企业微信走 Webhook 转发器(prometheus-webhook-dingtalk)。不要自己写脚本轮询 API,那会丢告警。
- 邮件:适合 P2/P3 日报与审计留痕,不适合 P0。
- 钉钉 / 企业微信机器人:国内团队首选,支持
@手机号精准提醒值班人。 - Webhook 自建:用于对接工单系统或电话外呼平台(如阿里云云呼、容联七陌)。
- 短信 / 电话:P0 必备,建议接第三方,避免依赖单一 IM 厂商。
钉钉机器人的消息模板要包含「级别、实例、摘要、值班人、Runbook 链接」,让值班人点开就知道做什么:
# /etc/alertmanager/templates/dingtalk.tmpl
{{ define "dingtalk.message" }}
## [{{ .Status | toUpper }}] {{ .CommonLabels.alertname }}({{ .CommonLabels.severity }})
{{ range .Alerts }}
- **级别**:{{ .Labels.severity }}
- **实例**:{{ .Labels.instance }}
- **摘要**:{{ .Annotations.summary }}
- **详情**:{{ .Annotations.description }}
- **开始**:{{ .StartsAt.Format "2006-01-02 15:04:05" }}
{{ end }}
> 值班人请按 Runbook 处理,处理完在群内回复"已恢复"。
{{ end }}告警太多怎么办?收敛、抑制与静默
结论:抗告警疲劳靠三个机制——分组(group_by)、抑制(inhibit_rules)、静默(silence),再加一个「告警体检」制度。
- 分组收敛:同一个
alertname + instance的告警在group_wait窗口内合并成一条消息。一台机器重启时,原本可能刷出 20 条,配置合理后只发 1 条。 - 抑制规则:主机失联(
HostDown)时,自动抑制该主机的 CPU、内存、磁盘告警——机器都宕了,再报 CPU 高毫无意义。 - 计划内静默:发版、压测、机房割接前,用
amtool silence add提前静默,避免「狼来了」。 - 重复间隔拉长:未恢复的 P2 告警 4 小时重发一次即可,不需要每 5 分钟提醒一次。
- 月度体检:统计触发次数 Top 10 的告警,凡「30 天内触发 > 20 次且无人处理」的,要么调阈值,要么删除。
# 静默 web-01 上所有告警 2 小时(用于计划内维护)
amtool silence add --alertmanager.url=http://127.0.0.1:9093 \
--author="zhangsan" --comment="发版维护窗口" \
--duration=2h instance="web-01:9100"
amtool silence query --alertmanager.url=http://127.0.0.1:9093值班与升级机制怎么设计
结论:没有升级机制的告警等于把风险压在最前线的人身上。建议「三级值班 + 30 分钟未响应自动升级」。
- 一线值班(L1):7×24 轮班,收到 P0 后 5 分钟内认领,按 Runbook 执行标准动作(重启服务、切备机、回滚)。
- 二线专家(L2):L1 在 30 分钟内无法恢复,升级到对应组件负责人(数据库、网络、中间件)。
- 三线管理(L3):P0 持续超过 60 分钟,通知技术负责人与业务方,启动对外沟通。
配套要求:
- 每条 P0 告警的
annotations里必须带runbook链接,没写 Runbook 的告警不允许上线。 - 交接班时要过一遍「当前 firing 告警」清单,避免跨班遗漏。
- 每月出一份告警统计:触发数、平均响应时长(MTTA)、平均恢复时长(MTTR)、误报率。误报率超过 30% 就说明阈值该调了。
常见误区 / 排错提示
- 误区:阈值照抄别人的 80%。不同业务基线不同,正确做法是先用
avg_over_time(...[7d])看一周基线,再在基线上加 20%~30% 余量作为阈值。 - 误区:
for: 0m立即告警。没有持续时长会导致瞬时抖动狂轰滥炸,资源类指标最少for: 5m。 - 排错:告警不触发。先
promtool check rules确认语法,再在 Prometheus UI 的 Graph 页直接跑同一条 PromQL,看是否有数据返回——90% 的问题出在指标名或标签写错。 - 排错:Alertmanager 收到告警但不发消息。用
amtool config routes test验证路由匹配;企业微信/钉钉机器人要检查 IP 白名单与关键字校验(很多机器人要求消息里必须包含预设关键字)。 - 排错:邮件进垃圾箱。给告警邮箱配置 SPF、DKIM、DMARC,否则运维邮箱大概率被判为垃圾邮件。
- 误区:只监控平均值。
avg会掩盖个别实例的问题,单机告警必须用by(instance)分组。
企业QQ咨询




