ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

从零搭一套服务器监控告警:Prometheus + Grafana + 飞书通知

从零搭一套服务器监控告警:Prometheus + Grafana + 飞书通知 从零开始把 Prometheus、Grafana、Alertmanager 和节点采集器搭起来最后把告警收到飞书群里。全程 Docker一台 4 核 8G 的机器就够。先看清数据是怎么流的node-exporter (9100) ─┐ cadvisor (8080) ──────┼─→ Prometheus (9090) ──→ Grafana (3000) 看板 你的应用 /metrics ────┘ │ └──→ Alertmanager (9093) ──→ 飞书 / 邮件几个容易搞混的点Prometheus 是拉模式pull它主动去所有目标抓指标。所以你得提前把目标写进配置或者用服务发现。每个要监控的机器上跑一个 node-exporter它把系统指标暴露在/metrics。Alertmanager 单独跑Prometheus 算出告警后推给它由它负责分组、去重、路由。目录结构先把文件位置定下来配置全部挂载进去改配置不用重建镜像monitoring/ ├── compose.yaml ├── prometheus/ │ ├── prometheus.yml │ └── rules/ │ └── node.yml ├── alertmanager/ │ └── alertmanager.yml └── grafana/ └── provisioning/ └── datasources/ └── prometheus.yml第一步写 compose.yaml版本就选当前 LTS 线。Prometheus 3.x 已经原生支持 OTLP 接入和 OpenTelemetry 的协议对接问题解决了Grafana 13 支持把告警直接推到飞书和钉钉不用自己写转发服务。services:prometheus:image:prom/prometheus:v3.13.1container_name:prometheusports:-9090:9090volumes:-./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro-./prometheus/rules:/etc/prometheus/rules:ro-prom_data:/prometheuscommand:---config.file/etc/prometheus/prometheus.yml---storage.tsdb.path/prometheus---storage.tsdb.retention.time30d---web.enable-lifecycle# 支持热重载配置restart:unless-stoppednode-exporter:image:prom/node-exporter:latestcontainer_name:node-exporterpid:host# 不加这个看不到宿主机全部进程volumes:-/proc:/host/proc:ro-/sys:/host/sys:ro-/:/rootfs:rocommand:---path.procfs/host/proc---path.sysfs/host/sys---path.rootfs/rootfs---collector.filesystem.mount-points-exclude^/(sys|proc|dev|host|etc)($$|/)restart:unless-stoppedalertmanager:image:prom/alertmanager:v0.29.0container_name:alertmanagerports:-9093:9093volumes:-./alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro-am_data:/alertmanagerrestart:unless-stoppedgrafana:image:grafana/grafana:13.0.2container_name:grafanaports:-3000:3000environment:GF_SECURITY_ADMIN_PASSWORD:change-me-nowGF_USERS_ALLOW_SIGN_UP:falsevolumes:-./grafana/provisioning:/etc/grafana/provisioning:ro-grafana_data:/var/lib/grafanadepends_on:-prometheusrestart:unless-stoppedvolumes:prom_data:am_data:grafana_data:node-exporter 那段有三个参数不加就取不到数据我列一下pid: host、--path.procfs、--path.rootfs。少了任何一个你会看到指标是空的或者只反映容器自己。第二步Prometheus 配置# prometheus/prometheus.ymlglobal:scrape_interval:15sevaluation_interval:15sexternal_labels:cluster:prod-1alerting:alertmanagers:-static_configs:-targets:[alertmanager:9093]rule_files:-/etc/prometheus/rules/*.ymlscrape_configs:-job_name:prometheusstatic_configs:-targets:[localhost:9090]-job_name:nodestatic_configs:-targets:[node-exporter:9100]# 监控更多机器就这样加# - targets: [10.0.1.11:9100, 10.0.1.12:9100]-job_name:appmetrics_path:/metricsscrape_interval:30sstatic_configs:-targets:[app:8000]scrape_interval怎么定默认 15 秒。核心业务想看得更细可以降到 5 秒但存储压力是线性涨的——采样频率翻三倍磁盘占用也差不多翻三倍。非核心的 30 秒或 60 秒就够。第三步写告警规则# prometheus/rules/node.ymlgroups:-name:hostrules:-alert:InstanceDownexpr:up 0for:2mlabels:severity:criticalannotations:summary:实例 {{ $labels.instance }} 已下线description:已持续 2 分钟无法抓取指标。-alert:HighCPUexpr:100-(avg by(instance) (rate(node_cpu_seconds_total{modeidle}[5m])) * 100)85for:10mlabels:severity:warningannotations:summary:{{ $labels.instance }} CPU 持续高于 85%-alert:LowDiskSpaceexpr:|(node_filesystem_avail_bytes{fstype!~tmpfs|overlay} / node_filesystem_size_bytes{fstype!~tmpfs|overlay}) * 100 15for:10mlabels:severity:warningannotations:summary:{{ $labels.instance }} 磁盘剩余不足 15%-alert:HighMemoryexpr:|(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 90for:10mlabels:severity:warningannotations:summary:{{ $labels.instance }} 内存使用率超过 90%两个细节值得说。内存告警一定用MemAvailable不要用MemFree。前者已经把可回收的 page cache 算进去了后者会把正常运行的系统报成 99% 占用——我见过太多人被这个指标坑。磁盘告警用剩余百分比而不是绝对值因为一台 2T 的盘剩 50G 很危险一台 100G 的盘剩 50G 还很宽裕。for: 10m是防抖用的。指标瞬间抖动不算要持续 10 分钟才发告警。没有这个半夜告警能把你手机震醒八次。第四步接到飞书Alertmanager 本身不支持飞书但飞书群机器人接受一个简单的 JSON webhook配一下就通。先在飞书群里加个自定义机器人拿到 webhook 地址然后# alertmanager/alertmanager.ymlglobal:resolve_timeout:5mroute:group_by:[alertname,instance]group_wait:10s# 等 10 秒看有没有同类告警一起发group_interval:5mrepeat_interval:4h# 同一个告警没恢复4 小时提醒一次receiver:feishureceivers:-name:feishuwebhook_configs:-url:http://feishu-bridge:8080/alertsend_resolved:true飞书的 payload 格式和 Alertmanager 默认的不一样需要一层转换。最简单的方法是加一个轻量 bridge把 Alertmanager 的 JSON 转成飞书的{msg_type:text,content:{text:...}}。写个二十行的 Flask 服务就够用模板渲染出标题和描述。如果你不想自己写也可以直接升级到 Grafana 13 —— 它在 2026 年已经内置了飞书和钉钉的告警通道把 Prometheus 作为数据源接进去告警直接在 Grafana 里配就行省掉这一层。第五步Grafana 初始化别用界面点用 provisioning 文件配置就能进 Git# grafana/provisioning/datasources/prometheus.ymlapiVersion:1datasources:-name:Prometheustype:prometheusaccess:proxyurl:http://prometheus:9090isDefault:trueeditable:false启动后浏览器打开http://localhost:3000默认账号密码都是admin密码我们已经在环境变量里改掉了。然后直接导入社区模板Node Exporter FullID1860主机监控的 CPU、内存、磁盘、网络就全有了不用自己拖面板。第六步验证一遍dockercompose up-ddockercomposeps# 看 Prometheus 有没有抓到目标curl-slocalhost:9090/api/v1/targets|head-c500# 手动触发一次告警确认通知链路通curl-HContent-Type: application/json-d[{labels:{alertname:TestAlert,severity:warning,instance:test}}]\http://localhost:9093/api/v2/alerts第二条命令发出去飞书群里应该几秒内就有消息。这一步一定要做很多人配完等到真出事才发现通知根本没通。改完 Prometheus 配置不想重启容器的话curl-XPOST http://localhost:9090/-/reload# 前提是开了 --web.enable-lifecycle第七步把告警收敛住真出事的时候最怕的不是没告警是告警刷屏。一台机器磁盘满了可能同时触发磁盘、写入延迟、服务异常、连接数超限七八条告警电话被打爆但根因只有一个。Alertmanager 有三个机制专门治这个都要配上。分组group_by把同一类告警合并成一条通知。我们已经配了group_by: [alertname, instance]再配合group_wait: 10s10 秒内的同类告警会合成一条发出去。抑制inhibit_rules高优先级告警出现时压掉它引起的次生告警。典型场景是机器下线和机器上的服务不可用——后者是前者的结果不用重复告警inhibit_rules:-source_match:alertname:InstanceDowntarget_match_re:alertname:HighCPU|HighMemory|HighDiskUsageequal:[instance]意思是同一台机器上只要InstanceDown在响就不发它的 CPU/内存/磁盘告警。静默silence计划内维护时手动关掉告警。这个在 Alertmanager 的 Web 界面9093 端口上点几下就行不需要改配置http://localhost:9093/#/silences维护窗口开始前设一个 silence结束自动失效。比临时注释掉规则文件安全得多。告警分级也很重要。我在规则里用了severity: critical和severity: warning两级路由可以按级别分critical直接进电话/短信PagerDuty、飞书加急warning进群消息工作时间看就行route:receiver:feishuroutes:-matchers:[severitycritical]receiver:pagerrepeat_interval:30m-matchers:[severitywarning]receiver:feishurepeat_interval:4h规则很简单但很有效只有真的需要人立刻起床的才进 critical。判断标准是这条告警值不值得凌晨三点把人叫起来不值得的一律 warning。几个容易翻车的点1. 容器里的 localhost。prometheus.yml里写localhost:9100是指 Prometheus 容器自己抓不到 node-exporter。服务之间用服务名互访也就是node-exporter:9100。这个错误新手基本都会犯一次。2. 磁盘被撑爆。默认保留 15 天如果采集目标多、指标基数高磁盘涨得很快。要么调--storage.tsdb.retention.time要么上 VictoriaMetrics——它的压缩比能省 70% 以上的磁盘而且兼容 PromQL。3. 指标基数爆炸。别把用户 ID、请求 ID 这种高基数的东西当标签label。一张报表带几万个不同 label 组合Prometheus 内存会直接飙起来。Prometheus 3.x 可以配sample_limit和label_limit兜底。4. 时区。容器默认 UTCGrafana 面板时间会差 8 小时。要么给 Grafana 设GF_DATE_FORMATS_DEFAULT_TIMEZONEAsia/Shanghai要么在面板里手动改。最后自建监控真正的成本不在搭建在告警质量。搭起来两小时把告警调到一个该响的响、不该响的不响的状态得花几周。所以我的建议是先只配四条告警实例下线、CPU、内存、磁盘跑两周看哪些是误报、哪些是真事再慢慢加。一上来配三十条规则结果就是所有人开始无视告警——那比不监控还危险。
返回列表