第4章:健康检查工具 - Prometheus

Prometheus 是我在生产环境里用得最多的监控系统。说实话,刚开始接触它的时候,我也被它的 Pull 模型、多维数据模型和 PromQL 搞得有点晕。但一旦上手,你会发现它的设计确实干净——不像传统监控那样什么都往里塞,而是专注做一件事:采集、存储、查询时序数据。

今天我就从三个角度带你把它吃透:架构、安装配置、指标采集。嗯,都是实战里绕不开的东西。

4.1 Prometheus 架构——Pull 模型到底好在哪

很多刚接触 Prometheus 的人会问:为什么不用 Push?我个人习惯的思路是这样:Pull 模型让监控系统主动去拉数据,而不是等着被推送。好处是什么?

  • 可控性强:监控端决定拉谁、什么时候拉、拉多久,而不是被采集端打爆。
  • 自我发现:结合服务发现,新加的服务自动进入采集列表,不用改配置。
  • 故障隔离:如果目标挂了,Pull 超时失败,不会影响监控系统本身。

下面这张图我把核心组件和流程画了一下,你看着应该就清楚多了。

Prometheus 核心架构 Prometheus Server Pull / 存储 / 查询 Targets(目标) Exporter / 应用自身 / Pushgateway 服务发现(SD) Alertmanager 本地存储(TSDB) 关键点 • Pull 模型——Server 主动抓取 • Exporter 暴露 /metrics 端点 • 告警规则推给 Alertmanager

你可能注意到了,Prometheus Server 是中心。它定期从 Targets 拉取数据,数据格式是 Key-Value 的时间序列。Exporter 负责把系统指标(CPU、内存、磁盘等)转成 Prometheus 能懂的 /metrics 接口。应用自己也可以直接暴露指标。

实战建议:我习惯把 Exporter 和主服务分开部署,这样就算 Exporter 挂了也不影响业务。另外,服务发现能大大减少维护成本——Kubernetes 环境下我基本不用改 Prometheus 配置。

4.2 安装配置——从零搭一个可用的 Prometheus

安装其实不复杂,但配置细节容易踩坑。我记得第一次搭的时候,因为防火墙没放开 9090 端口,折腾了半小时。咱们直接说主流方式:二进制安装和 Docker 部署。

4.2.1 二进制安装(Linux)

# 下载最新版本(以 2.45.0 为例)
wget https://github.com/prometheus/prometheus/releases/download/v2.45.0/prometheus-2.45.0.linux-amd64.tar.gz
tar -xzf prometheus-2.45.0.linux-amd64.tar.gz
cd prometheus-2.45.0.linux-amd64

# 创建数据目录
mkdir -p /data/prometheus

解压后直接就能用。但默认配置只是最简单的,我们需要写一个像样的 prometheus.yml。

global:
  scrape_interval:     15s      # 默认抓取间隔
  evaluation_interval: 15s      # 评估告警规则的间隔

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  - job_name: 'node_exporter'
    static_configs:
      - targets: ['192.168.1.100:9100']

启动命令:

./prometheus --config.file=prometheus.yml --storage.tsdb.path=/data/prometheus

启动后访问 http://localhost:9090,就能看到 Prometheus 的 Web UI。

注意:我曾经在生产环境遇到过数据目录磁盘写满导致 Prometheus 崩溃的故障。一定要给 --storage.tsdb.path 所在磁盘配好告警,或者用 --storage.tsdb.retention.time 控制保留时间,比如 30d。

4.2.2 Docker 部署

如果你跟我一样喜欢容器化,Docker 方式更简洁:

docker run -d \
  --name prometheus \
  -p 9090:9090 \
  -v /path/to/prometheus.yml:/etc/prometheus/prometheus.yml \
  prom/prometheus

嗯,这里要注意:挂载配置文件时,一定要用路径,而且文件权限要 644。我遇到过因为文件权限问题导致容器启动失败,日志显示 “permission denied”。

4.3 指标采集——把数据喂给 Prometheus

Prometheus 采集指标的核心思想是:每个 Target 暴露一个 HTTP 端点,返回 Prometheus 格式的文本数据。格式大概长这样:

# HELP node_cpu_seconds_total Total seconds for each CPU state
# TYPE node_cpu_seconds_total counter
node_cpu_seconds_total{cpu="0",mode="idle"} 100345.67
node_cpu_seconds_total{cpu="0",mode="system"} 2056.34
# HELP node_memory_MemAvailable_bytes Memory information
# TYPE node_memory_MemAvailable_bytes gauge
node_memory_MemAvailable_bytes 8352342016

有三种常见的指标采集方式:

方式 场景 举例
Exporter(官方/社区) 监控系统组件(Node、MySQL、Nginx 等) node_exporter、mysqld_exporter
应用自身暴露 自研服务,嵌入 Prometheus 客户端库 Java 用 micrometer,Go 用 promhttp
Pushgateway 短生命周期任务(批处理、CronJob) 批量作业结束后推送指标

我个人最常用的还是 Exporter 方式,尤其是 node_exporter——几乎覆盖了所有主机层的指标。配置好之后,Prometheus 自动采集,不需要手动操作。

核心原则:每个 Target 只暴露一个 /metrics 端点,Prometheus 只做 Pull。这样整个监控链路清晰,出了问题也容易定位——是目标服务没响应?还是 Prometheus 挂了?

采集配置里还可以加一些过滤和标签改写:

scrape_configs:
  - job_name: 'node'
    static_configs:
      - targets: ['10.0.0.1:9100', '10.0.0.2:9100']
    relabel_configs:
      - source_labels: [__address__]
        regex: '(.*):9100'
        target_label: 'instance'
        replacement: '$1'

这段配置的意思是把原始地址里的端口去掉,只保留 IP 作为 instance 标签。嗯,这样的好处是告警信息里看起来干净一些。

说到采集,还有一个容易忽略的点:拉取超时。如果目标响应慢,Prometheus 默认 10 秒超时,超时后跳过这次采集。我曾经遇到过 MySQL Exporter 在业务高峰期查询太慢,导致很多点丢失。解决方法是优化 Exporter 查询,或者在配置里增大 scrape_timeout(但不要超过 scrape_interval)。

避坑:我用过一个第三方 Exporter 暴露了上千个指标,Prometheus 采集一次要拉好几秒。后来加了个 metric_relabel_configs 过滤掉不需要的指标,采集压力立刻降下来。记住:不是所有指标都要拉,只保留你关心的。

指标采集之后,Prometheus 会把它们存储到本地 TSDB。每条时序数据由 metric name 和 labels 唯一标识。比如 node_cpu_seconds_total{cpu="0",mode="idle"},这是一个 counter 类型的指标,只增不减。查询时用 PromQL 做聚合,比如 rate(node_cpu_seconds_total[5m]) 就能算出 CPU 利用率。

好了,Prometheus 的核心套路你已经清楚了。下一步就是在你的测试环境里搭一套,试试采集几个 Exporter。嗯,动手才是最好的学习方式。