服务器宕机前的"预警雷达":Prometheus、Grafana 与云原生可观测性(Observability)

看一眼 CPU 占用率已经救不了现代系统了。用大白话讲清可观测性三大支柱、Prometheus 怎么主动拉数据、Grafana 大屏怎么在内存泄漏和硬盘爆满前给你发报警。

想象一下这个场景:凌晨三点,你睡得正香,手机突然开始疯狂震动——线上服务器挂了,用户投诉已经刷爆了客服群。等你迷迷糊糊爬起来登录上去看,命令行里 top 一敲,CPU 占用率明明只有 5%,内存也还有一大半,可服务就是死了。你盯着屏幕一脸懵:明明没报警啊?

这不是段子,这是无数运维和开发者都踩过的坑。问题出在哪?出在"看一眼 CPU 占用率"这种老式监控,早就不适合今天的系统了。今天的系统是一堆容器、一堆微服务、跑在成百上千台机器上,一个请求要穿过十几个服务才落地。光盯着一个数字,就像只看了汽车的油表就判断车会不会坏——显然不够。这篇文章就聊聊,真正能提前"嗅"到危险的预警雷达长什么样。

为什么"看 CPU"已经救不了你

传统监控的思路是:装个 agent,把 CPU、内存、硬盘这几个数采集上来,画个曲线,超阈值就红一下。这在只有一台服务器、一个应用的时代勉强够用。但现代系统有三个特点,让这种思路直接破防:

  • 规模爆炸:一台虚机可能跑着几十个容器,上千台机器同时跑,你根本看不过来。
  • 动态变化:容器随时生灭,IP 地址几分钟一变,今天还活着的实例明天可能就没了。
  • 故障隐蔽:真正搞垮系统的,往往是缓慢的内存泄漏、某个下游服务变慢、请求在某个环节悄悄堆积——这些在"当前 CPU 5%"里完全看不出来。

说白了,老式监控只能告诉你"现在是不是坏了",而现代系统需要的是"为什么坏、哪里坏、什么时候会坏"。这中间的鸿沟,就是可观测性(Observability)要填的。

可观测性的三大支柱:Metrics、Logs、Traces

业界把可观测性拆成三根柱子,每一根回答一个不同的问题。记住这个口诀就行:指标告诉你"出了事",日志告诉你"出了啥事",链路告诉你"事出在哪"

第一根柱子:Metrics(指标)

指标就是随时间采样的数字:请求数、错误数、CPU 百分比、响应延迟……它回答的问题是"系统现在还好吗?"。指标最大的优点是便宜——一个数据点不过是个时间戳加一个数字,所以你能存上百万个、查起来飞快。Prometheus 就是收集指标的事实标准。

有个有名的框架叫"四大黄金信号"(Four Golden Signals),全是指标:

  • 延迟(Latency):请求要多久。
  • 流量(Traffic):每秒多少个请求。
  • 错误(Errors):失败率多少。
  • 饱和度(Saturation):资源用了几成,比如内存快满没。

但指标有个天生短板:它只告诉你"出问题了",不告诉你"哪个用户、哪个代码路径、哪条错误"。错误率涨了,你还是不知道为啥涨。这就需要第二根柱子。

第二根柱子:Logs(日志)

日志是离散的事件记录:谁登录了、收到一个请求、抛了个异常、改了个配置。它回答"发生了什么"。日志信息量最大,带着用户 ID、堆栈、报错信息,是排查根因的终极武器。

但它的代价也最大:一个忙的系统一天能吐出几 TB 日志,存、索引、检索都烧钱。所以典型流程是——先用指标发现异常,再去翻日志看细节,而不是全天候盯着日志。

第三根柱子:Traces(链路追踪)

链路追踪跟踪"一个请求"穿过整个分布式系统的完整路径。它回答"这个请求是怎么一路走到现在的?"。一条 trace 由多个 span(片段)组成,每个 span 是一次具体工作(一次 HTTP 调用、一次数据库查询),带着时间信息。

当某个请求慢得离谱,trace 能直接告诉你:卡在支付服务了,而支付服务又在调库存时超时了。没有 trace,你只能在十几个服务之间瞎猜。

三根柱子怎么串起来:一个侦探故事

举个真实感的例子。Grafana 仪表盘上,结账服务的 p99 延迟从 200ms 飙到了 2 秒(这是指标发现的)。你顺着时间线点开同时段的慢 trace,发现瓶颈在支付服务的一个 span 上(这是链路定位的)。再拿这个 span 上的 trace ID 去过滤支付服务的日志,一眼看到一行 Stripe API timeout,连接池耗尽(这是日志定罪的)。三步走完,根因到手。三根柱子单独用都不够,合起来才是可观测性。

记住这个工作流:Metrics 发现 → Traces 定位 → Logs 定罪。少一根柱子,排查就要靠猜。

Prometheus:一个主动"上门收数据"的家伙

Prometheus 是 CNCF(云原生计算基金会)毕业的开源项目,最早在 SoundCloud 内部写出来,现在是 Kubernetes 生态里收集指标的事实标准。它最反直觉的一点,是它用拉取(Pull)模式,而不是大多数老工具用的推送(Push)模式。

为什么是"拉"而不是"推"?

推送模式是:每台机器上的 agent 主动把数据发给中心,中心很被动,容易被海量数据冲垮(背压问题),而且你很难统一管理"谁该发、多久发一次"。

拉取模式反过来:Prometheus Server 主动定时去敲每台目标机器的门,问它"你现在的指标是多少?",目标机器只要暴露一个 HTTP 接口(通常是 /metrics)返回纯文本数字就行。这个反转带来三个实打实的好处:

  • 控制反转:采集节奏、目标列表全在 Prometheus 一处配置,好管也好审计。被监控的服务啥都不用管,只管暴露端点。
  • 天然集成服务发现:在 K8s 里,新 Pod 一启动,Prometheus 通过 Service Discovery 自动发现它并加入采集;Pod 没了,自动移除。IP 天天变也不怕。
  • 健康检查白送:如果 Prometheus 敲不开某个目标,它本身就是一个强烈信号——这台机器可能挂了。所以 up == 0 这个指标,直接就是"服务器活着吗"的答案。

/metrics 端点与 PromQL

被监控的服务(或专门的 exporter)在 /metrics 暴露成百上千行这样的文本:

http_requests_total{service="api",status="200"} 145892 node_cpu_seconds_total{mode="idle"} 3849201.4

你可以用浏览器或 curl 直接访问这个端点看原始数据,调试门槛极低。Prometheus 把采集到的数据存进自己优化的时序数据库(TSDB),然后用一门叫 PromQL 的查询语言来算。比如"过去 5 分钟 CPU 空闲率"这种,PromQL 一行就搞定。想接 Grafana?配置一下数据源就能画。

要在 Prometheus 里加一个采集目标,只要在 prometheus.yml 里写:

scrape_configs: - job_name: "node_exporter" static_configs: - targets: ["192.0.2.10:9100"]

默认每分钟拉一次(scrape_interval 可调)。想更频繁?改一个数就行。

全家桶:Exporter、Alertmanager、Pushgateway

Prometheus 不是孤军作战,它有一套生态:

  • Exporter:轻量小程序,把第三方系统(数据库、硬件、消息队列)的指标转成 Prometheus 能懂的格式。比如 node_exporter 暴露 CPU、内存、磁盘、网络;装好默认就在 :9100/metrics
  • Alertmanager:Prometheus 自己只负责"判断告警该不该触发",真正发通知(去重、分组、路由到钉钉/Slack/邮件)是 Alertmanager 干的。
  • Pushgateway:给那些生命周期太短、来不及被拉取的任务(比如一次性批处理)用,让它们主动把指标推到一个中转站,Prometheus 再去拉。
  • Service Discovery:对接 K8s、Consul、DNS 等,自动发现目标,不用手动改配置。

Grafana:把冷冰冰的数字变成炫酷大屏

Prometheus 负责"收数据、算数据",但看原始数字太累。Grafana 就是那个把数据画成漂亮仪表盘的工具,它支持 70 多种数据源,Prometheus 是头号搭档。

接法很简单:在 Grafana 里添加数据源选 Prometheus,填 http://localhost:9090,点 Save & Test。想看服务器健康?直接导入现成的 Node Exporter 仪表盘(Dashboard ID:1860),CPU、内存、磁盘 I/O、网络吞吐一目了然,连配都不用配。

实战:在内存泄漏 / 硬盘爆满前收到钉钉报警

光有大屏还不够,关键是"出问题前主动喊你"。Grafana 的统一告警(unified alerting)让你直接基于 PromQL 写规则。两个最经典的例子:

服务器挂了:

up{job="node_exporter"} == 0

意思是:只要这个实例连续 1 分钟拉不到(up 为 0),就报警。这比"CPU 红了"管用一百倍——它直接告诉你"机器没响应了"。

CPU 飙太高:

100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 90

这条算的是"过去 5 分钟平均 CPU 使用率超过 90% 且持续 5 分钟"就报警。

告警触发后,交给 Alertmanager 路由。现代玩法是用 Webhook 打到钉钉或 Telegram 机器人,也能接 Slack、PagerDuty、Email。Alertmanager 还会做去重和分组——比如同一个服务挂了 10 台,它合并成一条消息发你,而不是轰炸你 10 遍,避免"告警疲劳"。

举一个"事前预警"的真实场景:内存缓慢泄漏。你的 Go 服务每天涨 50MB 不释放,三天后才会 OOM 崩溃。如果只盯着"当前 CPU 5%",你永远发现不了;但如果你画了一条"剩余可用内存"的指标曲线,配一条"可用内存低于 10% 且持续 30 分钟就报警"的规则,你能在崩溃前两天就收到钉钉:"兄弟,内存快见底了,赶紧看一眼是不是泄漏。"硬盘同理——配一条"根分区使用率 > 85%"的告警,就不会再出现"磁盘写满、服务全挂、你才知道"的惨剧。

SRE 的视角:四个九与告警疲劳

到了 SRE(系统稳定性工程师)手里,这些东西要跟业务目标绑定。比如"四个九"(99.99%)可用性,算下来一个月只允许约 4.3 分钟宕机。SRE 会定义 SLI(比如成功请求比例)、SLO(比如 99.99% 可用)、错误预算(能容忍的失败额度),再用 Prometheus + Grafana 盯错误预算的燃烧速度。

这里有个血泪经验:告警要挂在"症状"上,而不是"原始指标"上。与其对"CPU 高"狂报警,不如对"用户下单失败率涨了"报警——前者天天误报,后者才是真出事。Alertmanager 的分组、抑制规则就是干这个的:把噪音压下去,让每一条告警都"值钱"。

它也不是万能的

说句公道话,Prometheus 有几个公认的短板,规划时要心里有数:

  • 长期存储不是强项:单机默认本地存两周左右,想存一年得接远程存储(Thanos、Mimir 之类)。
  • 高基数会拖垮性能:如果指标的标签组合太多(比如每个用户 ID 当一个标签),内存和查询都会爆,标签设计要克制。
  • 没有内置多租户:原生不按团队/客户隔离数据,严格多租户要额外加层。
  • 大规模要 federation:监控很多集群时得跑多个 Prometheus 再联邦聚合,运维复杂度上来了。

总结:给你的"预警雷达"清单

收拢一下,今天我们聊了四件事:

  • "看 CPU"救不了现代系统,复杂系统需要可观测性——指标、日志、链路三根柱子缺一不可。
  • Prometheus 用 拉取模式主动收指标,配合 /metrics 端点、PromQL 和 TSDB,是云原生指标收集的事实标准。
  • Grafana 把数据画成酷炫大屏,并基于 PromQL 规则在 内存泄漏、硬盘爆满、机器宕机前通过钉钉/Telegram 喊你。
  • 真正的高手不是"出了事才看",而是用 SLO + 告警把故障挡在发生之前——这,就是预警雷达的意义。

下一篇我们聊另一个"看不见的守护者":云上那堵把千万家公司隔开的"隐形网络封锁"——VPC 和 SDN。为什么你和别人共用一堆网线和服务器,数据却从不会串台?我们下回分解。

延伸阅读

更多相关攻略推荐:VPS 延迟对照表:美国/香港/日本/新加坡/欧洲 各地区正常延迟是【购买指南 01】新手如何选购第一台 VPS:配置/线路/支付/退款'"黑五/双十一"促销避坑:如何识别假打折、"灵车 VPS"与"跑路【横向评测 02】RackNerd vs ColoCrossing 连云厂商也看不到你的数据?机密计算(Confidential Com