第1篇 Prometheus 监控体系全景与基础环境搭建

文章来源声明: 原文作者:鸿观工坊; 来源站点:掘金; 原文链接:https://juejin.cn/post/7689091429972082723; 本文基于上述来源整理/加工,觅优补充点评,仅供技术学习交流。版权归原作者所有。
觅优短评

架构拆解清晰,配置与权限坑点踩得实在,资源参考表可直接落地。适合从零搭建 Prometheus 监控栈的运维与后端工程师快速上手。

传统监控方案在扩展性上存在明显局限,难以满足云原生环境对多维标签监控的需求。Prometheus 凭借多维数据模型、强大的 PromQL 查询语言、主动拉取机制以及丰富的 Exporter 生态,原生支持 Kubernetes,已然成为云原生监控领域的主流方案。

架构与组件方面,Prometheus 监控体系的整体架构由以下核心组件协同构成:

  • Prometheus Server:负责采集与存储监控数据,并执行规则计算;
  • Exporters:负责暴露系统与业务指标,如 node_exporter、Spring Boot Actuator、Nginx Exporter;
  • Alertmanager:负责告警的去重、分组与路由分发;
  • Grafana:负责监控数据的可视化展示;
  • Pushgateway:用于短生命周期任务的指标推送;
  • Service Discovery:负责动态发现监控目标,支持静态文件、Consul、Kubernetes 等多种方式。

官方架构图:

本文主要介绍容器化部署方案,各工具的详细使用将在后续篇章中详细介绍。

一、创建默认桥接网络

相同容器使用同一网络时,相互间可直接通过容器名访问,也可减少对外暴露的端口。

创建默认桥接网络:

docker network create -d bridge my-bridge

二、Prometheus 搭建

1、prometheus.yml

文件默认位置:/etc/prometheus/prometheus.yml

<span># my global config</span>
global:
  scrape_interval: 10s <span># Set the scrape interval to every 15 seconds. Default is every 1 minute.</span>
  evaluation_interval: 10s <span># Evaluate rules every 15 seconds. The default is every 1 minute.</span>
  <span># scrape_timeout is set to the global default (10s).</span>

<span># Alertmanager configuration</span>
alerting:
  alertmanagers:
    - static_configs:
        - targets:
          <span># - alertmanager:9093</span>

<span># Load rules once and periodically evaluate them according to the global 'evaluation_interval'.</span>
rule_files:
  <span># - "first_rules.yml"</span>
  <span># - "second_rules.yml"</span>

<span># A scrape configuration containing exactly one endpoint to scrape:</span>
<span># Here it's Prometheus itself.</span>
scrape_configs:
  <span># The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.</span>
  - job_name: <span>"prometheus"</span>

    <span># metrics_path defaults to '/metrics'</span>
    <span># scheme defaults to 'http'.</span>

    static_configs:
      - targets: [<span>"127.0.0.1:9090"</span>]
       <span># The label name is added as a label `label_name=<label_value>` to any timeseries scraped from this config.</span>
        labels:
          svc: <span>"prometheus"</span>
  - job_name: <span>"cim"</span>
    metrics_path: /metrics
    relabel_configs:
      - source_labels: [__address__]
        target_label: instance
    file_sd_configs:
    - files:
      - scrape/cim-local.yml
      refresh_interval: 5s

cim-local.yml

- targets:
  - 10.0.2.15:9100
  labels:
    svc: nodb
    <span>type</span>: node
- targets:
  - 10.0.2.15:8082
  labels:
    svc: nodb
    <span>type</span>: jvm
    __metrics_path__: <span>"/actuator/prometheus"</span>

2、修改宿主机数据目录权限

确认容器运行用户

<span># 容器已存在时</span>
$ docker <span>exec</span> -it prom <span>id</span>

<span># 还没有容器,直接通过镜像查看</span>
$ docker run -it --name prometheus --<span>rm</span> --entrypoint /bin/sh prom/prometheus:v3
/prometheus $ <span>id</span>
uid=65534(nobody) gid=65534(nobody) <span>groups</span>=65534(nobody)

<span># 更简洁写法</span>
$ docker run -it --<span>rm</span> --entrypoint <span>id</span> prom/prometheus:v3
uid=65534(nobody) gid=65534(nobody) <span>groups</span>=65534(nobody)

输出一般是 uid=65534(nobody) 或者 uid=1001。

修改宿主机数据目录权限

假设将宿主机目录 /data/volumes/prometheus/data 映射到容器内 /prometheus

<span># 方式A:修改目录属主为prometheus运行uid,示例uid=65534</span>
$ sudo <span>chown</span> -R 65534:65534  /data/volumes/prometheus

<span># 方式B:宽松权限(测试环境可用,生产优先chown)</span>
$ sudo <span>chmod</span> -R 775 /data/volumes/prometheus

若不修改,很可能出现如下报错:

open /prometheus/queries.active: permission denied
failed to initialize active query tracker

3、启动服务

docker run -d --name prometheus \
  --restart=always \
  --network my-bridge \
  -p 9090:9090 \
  -e TZ=<span>"Asia/Shanghai"</span> \
  -v /data/volumes/prometheus:/etc/prometheus \
  -v /data/volumes/prometheus/data:/prometheus \
  prom/prometheus:v3 \
    --config.file=/etc/prometheus/prometheus.yml \
    --web.enable-lifecycle

注意:

添加 --web.enable-lifecycle 参数时,一定要显式指定 --config.file

4、验证配置文件是否正确

调整配置文件后,先验证配置是否正确,避免因配置问题导致服务异常。

验证通过后再重新加载配置。

$ docker <span>exec</span> -it prometheus promtool check config /etc/prometheus/prometheus.yml
Checking /etc/prometheus/prometheus.yml
 SUCCESS: /etc/prometheus/prometheus.yml is valid prometheus config file syntax

5、热加载配置

$ curl -XPOST http://127.0.0.1:9090/-/reload
Lifecycle API is not enabled.

出于安全考虑,HTTP 重载接口默认不启用,需要先在启动命令中添加 --web.enable-lifecycle 参数,才能开启 /-/reload 接口。接口开启后,向 /-/reload 发送 HTTP POST 请求即可触发配置重载。

6、单节点资源配置参考

| 监控规模| 建议监控的 Spring Boot 应用数| CPU (核心)| 内存 (RAM)| SSD 存储| 适用场景与说明| | --- | --- | --- | --- | --- | --- | | 中小规模生产| 5 - 25 个 | 2 - 4 核| 4 - 8 GB| 50 - 100 GB| 适合小型团队或轻量级生产环境。数据保留建议 30 天。 | | 大规模生产| 25 - 100+ 个 | 4 - 8+ 核| 8 - 32+ GB| 100 - 500+ GB| 适合较大规模的监控需求。数据保留可根据需要设置为 30-90 天。 | | 高性能/极限场景| 约 500 个 (估算) | 8+ 核| 32+ GB| 1+ TB| 这是一个理论上限,前提是每个应用指标数较少且采集间隔较长(如 15s)。单节点 Prometheus 理论可支持千级监控目标。 |

⚠️ 注意:监控自身:务必监控 Prometheus 容器自身的资源使用情况,特别是 process_resident_memory_bytes(内存占用)和磁盘使用率。

7、几个核心概念

为方便对后续篇章的理解,请提前熟悉以下概念,并注意相互间的区别。

1)数据模型

| 概念| 说明| 示例/格式| 关键点| | --- | --- | --- | --- | | 指标 Metric | 表示“测什么” | http_requests_total| 指标名是时间序列的一部分 | | 标签 Label | 键值对,用于多维区分 | method="GET", status="200"| 标签组合决定时间序列的唯一性 | | 时间序列 Time Series | 指标名 + 一组标签唯一确定一条序列 | http_requests_total{method="GET", status="200"}| 同一指标不同标签就是不同序列 | | 样本 Sample | 时间序列在某个时间点的值 | <时间戳(ms)> <值>,如 1710000000000 1027| Prometheus 实际存储的是“序列 + 时间戳 + 值” | | 抓取文本格式 | /metrics 暴露的文本格式 | http_requests_total{method="GET"} 1027| 时间戳通常省略,由服务端补当前时间 |

2)采集与目标

| 概念| 说明| 示例| 关键点| | --- | --- | --- | --- | | Target | 被采集的目标 | 10.0.0.1:9100| Prometheus 主动拉取目标 /metrics| | Scrape | 一次抓取行为 | 按 scrape_interval 周期执行 | 默认 15s,可在 global 配置 | | Job | 一组同类目标的逻辑名称 | job_name: node| 来自 scrape_configs| | Instance | 具体目标地址 | instance="10.0.0.1:9100"| 抓取时自动附加 job 和 instance 标签 |

三、Grafana 搭建

启动服务

docker run -d --name=grafana \
  --restart=no \
  --network my-bridge \
  -p 3000:3000 \
  -e TZ=<span>"Asia/Shanghai"</span> \
  -e GF_USERS_DEFAULT_TIMEZONE=Asia/Shanghai \
  -v /data/volumes/grafana:/var/lib/grafana \
  grafana/grafana:13.0.7-ubuntu

若需要导出图片,请参考《Grafana 开源版导出 Dashboard PDF 教程:Docker 部署 Image Renderer 完整指南》

四、Alertmanager

1、alertmanager.yml

<span># Alertmanager 配置示例</span>
<span># 覆盖:邮件 / Slack / 企业微信 三类接收器</span>
<span># 路由策略:</span>
<span>#   1. 先按 job 分组,不同系统(job)的告警聚合在一起</span>
<span>#   2. 子路由再按 severity 分发:Warning → 邮件,Critical → 企业微信</span>
<span>#   3. Slack 作为全量告警的备选/备份通道</span>
<span># 使用方式:替换 <占位符> 后,挂载到 Alertmanager 的 --config.file 路径</span>

global:
  <span># SMTP 全局配置(邮件)</span>

  smtp_smarthost: <span>'smtp.aliyun.com:465'</span>
  smtp_from: <span>'*****@aliyun.com'</span>
  smtp_auth_username: <span>'*****@aliyun.com'</span>
  smtp_auth_password: <span>'123456'</span>
  smtp_require_tls: <span>false</span>

  <span># Slack 全局配置</span>
  slack_api_url: <span>'https://hooks.slack.com/services/T0BM91K2H2P/B0BMBUKN40M/th4U2ouK2lGzSCeye'</span>

  <span># 抑制重复告警</span>
  resolve_timeout: 5m

<span># 通知模板(可选,自定义标题和内容格式)</span>
templates:
  - <span>'/etc/alertmanager/templates/*.tmpl'</span>

<span># 路由树:先按 job 分组,子路由按 severity 分发</span>
route:
  <span># 根路由:按 job 分组,同一系统的告警聚合在一起</span>
  group_by: [<span>'job'</span>]
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  receiver: <span>'default'</span>

  routes:
    <span># ============================================================</span>
    <span># VM</span>
    <span># ============================================================</span>
    - matchers:
      - job = <span>"vm"</span>
      group_by: [<span>'job'</span>]
      group_wait: 1m
      group_interval: 10m
      repeat_interval: 1h
      receiver: <span>'slack-all'</span>
      <span>continue</span>: <span>false</span>

<span># ============================================================</span>
<span># 接收器定义</span>
<span># ============================================================</span>
receivers:
  <span># 默认兜底接收器</span>
  - name: <span>'default'</span>
    email_configs:
      - to: <span>'******@aliyun.com'</span>
        headers:
          Subject: <span>'[Prometheus][{{ .GroupLabels.severity }}] {{ .GroupLabels.job }} 告警'</span>
        html: |
          {{ range .Alerts }}
          <b>告警名称:</b> {{ .Labels.alertname }}<br>
          <b>Job:</b> {{ .Labels.job }}<br>
          <b>Svc:</b> {{ .Labels.svc }}<br>
          <b>Instance:</b> {{ .Labels.instance }}<br>
          <b>级别:</b> {{ .Labels.severity }}<br>
          <b>摘要:</b> {{ .Annotations.summary }}<br>
          <b>描述:</b> {{ .Annotations.description }}<br>
          <b>开始时间:</b> {{ .StartsAt.Format <span>"2006-01-02 15:04:05"</span> }}<br>
          <hr>
          {{ end }}

  <span># -------------------- Slack 接收器 --------------------</span>
  - name: <span>'slack-all'</span>
    slack_configs:
      - channel: <span>'#ph'</span>
        username: <span>'Alertmanager'</span>
        icon_emoji: <span>':warning:'</span>
        title: |
          [{{ .Status | toUpper }}] {{ .GroupLabels.job }} - {{ .GroupLabels.severity }}
        text: |
          {{ range .Alerts }}
          *Alert:* {{ .Labels.alertname }}
          *Job:* {{ .Labels.job }}
          *Svc:* {{ .Labels.svc }}
          *Instance:* {{ .Labels.instance }}
          *Severity:* {{ .Labels.severity }}
          *Summary:* {{ .Annotations.summary }}
          *Description:* {{ .Annotations.description }}
          *Started:* {{ .StartsAt.Format <span>"2006-01-02 15:04:05"</span> }}
          {{ end }}

<span># ============================================================</span>
<span># 抑制规则:Critical 触发时抑制同 job+instance 的 Warning(避免轰炸)</span>
<span># ============================================================</span>
inhibit_rules:
  - source_match:
      severity: <span>'critical'</span>
    target_match:
      severity: <span>'warning'</span>
    equal: [<span>'job'</span>, <span>'instance'</span>]

2、启动服务

docker run -d --name alertmanager \
  --<span>rm</span> \
  --restart=no \
  --network my-bridge \
  -p 9093:9093 \
  -e TZ=Asia/Shanghai \
  -v /data/volumes/alertmanager:/etc/alertmanager \
  prom/alertmanager:v0.33.1

配置文件位置:/etc/alertmanager/alertmanager.yml。

3、验证配置文件是否正确

调整配置文件后,先验证配置是否正确,避免因配置问题导致服务异常。

验证通过后再重新加载配置。

$ docker <span>exec</span> -it alertmanager amtool check-config /etc/alertmanager/alertmanager.yml
Checking <span>'/etc/alertmanager/alertmanager.yml'</span>  SUCCESS
Found:
 - global config
 - route
 - 1 inhibit rules
 - 2 receivers
 - 1 templates
  SUCCESS

  • 输出 SUCCESS = yaml 语法、路由、接收器、抑制规则全部校验通过
  • 若有错误,会直接打印行号和错误原因,并以非 0 退出码退出。
  • 如果用到模板文件,会一并校验模板。

4、热加载配置

curl -XPOST http://127.0.0.1:9093/-/reload

五、Docker Compose 方式部署

注意:

  • docker-compose:独立二进制旧版本,Python 编写
  • docker compose:Docker Engine 内置插件(推荐,无短横线),Go 编写,用法基本一致

Docker 19.03 版本开始引入 docker compose 命令作为一项实验性功能。

Docker 20.10 及更高版本开始被广泛认为“自动集成了 Compose”。

Docker 22.06+ 版本明确内置了 docker compose 插件。

1、docker-compose.yml 文件示例

services:
  prometheus:
    image: prom/prometheus:v3
    container_name: prometheus
    restart: always
    networks:
      - my-bridge
    ports:
      - <span>"9090:9090"</span>
    environment:
      - TZ=<span>"Asia/Shanghai"</span>
    volumes:
      - /data/volumes/prometheus:/etc/prometheus
      - /data/volumes/prometheus/data:/prometheus
    <span>command</span>:
      - <span>'--config.file=/etc/prometheus/prometheus.yml'</span>
      - <span>'--web.enable-lifecycle'</span>

  grafana:
    image: grafana/grafana:13.0.7-ubuntu
    container_name: grafana
    restart: no
    networks:
      - my-bridge
    ports:
      - <span>"3000:3000"</span>
    environment:
      - TZ=<span>"Asia/Shanghai"</span>
      - GF_USERS_DEFAULT_TIMEZONE=Asia/Shanghai
    volumes:
      - /data/volumes/grafana:/var/lib/grafana

  alertmanager:
    image: prom/alertmanager:v0.33.1
    container_name: alertmanager
    restart: no
    networks:
      - my-bridge
    ports:
      - <span>"9093:9093"</span>
    environment:
      - TZ=<span>"Asia/Shanghai"</span>
    volumes:
      - /data/volumes/alertmanager:/etc/alertmanager

networks:
  my-bridge:
    external: <span>true</span>

2、启动服务

$ docker compose up -d
[+] up 3/3
✔ Container grafana      Created        1.3s
✔ Container alertmanager Created        1.2s
✔ Container prometheus   Created        1.2s

基础操作

<span># 启动所有服务(后台运行,推荐)</span>
docker compose up -d

<span># 启动并打印日志(前台)</span>
docker compose up

<span># 重启指定服务</span>
docker compose restart 服务名

<span># 停止服务,不删除容器、网络、卷</span>
docker compose stop

<span># 启动已停止的服务</span>
docker compose start

<span># 停止并删除容器、网络(保留数据卷)</span>
docker compose down

<span># 停止并删除容器、网络、数据卷(⚠️会丢数据)</span>
docker compose down -v