Prometheus + Grafana 监控系统搭建实战:从零到生产可用

前言

上个月公司服务器半夜挂了,第二天早上才发现。老板问:为什么没有监控?

好吧,是时候搞一套监控系统了。

调研了一圈,最终选了 Prometheus + Grafana 这套组合:

  • Prometheus:负责采集和存储指标数据
  • Grafana:负责可视化展示
  • 开源免费,社区活跃
  • 云原生标配,K8s原生支持

这篇文章记录完整的搭建过程,包括踩过的坑。


一、架构设计

先看整体架构:


┌─────────────────────────────────────────────────────────────┐
│ 监控系统架构 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 服务器A │ │ 服务器B │ │ 服务器C │ │
│ │ Node │ │ Node │ │ Node │ │
│ │ Exporter │ │ Exporter │ │ Exporter │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ └───────────────┼───────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ │
│ │ Prometheus │◄─── 拉取指标(Pull模式) │
│ │ (时序数据库) │ │
│ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ │
│ │ Grafana │◄─── 可视化展示 │
│ │ (仪表盘) │ │
│ └───────┬────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────┐ │
│ │ Alertmanager │◄─── 告警推送 │
│ │ (告警管理) │ (邮件/钉钉/企微) │
│ └────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘

**核心组件:**

| 组件 | 作用 | 端口 |
|------|------|------|
| Prometheus | 指标采集、存储、查询 | 9090 |
| Grafana | 可视化仪表盘 | 3000 |
| Node Exporter | 采集服务器指标(CPU/内存/磁盘) | 9100 |
| Alertmanager | 告警管理和推送 | 9093 |

---

## 二、环境准备

**服务器配置:**
- 监控服务器:2核4GB(跑Prometheus+Grafana)
- 被监控服务器:若干台

**系统环境:**
- Ubuntu 22.04 / CentOS 7+
- Docker 20.10+(推荐用Docker部署)

---

## 三、部署 Prometheus

### 3.1 Docker Compose 部署

创建目录和配置文件:

```bash
mkdir -p /opt/monitoring/{prometheus,grafana,alertmanager}
cd /opt/monitoring

创建 docker-compose.yml

version: '3.8'

services:
  prometheus:
    image: prom/prometheus:v2.47.0
    container_name: prometheus
    restart: always
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
      - ./prometheus/rules:/etc/prometheus/rules
      - prometheus_data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--storage.tsdb.retention.time=30d'  # 数据保留30天
      - '--web.enable-lifecycle'  # 支持热重载
    networks:
      - monitoring

  grafana:
    image: grafana/grafana:10.1.0
    container_name: grafana
    restart: always
    ports:
      - "3000:3000"
    volumes:
      - grafana_data:/var/lib/grafana
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=your_password  # 改成你的密码
      - GF_USERS_ALLOW_SIGN_UP=false
    networks:
      - monitoring

  alertmanager:
    image: prom/alertmanager:v0.26.0
    container_name: alertmanager
    restart: always
    ports:
      - "9093:9093"
    volumes:
      - ./alertmanager/alertmanager.yml:/etc/alertmanager/alertmanager.yml
    networks:
      - monitoring

volumes:
  prometheus_data:
  grafana_data:

networks:
  monitoring:
    driver: bridge

3.2 配置 Prometheus

创建 prometheus/prometheus.yml

global:
  scrape_interval: 15s      # 采集间隔
  evaluation_interval: 15s  # 规则评估间隔

alerting:
  alertmanagers:
    - static_configs:
        - targets:
          - alertmanager:9093

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

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

  # 监控服务器(Node Exporter)
  - job_name: 'nodes'
    static_configs:
      - targets:
        - '192.168.1.10:9100'  # 服务器A
        - '192.168.1.11:9100'  # 服务器B
        - '192.168.1.12:9100'  # 服务器C
    relabel_configs:
      - source_labels: [__address__]
        regex: '([^:]+):.*'
        target_label: instance
        replacement: '${1}'

3.3 配置告警规则

创建 prometheus/rules/node_alerts.yml

groups:
  - name: node_alerts
    rules:
      # CPU使用率过高
      - alert: HighCpuUsage
        expr: 100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "CPU使用率过高"
          description: "服务器 {{ $labels.instance }} CPU使用率超过80%,当前值:{{ $value | printf \"%.1f\" }}%"

      # 内存使用率过高
      - alert: HighMemoryUsage
        expr: (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100 > 85
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "内存使用率过高"
          description: "服务器 {{ $labels.instance }} 内存使用率超过85%,当前值:{{ $value | printf \"%.1f\" }}%"

      # 磁盘使用率过高
      - alert: HighDiskUsage
        expr: (1 - node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"} / node_filesystem_size_bytes) * 100 > 85
        for: 5m
        labels:
          severity: warning
        annotations:
          summary: "磁盘使用率过高"
          description: "服务器 {{ $labels.instance }} 磁盘 {{ $labels.mountpoint }} 使用率超过85%"

      # 服务器宕机
      - alert: InstanceDown
        expr: up == 0
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "服务器宕机"
          description: "服务器 {{ $labels.instance }} 已经宕机超过1分钟"

3.4 配置 Alertmanager(钉钉告警)

创建 alertmanager/alertmanager.yml

global:
  resolve_timeout: 5m

route:
  group_by: ['alertname', 'instance']
  group_wait: 30s
  group_interval: 5m
  repeat_interval: 4h
  receiver: 'dingtalk'

receivers:
  - name: 'dingtalk'
    webhook_configs:
      - url: 'http://dingtalk-webhook:8060/dingtalk/webhook1/send'
        send_resolved: true

钉钉Webhook需要单独部署一个转发服务,这里用 prometheus-webhook-dingtalk

docker-compose.yml 中添加:

dingtalk:
    image: timonwong/prometheus-webhook-dingtalk:v2.1.0
    container_name: dingtalk-webhook
    restart: always
    ports:
      - "8060:8060"
    volumes:
      - ./dingtalk/config.yml:/etc/prometheus-webhook-dingtalk/config.yml
    networks:
      - monitoring

创建 dingtalk/config.yml

targets:
  webhook1:
    url: https://oapi.dingtalk.com/robot/send?access_token=你的钉钉机器人Token
    secret: 你的钉钉机器人加签密钥

3.5 启动服务

docker-compose up -d

# 检查状态
docker-compose ps

# 查看日志
docker-compose logs -f prometheus

访问 http://服务器IP:9090 验证Prometheus是否正常。


四、部署 Node Exporter

每台被监控的服务器上部署 Node Exporter。

4.1 Docker 部署

docker run -d \
  --name node_exporter \
  --restart always \
  --net host \
  --pid host \
  -v "/:/host:ro,rslave" \
  prom/node-exporter:v1.6.1 \
  --path.rootfs=/host

4.2 二进制部署(推荐生产环境)

# 下载
wget https://github.com/prometheus/node_exporter/releases/download/v1.6.1/node_exporter-1.6.1.linux-amd64.tar.gz

# 解压
tar xvf node_exporter-1.6.1.linux-amd64.tar.gz
mv node_exporter-1.6.1.linux-amd64/node_exporter /usr/local/bin/

# 创建systemd服务
cat > /etc/systemd/system/node_exporter.service << 'EOF'
[Unit]
Description=Node Exporter
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/node_exporter
Restart=on-failure

[Install]
WantedBy=multi-user.target
EOF

# 启动
systemctl daemon-reload
systemctl enable node_exporter
systemctl start node_exporter

# 验证
curl localhost:9100/metrics

4.3 验证数据采集

回到Prometheus的Web界面:

  1. 访问 http://Prometheus服务器:9090/targets
  2. 确认所有Node Exporter状态为 UP

如果状态是 DOWN,检查:

  • Node Exporter是否启动
  • 防火墙是否开放9100端口
  • 网络是否连通

五、配置 Grafana 仪表盘

5.1 登录 Grafana

访问 http://服务器IP:3000

  • 用户名:admin
  • 密码:docker-compose.yml 中设置的密码

5.2 添加数据源

  1. 左侧菜单 → Configuration → Data Sources
  2. 点击 "Add data source"
  3. 选择 "Prometheus"
  4. URL填写:http://prometheus:9090(Docker网络内部地址)
  5. 点击 "Save & Test"

5.3 导入仪表盘

不用从零开始做仪表盘,直接导入社区模板:

  1. 左侧菜单 → Dashboards → Import

  2. 输入仪表盘ID:

    • Node Exporter Full:1860(最全面的服务器监控)
    • Docker监控:893
    • Prometheus Stats:2
  3. 选择Prometheus数据源

  4. 点击Import

导入1860号仪表盘后,你会看到:

  • CPU使用率曲线
  • 内存使用情况
  • 磁盘IO
  • 网络流量
  • 系统负载
  • ...

非常全面,基本不用自己配置。

5.4 自定义仪表盘(进阶)

如果想自定义,了解几个常用的PromQL查询:

CPU使用率:

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

内存使用率:

(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100

磁盘使用率:

(1 - node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"} / node_filesystem_size_bytes) * 100

网络接收流量(MB/s):

irate(node_network_receive_bytes_total{device!~"lo|veth.*"}[5m]) / 1024 / 1024

系统负载:

node_load1  # 1分钟负载
node_load5  # 5分钟负载
node_load15 # 15分钟负载

六、监控更多服务

6.1 监控 MySQL

部署 mysqld_exporter

docker run -d \
  --name mysqld_exporter \
  --restart always \
  -p 9104:9104 \
  -e DATA_SOURCE_NAME="exporter:密码@(mysql服务器:3306)/" \
  prom/mysqld-exporter

在Prometheus配置中添加:

- job_name: 'mysql'
    static_configs:
      - targets: ['mysqld_exporter:9104']

Grafana仪表盘ID:7362

6.2 监控 Redis

部署 redis_exporter

docker run -d \
  --name redis_exporter \
  --restart always \
  -p 9121:9121 \
  oliver006/redis_exporter \
  --redis.addr=redis://Redis服务器:6379

Prometheus配置:

- job_name: 'redis'
    static_configs:
      - targets: ['redis_exporter:9121']

Grafana仪表盘ID:763

6.3 监控 Nginx

需要先开启Nginx的stub_status模块:

server {
    listen 8080;
    location /nginx_status {
        stub_status;
        allow 127.0.0.1;
        deny all;
    }
}

部署 nginx-prometheus-exporter

docker run -d \
  --name nginx_exporter \
  --restart always \
  -p 9113:9113 \
  nginx/nginx-prometheus-exporter \
  -nginx.scrape-uri=http://Nginx服务器:8080/nginx_status

Grafana仪表盘ID:12708

6.4 监控 Docker 容器

部署 cAdvisor

docker run -d \
  --name cadvisor \
  --restart always \
  -p 8080:8080 \
  -v /:/rootfs:ro \
  -v /var/run:/var/run:ro \
  -v /sys:/sys:ro \
  -v /var/lib/docker/:/var/lib/docker:ro \
  gcr.io/cadvisor/cadvisor:v0.47.0

Prometheus配置:

- job_name: 'cadvisor'
    static_configs:
      - targets: ['cadvisor:8080']

Grafana仪表盘ID:893


七、告警配置实战

7.1 告警触发流程

Prometheus采集指标 → 匹配告警规则 → 触发告警 → 发送到Alertmanager → 推送到钉钉/邮件

7.2 告警规则详解

- alert: HighCpuUsage
  expr: 100 - (avg by(instance) (irate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
  for: 5m  # 持续5分钟才告警,避免瞬时波动误报
  labels:
    severity: warning  # 告警级别
  annotations:
    summary: "CPU使用率过高"
    description: "服务器 {{ $labels.instance }} CPU使用率超过80%"

关键参数:

  • expr:PromQL表达式,满足条件则触发
  • for:持续时间,防止抖动
  • labels:标签,用于告警分组和路由
  • annotations:告警内容描述

7.3 告警分级路由

在Alertmanager中配置不同级别告警发送到不同渠道:

route:
  receiver: 'default'
  routes:
    # 严重告警发到运维群
    - match:
        severity: critical
      receiver: 'ops-team'
      repeat_interval: 1h
    
    # 警告级别发到开发群
    - match:
        severity: warning
      receiver: 'dev-team'
      repeat_interval: 4h

receivers:
  - name: 'default'
    webhook_configs:
      - url: 'http://dingtalk:8060/dingtalk/default/send'
  
  - name: 'ops-team'
    webhook_configs:
      - url: 'http://dingtalk:8060/dingtalk/ops/send'
  
  - name: 'dev-team'
    webhook_configs:
      - url: 'http://dingtalk:8060/dingtalk/dev/send'

7.4 告警静默

半夜发版不想收到告警?可以设置静默:

  1. 访问 Alertmanager:http://服务器IP:9093
  2. 点击 "Silences" → "New Silence"
  3. 设置匹配条件和静默时间

八、远程监控方案

如果你的服务器分布在不同地方(公司、家里、云上),怎么统一监控?

8.1 方案一:公网暴露(不推荐)

把Prometheus的9090端口暴露到公网,不安全。

8.2 方案二:VPN(传统方案)

配置复杂,维护成本高。

8.3 方案三:组网工具(推荐)

我用的是星空组网,把分布在不同地方的服务器组成一个虚拟局域网:

  1. 每台服务器装星空组网客户端
  2. 登录同一账号,加入同一网络
  3. 服务器互相之间可以用虚拟IP访问

配置Prometheus监控远程服务器:

scrape_configs:
  - job_name: 'nodes'
    static_configs:
      - targets:
        - '10.26.1.10:9100'  # 公司服务器(虚拟IP)
        - '10.26.1.20:9100'  # 家里NAS(虚拟IP)
        - '10.26.1.30:9100'  # 云服务器(虚拟IP)

优势:

  • 不用暴露端口到公网
  • 配置简单,5分钟搞定
  • P2P直连,延迟低
  • 免费版3设备够个人用

这样在家也能看到公司服务器的监控数据,出差时也能随时查看。


九、性能优化

9.1 Prometheus 存储优化

默认配置下,Prometheus会把所有数据存本地。数据量大了会有问题。

优化参数:

# docker-compose.yml 的 command 部分
command:
  - '--storage.tsdb.retention.time=15d'  # 减少保留时间
  - '--storage.tsdb.retention.size=10GB'  # 限制存储大小
  - '--storage.tsdb.wal-compression'      # 开启WAL压缩

9.2 采集频率优化

不是所有指标都需要15秒采集一次:

scrape_configs:
  # 核心服务,15秒采集
  - job_name: 'critical-nodes'
    scrape_interval: 15s
    static_configs:
      - targets: ['核心服务器:9100']

  # 非核心服务,1分钟采集
  - job_name: 'normal-nodes'
    scrape_interval: 60s
    static_configs:
      - targets: ['普通服务器:9100']

9.3 Grafana 查询优化

仪表盘卡顿?可能是查询太重:

  1. 减少时间范围(从7天改成1天)
  2. 增加查询步长(Step)
  3. 使用 rate() 代替 irate()(更平滑,计算量小)

十、踩过的坑

坑1:时间不同步导致数据断层

现象: Grafana图表有断层,Prometheus显示"target is 5m in the future"

原因: 被监控服务器时间比Prometheus快了5分钟

解决: 所有服务器配置NTP同步

# Ubuntu
apt install chrony
systemctl enable chrony

# 强制同步
chronyc makestep

坑2:Docker网络内访问不通

现象: Prometheus采集不到容器内的Exporter

原因: 网络模式问题

解决: 确保所有容器在同一个Docker网络(monitoring)

坑3:Grafana仪表盘不显示数据

现象: 导入仪表盘后一片空白

原因: 数据源名称不匹配

解决: 仪表盘设置里把数据源改成你创建的名称

坑4:磁盘监控指标为空

现象: node_filesystem_* 指标没有数据

原因: Node Exporter没有挂载宿主机文件系统

解决:--path.rootfs=/host 参数并挂载 /:/host:ro


十一、生产环境 Checklist

部署到生产环境前,检查这些:


十二、总结

Prometheus + Grafana 这套组合,基本是现在监控的事实标准。

核心要点:

  1. 架构:Prometheus采集 + Grafana展示 + Alertmanager告警
  2. 部署:推荐Docker Compose,方便管理
  3. 仪表盘:直接导入社区模板,省时省力
  4. 告警:规则要合理,避免告警风暴
  5. 远程监控:用组网工具打通不同地点的服务器

下一步可以做的:

  • 接入更多服务监控(MySQL、Redis、应用指标)
  • 配置更完善的告警规则
  • 搭建高可用集群(Thanos/Cortex)

有问题评论区讨论,我尽量回复。


参考资料:


posted @ 2025-12-02 14:38  花宝宝  阅读(0)  评论(0)    收藏  举报