使用 Docker 部署 Prometheus、Grafana 和 Alertmanager 监控系统
先决条件
- Ubuntu 24.04 LTS
- Docker-CE 已安装
创建公共网络
# 默认只有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 文件内容
- 添加监控服务器只需要在 job_name: node_exporter 下编辑即可
点击展开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 文件内容
- 默认使用 telegram 接收告警通知,你可以改成邮件或其他
- 记得修改 chat_id 和 bot_token,换成你自己的ID
- 根据需求可修改 message 参数下的信息
- 可适当修改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 文件内容
- 注意rules是目录,要跟上面prometheus.yml 文件里的 rule_files 参数对应
- 可根据需要添加alert,如监控流量、抓取各种指标数据等等
点击查看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 相关配置
- 禁止部分端口对外访问,并通过nginx proxy manager 进行反代(通过域名+证书进行访问)
# 添加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
告警通知示例
