4. Prometheus 部署与配置:二进制与容器化部署、服务发现

说到 Prometheus 的部署,其实我见过不少团队在这个环节栽跟头。有人觉得「不就是装个监控嘛,docker run 一下完事」,结果上了生产才发现配置不对、数据丢了、服务发现没生效。嗯,今天咱们就把这事聊透。

4.1 二进制部署:最传统也最可控

我个人习惯在测试环境先用二进制部署。为什么?因为你能看到每一个文件、每一个进程,排查问题最直接。

步骤其实很简单:

# 下载 Prometheus(以 2.45.0 为例)
wget https://github.com/prometheus/prometheus/releases/download/v2.45.0/prometheus-2.45.0.linux-amd64.tar.gz

# 解压
tar xvf prometheus-2.45.0.linux-amd64.tar.gz
cd prometheus-2.45.0.linux-amd64

# 启动
./prometheus --config.file=prometheus.yml

启动后访问 http://localhost:9090,看到那个熟悉的界面就算成了。但这里有个坑——默认配置只监控自己,说白了就是 Prometheus 只抓自己的 /metrics 端点。

我曾经遇到过一个问题:二进制部署后忘了配置 systemd 服务,结果服务器重启后 Prometheus 没起来,监控数据断了整整两天。所以一定要做成系统服务。

写个 systemd 单元文件:

[Unit]
Description=Prometheus
After=network.target

[Service]
User=prometheus
Group=prometheus
ExecStart=/usr/local/prometheus/prometheus \
  --config.file=/etc/prometheus/prometheus.yml \
  --storage.tsdb.path=/var/lib/prometheus/data \
  --web.listen-address=0.0.0.0:9090

[Install]
WantedBy=multi-user.target

你想想看,这样是不是稳多了?

4.2 容器化部署:灵活但别掉坑

容器化部署现在更常见。我建议用 Docker Compose 来管理,比裸 docker run 好维护得多。

version: '3.8'
services:
  prometheus:
    image: prom/prometheus:v2.45.0
    container_name: prometheus
    restart: always
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - prometheus_data:/prometheus
    ports:
      - "9090:9090"
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--web.console.libraries=/etc/prometheus/console_libraries'
      - '--web.console.templates=/etc/prometheus/consoles'

volumes:
  prometheus_data:
小技巧:容器化部署时,数据卷一定要挂载到宿主机持久化目录。我见过有人用匿名卷,容器一删数据全没了,那叫一个酸爽。

启动命令:

docker-compose up -d

就这么简单。但注意——容器里的时区问题。Prometheus 默认用 UTC,你看到的时间戳可能跟预期差 8 小时。解决办法是在 docker-compose 里加环境变量:

environment:
  - TZ=Asia/Shanghai

4.3 配置文件详解:别被 YAML 坑了

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.10:9100', '192.168.1.11:9100']

这里有几个关键参数:

参数 说明 建议值
scrape_interval 抓取频率 生产环境 15s-30s
scrape_timeout 单次抓取超时 默认 10s,网络差可调大
evaluation_interval 告警规则评估频率 建议与 scrape_interval 一致
重点:scrape_timeout 不能大于 scrape_interval,否则会出现抓取重叠。我见过有人设了 30s 超时但间隔只有 15s,结果 Prometheus 进程越来越多,最后 OOM 了。

4.4 服务发现:告别手动维护

静态配置在小规模还行,一旦节点超过几十个,手动维护 targets 就是噩梦。你想想看,每次扩容都要改配置文件再重启 Prometheus,这谁受得了?

Prometheus 支持多种服务发现机制。我重点讲两个最常用的:

4.4.1 基于文件的服务发现

这是最轻量级的方式。你只需要维护一个 JSON 或 YAML 文件,Prometheus 会自动监听文件变化。

# prometheus.yml 配置
scrape_configs:
  - job_name: 'node_exporter'
    file_sd_configs:
      - files:
          - 'targets/node_*.json'
        refresh_interval: 30s

对应的 targets 文件:

// targets/node_exporter.json
[
  {
    "targets": ["192.168.1.10:9100", "192.168.1.11:9100"],
    "labels": {
      "env": "production",
      "region": "cn-beijing"
    }
  }
]

这样做的好处是——你可以在外部用脚本动态生成这个文件,Prometheus 自动加载,完全不用重启。

我在项目中遇到过一个场景:CMDB 变更后自动生成 targets 文件,配合 Ansible 推送,实现了监控目标的自动化管理。效果非常好。

4.4.2 基于 Consul 的服务发现

如果你的服务已经注册到 Consul,那直接用 Consul 的服务发现最省事。

scrape_configs:
  - job_name: 'consul_services'
    consul_sd_configs:
      - server: 'localhost:8500'
        services: []  # 空数组表示发现所有服务
    relabel_configs:
      - source_labels: [__meta_consul_service]
        target_label: job
      - source_labels: [__meta_consul_node]
        target_label: instance
      - source_labels: [__meta_consul_tags]
        target_label: tags

这里有个关键点——relabel_configs。说白了就是给抓取到的目标打标签,方便后续查询和告警。

我常用的 relabel 技巧:

  • 过滤不需要的服务:比如只抓取带 "monitor" 标签的服务
  • 重写 metrics_path:有些服务的 /metrics 路径不一样
  • 添加自定义标签:比如环境、机房等信息
注意:Consul 服务发现默认会抓取所有服务。如果你的 Consul 里注册了上百个服务,但只有十几个需要监控,一定要用 relabel 过滤掉不需要的。否则 Prometheus 会疯狂抓取,浪费资源。

4.5 实战经验总结

说了这么多,最后分享几个我踩过的坑:

  1. 存储路径权限:二进制部署时,Prometheus 进程用户要对数据目录有写权限。我见过有人用 root 启动,后来切到普通用户,数据目录权限没改,直接启动失败。
  2. 容器化部署的日志:Docker 方式部署时,日志默认输出到 stdout。建议配置日志轮转,否则 /var/lib/docker 会被撑爆。
  3. 服务发现频率:refresh_interval 别设太短。我曾经设了 5s,结果 Consul 压力太大,差点把注册中心搞挂了。建议 30s 以上。
  4. 配置校验:每次改完配置文件,记得用 promtool check config prometheus.yml 检查一下。这个习惯救过我很多次。

嗯,关于部署和配置就先聊到这。下一章咱们讲 PromQL 查询语言,那可是 Prometheus 的灵魂。到时候我会分享一些我写查询语句的「野路子」,保证让你少走弯路。