Prometheus服务器监控部署指南:安装配置、指标采集与告警设置

公司服务器从 5 台涨到 50 台之后,靠人肉登录看 top 就彻底不现实了。你需要一个系统能自动把所有机器的指标收集起来、存下历史、能查能画图、还能在出问题时主动通知你。Prometheus 就是当前最主流的开源方案之一,它本身是一个时序数据库(TSDB),加上一套采集、查询、告警的完整生态。很多人的第一印象是"Prometheus 配置很复杂",其实它的核心配置文件只有一个 prometheus.yml,搞懂 scrape_configs、job_name、scrape_interval 三个概念,再加上几条 PromQL,就能支撑起几十台服务器的日常监控。本文按"安装 → 配置 → 采集 → 查询 → 告警"的顺序,把 Prometheus 服务器监控部署的完整流程讲透。

一、先理解 Prometheus 的三个基本设定

上手之前有三个设定必须先接受,否则后面的配置会觉得很别扭。

第一,它是"拉"模型。Prometheus 主动定时去被监控对象上拉取指标,而不是等对方上报。这意味着被监控端只需要暴露一个 HTTP 接口(通常是 /metrics),不需要知道 Prometheus 在哪——对被监控机器零侵入。代价是 Prometheus 必须能网络连通到目标端口,跨机房、跨 NAT 场景需要额外处理(可用 Pushgateway 或联邦)。

第二,指标是文本格式。访问 http://目标:9100/metrics 会返回纯文本,每行形如 node_memory_MemAvailable_bytes 3.76915968e+09,前面可以带标签,如 node_cpu_seconds_total{cpu="0",mode="idle"} 123456.78。理解这个格式,你就明白为什么 PromQL 里到处是花括号。

第三,指标有四种类型:Counter(只增不减的累计值,如网卡收发字节总数)、Gauge(可增可减的瞬时值,如当前可用内存)、Histogram(分桶统计,如请求耗时分布)、Summary(分位数统计)。区分 Counter 和 Gauge 是最关键的一步:Counter 类型的指标直接查出来没有意义,必须套上速率函数。

二、安装部署:二进制 + systemd 是最省心的选择

生产环境推荐二进制部署而非容器,理由是数据目录、配置文件的路径清晰,排障方便,也不受容器运行时影响。下面以 Linux x86_64 为例。

# 1. 创建专用用户与目录
useradd --no-create-home --shell /bin/false prometheus
mkdir -p /etc/prometheus /var/lib/prometheus
chown -R prometheus:prometheus /etc/prometheus /var/lib/prometheus

# 2. 下载解压(版本号请到 prometheus.io 下载页确认最新版)
wget https://github.com/prometheus/prometheus/releases/download/v2.51.0/prometheus-2.51.0.linux-amd64.tar.gz
tar -xzf prometheus-2.51.0.linux-amd64.tar.gz
cd prometheus-2.51.0.linux-amd64
cp prometheus promtool /usr/local/bin/
cp -r consoles console_libraries /etc/prometheus/

# 3. 写入主配置文件(内容见下一节)
vi /etc/prometheus/prometheus.yml

# 4. 校验配置文件语法,这步不要省
promtool check config /etc/prometheus/prometheus.yml

promtool check config 是一个救命命令,它能在不启动服务的情况下检查 YAML 缩进、规则语法是否合法。改完配置先跑一遍,能避免 80% 的启动失败。

# /etc/systemd/system/prometheus.service
[Unit]
Description=Prometheus Time Series Collection and Processing Server
Wants=network-online.target
After=network-online.target

[Service]
User=prometheus
Group=prometheus
Type=simple
ExecStart=/usr/local/bin/prometheus \
  --config.file=/etc/prometheus/prometheus.yml \
  --storage.tsdb.path=/var/lib/prometheus \
  --storage.tsdb.retention.time=15d \
  --web.console.templates=/etc/prometheus/consoles \
  --web.console.libraries=/etc/prometheus/console_libraries \
  --web.listen-address=0.0.0.0:9090 \
  --web.enable-lifecycle
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

几个参数值得说明:--storage.tsdb.retention.time=15d 表示数据只保留 15 天,按经验每台被监控机每 15s 采集一次大约占用 200-300 MB,你可以按磁盘容量反推保留时长;--web.enable-lifecycle 开启后可以用 curl -X POST localhost:9090/-/reload 热加载配置,不必每次重启。启动后用 systemctl status prometheus 和 journalctl -u prometheus -f 确认,浏览器访问 http://服务器IP:9090 打开自带 Web UI,在 Status → Targets 页面能看到采集目标列表及其健康状态。

三、prometheus.yml 配置详解

整份配置分四段:global(全局默认值)、alerting(告警发往哪里)、rule_files(告警规则文件)、scrape_configs(采集任务,核心中的核心)。

global:
  scrape_interval: 15s          # 默认采集间隔,可被 job 覆盖
  scrape_timeout: 10s           # 单次采集超时,必须小于 scrape_interval
  evaluation_interval: 15s      # 告警规则评估间隔
  external_labels:
    region: cn-shanghai         # 联邦/远端写入时用于区分来源

alerting:
  alertmanagers:
    - static_configs:
        - targets: ['127.0.0.1:9093']

rule_files:
  - "/etc/prometheus/rules/*.yml"

scrape_configs:
  # 采集 Prometheus 自身
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  # 采集所有 Linux 服务器
  - job_name: 'node'
    scrape_interval: 15s        # 覆盖 global 的 15s
    metrics_path: /metrics      # 默认值,一般不用写
    static_configs:
      - targets:
          - '10.0.0.11:9100'
          - '10.0.0.12:9100'
        labels:
          env: prod
          role: web
      - targets:
          - '10.0.0.21:9100'
        labels:
          env: prod
          role: db

关于 job_name:它不仅是任务的名字,还会自动写入每条指标的 job 标签。所以查询时可以用 node_load1{job="node"} 来筛选,也可以按 role、env 这些自定义标签做分组聚合,例如 avg by (role) (node_load1)。标签设计得好,后面做分组告警和面板下拉筛选会非常轻松。

关于 scrape_interval:全局设一个默认值,个别任务可以覆盖。经验值:生产环境 15s 或 30s 足够;对精度要求高的核心接口可以单独开一个 5s 的 job,但要注意数据量会变为三倍,同时 scrape_timeout 必须小于 scrape_interval,否则任务会互相挤压。

机器数量多时,不要在 targets 里手写几十行 IP。改用文件服务发现:

# prometheus.yml 片段
  - job_name: 'node'
    file_sd_configs:
      - files:
          - /etc/prometheus/targets/nodes.yml
        refresh_interval: 30s

# /etc/prometheus/targets/nodes.yml 内容
- targets:
    - '10.0.0.11:9100'
    - '10.0.0.12:9100'
  labels:
    env: prod
    role: web

file_sd_configs 的好处是修改 targets 文件后 30 秒内自动生效,不用 reload Prometheus,也方便由 CMDB 或 Ansible 自动生成这个文件。

四、PromQL 实战:rate、increase、irate 到底该用哪个

这是新手最容易搞混的地方,也是本文最该记住的一节。三个函数都用于处理 Counter 类型指标,但适用场景完全不同。

函数含义适用场景不适用场景
rate(v[5m])区间内平均每秒增长率告警规则、长期趋势图,最常用需要捕捉瞬时尖峰时
irate(v[5m])取区间内最后两个点的瞬时速率观察快速变化的曲线细节告警(会因抖动误报)
increase(v[1h])区间内的总增量统计"一小时内发生了多少次"需要每秒速率的场合

简单记:画图和告警用 rate,看瞬时细节用 irate,算总量用 increase。原因是 rate 会对区间内所有采样点做平均,曲线平滑,不会因为单个采样点抖动而误报;而 irate 只看最后两个点,反应灵敏但噪声大,用在告警里会产生大量误报。

另外要注意区间选择:方括号里的区间必须至少是 scrape_interval 的 4 倍,即 15s 采集时区间至少写 [1m],否则样本点太少算不准。常用区间是 [5m]。

# CPU 使用率(%):取 idle 模式的速率,用 1 减掉,再按实例聚合
100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)

# 内存使用率(%)
(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100

# 磁盘使用率(%),排除 tmpfs 和容器 overlay
(1 - node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"}
    / node_filesystem_size_bytes{fstype!~"tmpfs|overlay"}) * 100 > 85

# 磁盘设备繁忙度(等价于 iostat 的 %util)
rate(node_disk_io_time_seconds_total[5m]) * 100

# 网卡入方向带宽(字节/秒)
rate(node_network_receive_bytes_total{device!~"lo|docker.*|veth.*"}[5m])

# 15 分钟负载除以 CPU 核数,> 1 说明排队
node_load15 / count by (instance) (node_cpu_seconds_total{mode="idle"})

五、告警:Alertmanager 的路由与通知

架构上分两步:Prometheus 根据 rule_files 里的规则判断"是否触发",然后把告警推给 Alertmanager;Alertmanager 负责去重、分组、抑制、静默,并最终发到邮件、企业微信、钉钉、Slack 等渠道。很多人把这两步混为一谈,遇到"告警没发出来"就不知道查哪边——记住:在 Prometheus 的 Alerts 页面能看到 FIRING 状态,说明规则生效了;收不到通知是 Alertmanager 的问题。

# /etc/prometheus/rules/node.yml
groups:
  - name: node-health
    rules:
      - alert: NodeDown
        expr: up{job="node"} == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "服务器 {{ $labels.instance }} 失联"
          description: "node_exporter 已连续 1 分钟无法抓取"

      - alert: DiskUsageCritical
        expr: |
          (1 - node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"}
            / node_filesystem_size_bytes{fstype!~"tmpfs|overlay"}) * 100 > 90
        for: 10m
        labels:
          severity: critical
        annotations:
          summary: "磁盘使用率超过 90%"

      - alert: CPULoadHigh
        expr: node_load5 / count by (instance) (node_cpu_seconds_total{mode="idle"}) > 1.5
        for: 5m
        labels:
          severity: warning

Alertmanager 的配置重点是 route(路由树)与 receivers(接收人)。group_wait 表示一组告警产生后先等 30s 再发,目的是把同时爆发的多个告警合并成一条通知;group_interval 是同组后续告警的间隔;repeat_interval 是未恢复告警的重复提醒间隔,建议设 4h 以上,否则会被同一条告警刷屏。

# /etc/alertmanager/alertmanager.yml
global:
  resolve_timeout: 5m
  smtp_smarthost: 'smtp.exmail.qq.com:465'
  smtp_from: 'alert@yourdomain.com'
  smtp_auth_username: 'alert@yourdomain.com'
  smtp_auth_password: '邮箱授权码或密码'
  smtp_require_tls: false

route:
  receiver: 'default'
  group_by: ['alertname', 'instance']
  group_wait: 30s        # 组内第一条告警等待 30s,攒一起发
  group_interval: 5m     # 同组后续告警间隔 5 分钟
  repeat_interval: 4h    # 未恢复的告警每 4 小时重复提醒一次
  routes:                # 子路由,按标签分流
    - receiver: 'db-team'
      matchers:
        - role = "db"
      continue: false
    - receiver: 'critical-phone'
      matchers:
        - severity = "critical"
      group_wait: 10s

receivers:
  - name: 'default'
    email_configs:
      - to: 'ops@yourdomain.com'
        send_resolved: true
  - name: 'db-team'
    email_configs:
      - to: 'dba@yourdomain.com'
  - name: 'critical-phone'
    webhook_configs:
      - url: 'http://127.0.0.1:5001/webhook'

用 amtool check-config /etc/alertmanager/alertmanager.yml 校验语法。注意新版本 Alertmanager 推荐用 matchers(形如 role = "db")替代旧的 match/match_re 写法。

六、部署实施步骤

  1. 规划:确定 Prometheus 服务器本身的磁盘容量(按 保留天数 × 机器数 × 300MB 估算)与数据保留期。
  2. 在所有被监控机器部署 node_exporter,用 curl localhost:9100/metrics 验证有指标输出,并确认防火墙对 Prometheus 服务器放通 9100。
  3. 安装 Prometheus 二进制与 systemd 服务,先只配置 job_name: prometheus 自监控,确认能启动。
  4. 编写 scrape_configs(机器多就用 file_sd_configs),用 promtool check config 校验后 reload。
  5. 在 Web UI 的 Targets 页面确认所有目标 State 为 UP;UP 之外要留意 Error 列的具体提示。
  6. 用 PromQL 试查几条核心指标(CPU、内存、磁盘),确认数值与实际相符(可对照 top、free、df)。
  7. 编写告警规则文件,逐个用 promtool test rules 或直接在 Alerts 页面观察是否按预期 FIRING。
  8. 配置 Alertmanager 并做一次真实演练:停掉某台测试机的 node_exporter,确认邮件/消息在预期时间内到达。

小结

Prometheus 部署的门槛主要在概念而非操作:scrape_configs 定义采谁、job_name 决定标签归类、scrape_interval 决定精度与数据量;Counter 指标必须配 rate() 才有意义,告警用 rate 不用 irate;告警链路分两段排查,Prometheus 看 FIRING、Alertmanager 看通知。避坑清单:一是 scrape_timeout 不要大于 scrape_interval;二是 rate 的区间不要小于采集间隔的 4 倍;三是 repeat_interval 别设太短,否则告警风暴会让所有人屏蔽通知;四是 group_wait 别设 0,失去合并效果;五是别忘了对 Prometheus 自身做监控(up、prometheus_tsdb_head_series),否则哪天它自己挂了你也不知道。


关键词:Prometheus部署、prometheus.yml配置、scrape_configs、node_exporter、PromQL rate、Alertmanager告警