Skip to content
Go back

Docker deploys Prometheus Grafana Alertmanager monitoring system

Updated:

使用 Docker 部署 Prometheus、Grafana 和 Alertmanager 监控系统

先决条件

创建公共网络

# 默认只有ipv4地址
docker network create proxy_net
# 下面命令是容器需要分配ipv6地址
docker network create --driver bridge --ipv6 proxy_net

docker-compose.yml 文件内容

点击展开docker-compose代码
services:
  prometheus:
    image: prom/prometheus:latest
    ports:
      - "9090:9090"
    volumes:
      - prometheus_data:/prometheus
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
      - ./rules/:/etc/prometheus/rules
    networks:
      - proxy_net

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    volumes:
      - grafana_data:/var/lib/grafana
    environment:
      - GF_SECURITY_ADMIN_USER=admin
      - GF_SECURITY_ADMIN_PASSWORD=admin
    networks:
      - proxy_net

  alertmanager:
    image: prom/alertmanager:latest
    ports:
      - "9093:9093"
    volumes:
      - alertmanager_data:/alertmanager
      - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml
    networks:
      - proxy_net

  node-exporter:
    image: prom/node-exporter:latest
    ports:
      - "127.0.0.1:9100:9100"
    command:
      # 排除一些不必要的挂载点,避免产生过多或无用的指标
      - --path.procfs=/host/proc
      - --path.sysfs=/host/sys
      - --collector.filesystem.mount-points-exclude="^/(sys|proc|dev|host|etc|mnt/host|var/lib/docker/containers)($|/)"
    volumes:
      - /proc:/host/proc:ro # 挂载主机的 proc 文件系统
      - /sys:/host/sys:ro   # 挂载主机的 sys 文件系统
      - /:/rootfs:ro,rslave # 挂载根文件系统,用于获取磁盘使用等信息
    networks:
      - proxy_net

volumes:
  prometheus_data:
  grafana_data:
  alertmanager_data:

networks:
  proxy_net:
    external: true

prometheus.yml 文件内容

点击展开prometheus代码
global:
  scrape_interval: 15s # 默认抓取间隔
  evaluation_interval: 15s # 默认规则评估间隔

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

alerting:
  alertmanagers:
    - static_configs:
        - targets:
          # Alertmanager 的服务名称和端口,它在同一个 Docker Compose 网络中
          - 'alertmanager:9093'

scrape_configs:
  # 抓取 Prometheus 自身指标
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']
        labels:
          instance: 'prometheus-server'
          service: 'self-monitoring'

  # 抓取 Alertmanager 自身指标
  - job_name: 'alertmanager'
    static_configs:
      - targets: ['alertmanager:9093'] # Alertmanager 的服务名称和端口
        labels:
          instance: 'alertmanager-service'
          component: 'alerting'

  # 示例:如果要监控其他远程服务器上的 Node Exporter
  - job_name: 'node_exporter'
    static_configs:
      - targets: ['node-exporter:9100'] # 替换为你的远程服务器IP
        labels:
          instance: 'USA'
          location: 'GCP'

      - targets: ['[2000:0000:0000:0000:0000:0000:0000:0002]:9100'] # 替换为你的远程服务器IP
        labels:
          instance: 'FR'
          location: 'AWS'


    relabel_configs:
       - source_labels: [__address__]
         regex: '(\[([0-9a-fA-F:]+)\](:[0-9]+)?)|(([^:]+)(:[0-9]+)?)'
         target_label: ip
         replacement: '$2$4'

alertmanager.yml 文件内容

点击查看alertmanager代码
global:
  resolve_timeout: 5m  # 默认情况下,告警解决的超时时间

route:
  group_by: ['alertname']  # 按照 `alertname` 来分组告警
  group_wait: 30s  # 分组前等待的时间
  group_interval: 1m  # 两个告警之间的间隔
  repeat_interval: 2m  # 重复通知的间隔
  receiver: 'telegram'  # 默认接收器是 telegram

receivers:
  - name: 'telegram'
    telegram_configs:
      - chat_id: xxx
        bot_token: 'xxx'
        message: |
          {{ if eq .Status "firing" }}
          🚨 <b>严重告警</b> 🚨
          ⚠️ <b>告警名称:</b> {{ .CommonLabels.alertname | html }} (共 {{ .Alerts | len }} 个实例)
          {{ range .Alerts }}
          ----------------------------------------
          ⚠️ <b> IP地址:</b> {{ .Labels.ip | html }}
          ⚠️ <b>数据中心:</b> {{ .Labels.location | html }}
          ⚠️ <b>详细描述:</b> {{ .Annotations.description | html }}
          ⚠️ <b>通知时间:</b> {{ .StartsAt.Format "2006-01-02 15:04:05" }}
          ----------------------------------------
          {{ end }}
          {{ else }}
          ✅ <b>严重告警恢复</b> ✅
          <b>告警名称:</b> {{ .CommonLabels.alertname | html }} (共 {{ .Alerts | len }} 个实例)
          {{ range .Alerts }}
          ----------------------------------------
          <b> IP地址:</b> {{ .Labels.ip | html }}
          <b>数据中心:</b> {{ .Labels.location | html }}
          <b>详细描述:</b> {{ .Annotations.description | html }}
          <b>恢复时间:</b> {{ .EndsAt.Format "2006-01-02 15:04:05" }}
          {{ end }}
          {{ end }}
        parse_mode: 'HTML'
        send_resolved: true

rules/alerts.yml 文件内容

点击查看alerts代码
groups:
  - name: node-exporter-alerts
    rules:
      - alert: 实例离线
        expr: up == 0
        for: 1m
        labels:
          severity: critical
          instance: "{{ $labels.instance }}"
          ip: "{{ $labels.ip }}"
          location: "{{ $labels.location }}"
        annotations:
          summary: "实例 {{ $labels.instance }} 离线"
          description: "{{ $labels.instance }} 已停机超过 1 分钟。"

      - alert: 主机CPU使用率过高
        expr: 100 - (avg by(instance, ip, location) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 70
        for: 1m
        labels:
          severity: warning
          instance: "{{ $labels.instance }}"
          ip: "{{ $labels.ip }}"
          location: "{{ $labels.location }}"
        annotations:
          summary: "主机 CPU 使用率过高 (实例 {{ $labels.instance }})"
          description: "实例 {{ $labels.instance }} 的 CPU 使用率在过去 1 分钟内超过 70%。当前值: {{ $value | humanize }}%"

      - alert: 主机内存不足
        expr: node_memory_MemAvailable_bytes{job="node_exporter"} / node_memory_MemTotal_bytes{job="node_exporter"} * 100 < 10
        for: 5m
        labels:
          severity: critical
          instance: "{{ $labels.instance }}"
          ip: "{{ $labels.ip }}"
          location: "{{ $labels.location }}"
        annotations:
          summary: "主机内存不足 (实例 {{ $labels.instance }})"
          description: "实例 {{ $labels.instance }} 的可用内存低于总内存的 10% (过去 5 分钟)。当前值: {{ $value | humanize }}%"

      - alert: 主机磁盘空间不足
        expr: node_filesystem_avail_bytes{job="node_exporter",fstype="ext4",mountpoint="/"} / node_filesystem_size_bytes{job="node_exporter",fstype="ext4",mountpoint="/"} * 100 < 20
        for: 5m
        labels:
          severity: warning
          instance: "{{ $labels.instance }}"
          ip: "{{ $labels.ip }}"
          location: "{{ $labels.location }}"
        annotations:
          summary: "主机磁盘空间不足 (实例 {{ $labels.instance }}, 挂载点 {{ $labels.mountpoint }})"
          description: "实例 {{ $labels.instance }} (挂载点 {{ $labels.mountpoint }}) 的可用磁盘空间低于 20% (过去 5 分钟)。当前值: {{ $value | humanize }}%"

执行下面命令部署:

# 部署命令
docker compose up -d
# 查看容器运行情况
docker compose ps
# 容器重启命令
docker compose restart
# 重启单个容器只需加对应的名称
docker compose restart alertmanager

iptables 相关配置

# 添加iptables禁止部分端口对外访问
iptables -I DOCKER-USER -p tcp --dport 9090 -j DROP
iptables -I DOCKER-USER -p tcp --dport 9093 -j DROP
iptables -I DOCKER-USER -p tcp --dport 3000 -j DROP
# iptables修改后保存
netfilter-persistent save

告警通知示例

telegram告警通知


Share this post on:

Previous Post
Daily server traffic usage
Next Post
How to Install Nginx Proxy Manager on Ubuntu 24.04