共计 5150 个字符,预计需要花费 13 分钟才能阅读完成。
文章目录 [显示]
Docker 30 天实战系列 · Day 25
你有没有过这种经历:线上容器突然挂了,你一脸懵地看着 docker ps,发现容器已经重启了三次,但完全不知道发生了什么。CPU 飙了?内存爆了?磁盘满了?全靠猜。
这就像开车没有仪表盘——油量多少不知道,水温多高不清楚,等到车抛锚了才知道出了问题。今天我们就来给 Docker 装上一套 " 全液晶仪表盘 ":Prometheus + Grafana 监控体系。
本文你将学到
- 理解容器监控的整体架构和数据流向
- 使用 cAdvisor 采集容器运行指标
- 配置 Prometheus 存储和查询时序数据
- 搭建 Grafana 仪表盘实现可视化
- 编写 PromQL 查询常用容器指标
- 配置基础告警规则,让问题主动找你
阅读时间:15 分钟 | 实操时间:30 分钟 | 难度等级:中级
监控架构:三兄弟各司其职
在动手之前,先搞清楚这套监控体系的分工。我喜欢用餐厅来类比:
- cAdvisor 是 " 传菜员 "——它贴身跟着每个容器,实时收集 CPU、内存、网络、磁盘等指标数据
- Prometheus 是 " 账房先生 "——它定时去 cAdvisor 那里拉数据,分门别类记在自己的时序数据库里
- Grafana 是 " 大堂经理 "——它从 Prometheus 那里取数据,画成漂亮的图表展示给你看
数据流向用一张图表示:
+------------+ +------------+ +-----------+
| | pull | | query| |
| cAdvisor |<-----|Prometheus |<-----| Grafana |
| (采集器) | | (时序库) | | (仪表盘) |
+------------+ +------------+ +-----------+
| | |
v v v
容器指标 存储 + 告警 可视化展示
CPU/ 内存 / 网络 PromQL 查询 图表 / 仪表盘
注意这里的关键设计:Prometheus 是主动去 " 拉 " 数据的(Pull 模型),而不是 cAdvisor 主动 " 推 " 过来。这个设计很巧妙——Prometheus 自己控制采集频率,哪个目标挂了它也能立刻知道。
实操:一键部署监控栈
准备配置文件
首先创建项目目录和 Prometheus 配置:
mkdir -p monitoring && cd monitoring
创建 prometheus.yml 配置文件:
# prometheus.yml
global:
scrape_interval: 15s # 每 15 秒采集一次
evaluation_interval: 15s # 每 15 秒评估一次告警规则
rule_files:
- "alert_rules.yml"
scrape_configs:
# 监控 Prometheus 自身
- job_name: "prometheus"
static_configs:
- targets: ["localhost:9090"]
# 监控容器(通过 cAdvisor)- job_name: "cadvisor"
static_configs:
- targets: ["cadvisor:8080"]
# 监控宿主机(通过 Node Exporter)- job_name: "node-exporter"
static_configs:
- targets: ["node-exporter:9100"]
创建 alert_rules.yml 告警规则文件:
# alert_rules.yml
groups:
- name: container_alerts
rules:
# 容器 CPU 使用率超过 80%
- alert: ContainerHighCPU
expr: rate(container_cpu_usage_seconds_total{name!=""}[5m]) * 100 > 80
for: 2m
labels:
severity: warning
annotations:
summary: "容器 {{$labels.name}} CPU 使用率过高"
description: "容器 {{$labels.name}} CPU 使用率超过 80%,当前值: {{$value}}%"
# 容器内存使用率超过 85%
- alert: ContainerHighMemory
expr: container_memory_usage_bytes{name!=""} / container_spec_memory_limit_bytes{name!=""} * 100 > 85
for: 2m
labels:
severity: warning
annotations:
summary: "容器 {{$labels.name}} 内存使用率过高"
description: "容器 {{$labels.name}} 内存使用率超过 85%,当前值: {{$value}}%"
# 容器重启次数过多
- alert: ContainerFrequentRestart
expr: increase(container_last_seen{name!=""}[1h]) < 1
for: 5m
labels:
severity: critical
annotations:
summary: "容器 {{$labels.name}} 可能频繁重启"
编写 docker-compose.yml
这是完整的监控栈编排文件:
# docker-compose.yml
services:
# 容器指标采集器
cadvisor:
image: gcr.io/cadvisor/cadvisor:v0.47.2
container_name: cadvisor
restart: unless-stopped
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
- /dev/disk/:/dev/disk:ro
ports:
- "8080:8080"
privileged: true
devices:
- /dev/kmsg:/dev/kmsg
# 时序数据库 + 告警引擎
prometheus:
image: prom/prometheus:v2.51.0
container_name: prometheus
restart: unless-stopped
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
- ./alert_rules.yml:/etc/prometheus/alert_rules.yml:ro
- prometheus_data:/prometheus
ports:
- "9090:9090"
command:
- "--config.file=/etc/prometheus/prometheus.yml"
- "--storage.tsdb.retention.time=15d"
- "--web.enable-lifecycle"
depends_on:
- cadvisor
# 可视化仪表盘
grafana:
image: grafana/grafana:10.4.0
container_name: grafana
restart: unless-stopped
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin123
- GF_USERS_ALLOW_SIGN_UP=false
volumes:
- grafana_data:/var/lib/grafana
ports:
- "3000:3000"
depends_on:
- prometheus
# 宿主机指标采集(可选但推荐)node-exporter:
image: prom/node-exporter:v1.7.0
container_name: node-exporter
restart: unless-stopped
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- "--path.procfs=/host/proc"
- "--path.rootfs=/rootfs"
- "--path.sysfs=/host/sys"
ports:
- "9100:9100"
volumes:
prometheus_data:
grafana_data:
启动监控栈
docker compose up -d
预期输出:
[+] Running 5/5
✔ Network monitoring_default Created
✔ Volume "monitoring_prometheus_data" Created
✔ Volume "monitoring_grafana_data" Created
✔ Container cadvisor Started
✔ Container node-exporter Started
✔ Container prometheus Started
✔ Container grafana Started
等待约 30 秒让各组件初始化完成,然后验证:
# 检查所有容器是否正常运行
docker compose ps
# 验证 Prometheus 能采集到 cAdvisor 数据
curl -s http://localhost:9090/api/v1/targets | python3 -m json.tool | head -20
你应该能看到 cadvisor、prometheus、node-exporter 三个目标的状态都是 "health": "up"。
PromQL 入门:和数据对话
Prometheus 有自己的查询语言叫 PromQL,你可以把它理解为 " 时序数据的 SQL"。打开 http://localhost:9090,在查询框里试试这些:
常用查询示例
查看所有容器的 CPU 使用率(最近 5 分钟平均):
rate(container_cpu_usage_seconds_total{name!=""}[5m]) * 100
这里 rate() 计算的是每秒变化率,乘以 100 转成百分比。name!="" 过滤掉那些没名字的系统级 cgroup。
查看容器内存使用量(MB):
container_memory_usage_bytes{name!=""} / 1024 / 1024
查看容器网络接收速率(KB/s):
rate(container_network_receive_bytes_total{name!=""}[5m]) / 1024
找出内存使用 Top 5 的容器:
topk(5, container_memory_usage_bytes{name!=""})
PromQL 的套路其实很固定:选指标 → 加过滤条件 → 套函数。掌握 rate()、increase()、topk()、histogram_quantile() 这几个函数,日常监控就够用了。
Grafana 仪表盘搭建
添加数据源
- 打开
http://localhost:3000,用admin/admin123登录 - 进入 Connections > Data Sources > Add data source
- 选择 Prometheus
- URL 填写
http://prometheus:9090(容器间用服务名通信) - 点击 Save & test,看到绿色的 "Successfully queried the Prometheus API" 就对了
导入现成仪表盘
自己从零画仪表盘太费时间,Grafana 社区有大量现成模板。推荐这两个:
Docker 容器监控(Dashboard ID: 893):
- 进入 Dashboards > New > Import
- 输入 ID
893,点 Load - 选择刚才配置的 Prometheus 数据源
- 点 Import
你会立刻看到一个完整的容器监控面板,包含 CPU、内存、网络、磁盘 IO 等图表。
Node Exporter 宿主机监控(Dashboard ID: 1860):
同样的步骤,输入 ID 1860 导入,可以监控宿主机的系统资源。
自定义面板
如果想自己加一个面板,比如 " 各容器内存使用排行 ":
- 在仪表盘页面点 Add > Visualization
- 查询框输入:
sort_desc(container_memory_usage_bytes{name!=""}) / 1024 / 1024 - 右侧面板类型选 Bar gauge
- 单位设置为 MB
- 标题填 " 容器内存排行 "
几下点击,一个实用的面板就出来了。
告警配置进阶
前面 alert_rules.yml 里已经定义了基础告警规则,但光有规则还不够——告警触发了得通知到人才行。
查看告警状态
打开 http://localhost:9090/alerts,可以看到当前所有告警规则的状态:
- Inactive:一切正常,规则没触发
- Pending:条件已满足,但还在等
for指定的持续时间 - Firing:告警已触发
接入通知渠道
生产环境建议配合 Alertmanager 使用,可以对接:
- 企业微信 / 钉钉 Webhook
- 邮件通知
- PagerDuty
- Slack
在 docker-compose.yml 中增加 Alertmanager 服务:
alertmanager:
image: prom/alertmanager:v0.27.0
container_name: alertmanager
restart: unless-stopped
volumes:
- ./alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
ports:
- "9093:9093"
然后在 prometheus.yml 中添加 Alertmanager 地址:
alerting:
alertmanagers:
- static_configs:
- targets: ["alertmanager:9093"]
具体的通知渠道配置因团队而异,这里就不展开了,核心思路就是 " 规则在 Prometheus 定义,通知在 Alertmanager 分发 "。
常见问题 Q&A
Q1:cAdvisor 占用资源多吗?会不会影响业务容器?
cAdvisor 本身非常轻量,通常只占用 50-100MB 内存和极少的 CPU。它直接读取 Linux 内核的 cgroup 文件系统来获取指标,不会对业务容器产生干扰。不过在容器数量特别多(几百个以上)的场景下,建议适当调大采集间隔。
Q2:Prometheus 数据会不会把磁盘撑爆?
我们配置了 --storage.tsdb.retention.time=15d,也就是只保留最近 15 天的数据。按照采集 50 个容器、15 秒间隔来算,一天大约产生 200MB 数据,15 天也就 3GB 左右。如果你的容器特别多,可以调整保留时间或者增加磁盘。
Q3:Grafana 仪表盘打开很慢怎么办?
通常是查询时间范围太大导致的。把时间范围从 " 最近 7 天 " 缩小到 " 最近 1 小时 " 试试。另外检查一下面板里的 PromQL 查询有没有漏加 {name!=""} 过滤条件——不加过滤会查出大量系统级 cgroup 数据,严重拖慢速度。
小结
今天我们搭建了一套完整的容器监控体系:
- cAdvisor 负责采集每个容器的实时指标
- Prometheus 负责存储时序数据,提供 PromQL 查询能力
- Grafana 负责将数据可视化,让你一眼看清系统状态
- 告警规则 让问题主动找你,而不是你去找问题
这套方案是目前容器监控的事实标准,从个人项目到大厂生产环境都在用。掌握了它,你的容器就不再是 " 黑箱 " 了——每个容器用了多少 CPU、吃了多少内存、网络流量是否异常,全都一目了然。
记住一句话: 没有监控的系统就像没有仪表盘的汽车,跑得再快也不安全。
明天的 Day 26,我们将进入 Docker Swarm 集群编排,学习如何把多台机器组成一个集群来运行容器。单机玩够了,是时候搞集群了。