Prometheus监控实战:从零搭建云原生监控体系
1. 为什么你需要一个云原生监控系统?
如果你正在管理一个现代化的应用,无论是跑在Kubernetes上的微服务,还是分布在不同服务器上的容器化应用,你肯定遇到过这些问题:半夜收到报警说服务挂了,但登录服务器一看,CPU、内存都正常,问题到底出在哪?新版本上线后,某个接口的响应时间突然变长,是代码问题还是数据库瓶颈?想看看过去一周的业务增长趋势,却发现数据分散在各个日志文件里,无从下手。
传统的监控工具,比如Zabbix或者Nagios,在应对这种动态、弹性的云原生环境时,常常力不从心。它们配置复杂,扩展性差,而且很难和容器平台深度集成。这时候,你就需要一个像Prometheus这样的“云原生原住民”监控系统。
Prometheus(普罗米修斯)就像一个不知疲倦的“数据采集员”和“数据分析师”。它的核心工作模式非常简单:定期去各个被监控的目标(我们称之为Target)那里“问一问”:“嘿,你现在的状态怎么样?”目标通过一个HTTP接口把自己的各项指标(比如CPU使用率、请求数量、错误率)告诉它。Prometheus把这些带时间戳的数据存起来,形成一个时间序列数据库。之后,无论是你想实时查看图表,还是设置复杂的报警规则,它都能通过强大的PromQL查询语言快速给出答案。
我刚开始接触Prometheus时,最让我惊喜的就是它的“拉取模型”(Pull-based)。这意味着你的应用不需要集成复杂的SDK,只要暴露出一个/metrics的HTTP端点,Prometheus就能来抓数据。这种设计天生适合服务发现,在Kubernetes里,Pod今天在这台机器,明天可能就漂移到另一台,Prometheus能自动发现并开始监控它,完全不用你手动修改配置。
所以,这篇文章就是为你准备的,无论你是想监控几台虚拟机的基础设施,还是管理一个庞大的Kubernetes集群,我都会手把手带你从零开始,搭建一套功能完整、颜值在线的云原生监控体系。我们会覆盖最核心的四大块:Prometheus Server部署、各类Exporter配置、用Grafana做酷炫的可视化,以及通过Alertmanager实现精准的告警。跟着做下来,你不仅能获得一个生产可用的监控系统,更能彻底理解其运作原理。
2. 动手之前:理解核心组件与实验环境规划
在真正敲命令之前,花几分钟搞清楚Prometheus家族的几个核心成员是很有必要的,这能让你在后续配置时心里有张清晰的地图。
Prometheus Server 是绝对的大脑和心脏。它主要负责两件事:一是按照你设定的周期(比如15秒一次),主动去拉取(Scrape)各个监控目标的指标数据;二是将这些数据以时间序列的形式,高效地存储在本地的TSDB(时间序列数据库)中。它还提供了一个Web UI和HTTP API,让你能用PromQL查询数据。
Exporters 可以理解为“翻译官”或“适配器”。很多系统(比如Linux主机、MySQL数据库、Nginx)本身不会用Prometheus能理解的格式暴露指标。Exporter就负责“蹲守”在这些系统旁边,收集它们的原始数据,然后转换成Prometheus的格式,并通过一个HTTP端口暴露出来。例如,node_exporter专门收集主机层面的CPU、内存、磁盘、网络等信息;mysqld_exporter则专门收集MySQL的运行状态。
Alertmanager 是独立的“告警处理中心”。Prometheus Server根据你定义的规则(比如“CPU使用率超过80%持续5分钟”)计算出告警,然后发送给Alertmanager。Alertmanager的厉害之处在于,它能对这些告警进行分组、去重、静音,并决定通过什么渠道(邮件、Slack、钉钉等)发送给谁,避免告警风暴淹没运维人员。
Grafana 是“首席设计师”。Prometheus自带的UI比较简陋,主要用于查询和调试。Grafana则是一个专业的可视化平台,它可以从Prometheus(以及其他多种数据源)拉取数据,然后让你通过拖拽的方式,创建出非常美观、信息丰富的监控仪表盘(Dashboard)。社区有成千上万的现成仪表盘模板,你几乎可以“开箱即用”。
Pushgateway 是一个特殊的“中转站”。Prometheus默认是拉取模型,但有些生命周期很短的批处理任务(比如定时跑的数据备份脚本),还没等Prometheus来拉取就结束了。这类任务可以把指标数据“推”(Push)到Pushgateway暂存起来,再由Prometheus从中拉取。
为了模拟一个真实的小型环境,我们规划一个三节点的实验集群。所有操作都基于Docker,这能保证环境的一致性,也最贴近云原生的部署方式。
| 主机名 | IP地址 | 部署组件 | 角色 |
|---|---|---|---|
| docker1 | 192.168.10.11 | Prometheus Server, Node Exporter, cAdvisor, Grafana, Alertmanager | 监控服务器 |
| docker2 | 192.168.10.12 | Node Exporter, cAdvisor | 被监控节点 |
| docker3 | 192.168.10.13 | Node Exporter, cAdvisor | 被监控节点 |
准备工作:请确保三台主机之间网络互通,并且已经安装了Docker引擎。为了简化,我们暂时关闭防火墙和SELinux(生产环境请按需配置安全策略)。同时,记得修改三台主机的主机名分别为docker1、docker2、docker3,这会让后续操作更清晰。
3. 第一步:部署数据采集器(Node Exporter 和 cAdvisor)
监控的第一步是拿到数据。我们首先在所有三台主机上部署 node_exporter 和 cAdvisor,它们分别负责收集主机硬件/系统指标和容器运行指标。
3.1 部署 Node Exporter
node_exporter 是一个静态二进制文件,用Docker运行它非常简单。它的原理是读取Linux系统下的 /proc、/sys 等虚拟文件系统来获取信息。
在 docker1、docker2、docker3 上分别执行以下命令:
docker run -d \
--name node-exporter \
--net=host \
--pid=host \
-v /proc:/host/proc:ro \
-v /sys:/host/sys:ro \
-v /:/rootfs:ro \
prom/node-exporter:latest \
--path.procfs=/host/proc \
--path.sysfs=/host/sys \
--collector.filesystem.ignored-mount-points="^/(sys|proc|dev|host|etc)($|/)"
我来解释一下这几个参数:
--net=host:让容器使用宿主机的网络命名空间。这样Prometheus Server(也在docker1上)就能直接用宿主机的IP(192.168.10.11)和端口(9100)来访问它,省去了复杂的网络配置。--pid=host:让容器能看到宿主机的所有进程信息,这对于收集进程相关的指标是必要的。-v ...:将宿主机的/proc、/sys和根目录/以只读(ro)方式挂载到容器内,这是node_exporter的数据来源。- 最后的命令行参数是告诉
node_exporter挂载点的路径,并忽略一些无关的文件系统。
执行后,用 docker ps 检查容器是否运行正常。然后,你可以在浏览器访问 http://192.168.10.11:9100/metrics(将IP换成对应主机的),应该能看到大量以 node_ 开头的指标文本,例如 node_cpu_seconds_total、node_memory_MemFree_bytes。这就说明 node_exporter 工作正常,正在暴露指标。
3.2 部署 cAdvisor
cAdvisor(Container Advisor)是Google开源的工具,它能自动发现、采集、处理和导出所在机器上运行的所有容器的资源使用和性能指标。
同样,在三台主机上分别执行:
docker run -d \
--name=cadvisor \
--net=host \
--volume=/:/rootfs:ro \
--volume=/var/run:/var/run:rw \
--volume=/sys:/sys:ro \
--volume=/var/lib/docker:/var/lib/docker:ro \
--volume=/dev/disk/:/dev/disk:ro \
google/cadvisor:latest
参数解读:
- 同样使用
--net=host模式。 - 挂载了多个宿主机的目录,使cAdvisor能访问到Docker守护进程、容器文件系统、磁盘设备等信息。
- 默认会暴露8080端口。
部署完成后,访问 http://192.168.10.11:8080/containers/ 可以看到一个简单的Web UI,列出了当前主机上所有容器及其资源使用情况。更重要的,访问 http://192.168.10.11:8080/metrics 会看到大量以 container_ 开头的指标,这些就是Prometheus需要的数据。
至此,我们三台主机上的“数据探针”都已经就位,它们正静静地通过9100和8080端口,等待着Prometheus Server来采集数据。
4. 第二步:安装与配置监控大脑(Prometheus Server)
现在,数据源准备好了,我们该部署核心的Prometheus Server了。我们将在 docker1 这台监控服务器上进行操作。
4.1 首次运行并获取配置文件
首先,我们以最简单的方式启动一个Prometheus容器,目的是把它默认的配置文件复制出来进行修改。
# 在 docker1 上执行
docker run -d --name prometheus-temp -p 9090:9090 prom/prometheus:latest
等待几秒钟后,将容器内的配置文件复制到宿主机当前目录:
docker cp prometheus-temp:/etc/prometheus/prometheus.yml ./
然后删除这个临时容器:
docker rm -f prometheus-temp
现在,你当前目录下就有了一个 prometheus.yml 文件。用文本编辑器(如vim)打开它,你会看到类似下面的内容:
global:
scrape_interval: 15s
evaluation_interval: 15s
alerting:
alertmanagers:
- static_configs:
- targets:
# - alertmanager:9093
rule_files:
# - "first_rules.yml"
# - "second_rules.yml"
scrape_configs:
- job_name: "prometheus"
static_configs:
- targets: ["localhost:9090"]
这个配置文件是Prometheus的“指挥手册”。scrape_interval 定义了拉取数据的默认频率。scrape_configs 部分是核心,它定义了要监控哪些“任务”(job)以及对应的目标(targets)。目前只有一个监控Prometheus自身(端口9090)的任务。
4.2 配置监控目标
我们需要修改 scrape_configs,把我们三台主机上的 node_exporter 和 cAdvisor 都加进去。为了清晰,我们可以定义两个监控任务。
将 scrape_configs 部分修改为如下内容:
scrape_configs:
# 监控Prometheus自身
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
# 监控所有节点的硬件和系统指标
- job_name: 'node-exporter'
static_configs:
- targets:
- '192.168.10.11:9100'
- '192.168.10.12:9100'
- '192.168.10.13:9100'
# 监控所有节点上的容器指标
- job_name: 'cadvisor'
static_configs:
- targets:
- '192.168.10.11:8080'
- '192.168.10.12:8080'
- '192.168.10.13:8080'
这里我们创建了三个“任务”:
prometheus:监控Prometheus Server自己的健康状态。node-exporter:监控三台主机的系统资源。cadvisor:监控三台主机上的容器。
static_configs 是一种静态配置目标的方式,适合我们这种IP固定的测试环境。在生产中,你可能会使用基于文件、DNS或Kubernetes的服务发现来动态管理目标。
4.3 正式启动Prometheus Server
配置文件修改好后,我们正式启动Prometheus Server,并将本地的配置文件挂载到容器内,这样我们的修改才能生效。
# 在 docker1 上执行
docker run -d \
--name prometheus \
--net=host \
-p 9090:9090 \
-v $(pwd)/prometheus.yml:/etc/prometheus/prometheus.yml \
prom/prometheus:latest
关键参数:
-v $(pwd)/prometheus.yml:/etc/prometheus/prometheus.yml:将宿主机当前目录下的配置文件,覆盖容器内的默认配置。--net=host:同样使用主机网络,方便与其他组件通信。
启动后,访问 http://192.168.10.11:9090。点击页面上方的 Status -> Targets。你应该能看到我们配置的7个目标(3个node-exporter + 3个cadvisor + 1个prometheus自身),并且它们的 State 都应该是绿色的 UP。
如果状态是 DOWN,通常是因为网络不通或端口未开放,请检查防火墙和容器运行状态。到这里,Prometheus Server已经在持续地采集并存储所有监控目标的指标数据了。你可以在首页的查询框里输入 up 并按 Execute,它会显示所有目标的存活状态(1为正常,0为异常)。试试输入 node_cpu_seconds_total 看看,你会看到所有节点CPU时间的详细时间序列数据。恭喜,监控数据流已经打通了!
5. 第三步:用Grafana打造专业可视化仪表盘
虽然Prometheus自带查询界面,但用它来做日常监控和展示实在太简陋了。接下来请出我们的可视化利器——Grafana。
5.1 部署Grafana
在 docker1 上执行以下命令来运行Grafana:
# 创建一个目录用于持久化Grafana的数据(如图表、用户信息等)
sudo mkdir -p /data/grafana-storage
sudo chmod 777 -R /data/grafana-storage
# 启动Grafana容器
docker run -d \
--name grafana \
--net=host \
-p 3000:3000 \
-v /data/grafana-storage:/var/lib/grafana \
-e "GF_SECURITY_ADMIN_PASSWORD=YourStrongPassword123" \
grafana/grafana-oss:latest
这里我们通过环境变量 GF_SECURITY_ADMIN_PASSWORD 设置了初始管理员密码(请务必修改成强密码)。Grafana默认用户名是 admin。
访问 http://192.168.10.11:3000,用 admin 和你设置的密码登录。
5.2 添加Prometheus数据源
登录后第一件事,就是告诉Grafana数据从哪里来。
- 点击左侧导航栏的齿轮图标(Configuration),选择 Data sources。
- 点击 Add data source。
- 选择 Prometheus。
- 在 HTTP 部分的 URL 栏,填写
http://localhost:9090(因为Grafana和Prometheus在同一主机且用了host网络)。 - 其他选项保持默认,滚动到页面最下方,点击 Save & test。如果看到绿色的 “Data source is working” 提示,说明连接成功。
5.3 导入现成的监控仪表盘
从头创建仪表盘很费时间,好在Grafana社区有海量优秀的模板。我们直接导入两个最常用的。
导入Node Exporter主机监控大盘:
- 点击左侧导航栏的 + 号,选择 Import。
- 在 Import via grafana.com 输入框中,填入模板ID
1860(这是一个非常全面和流行的Node Exporter监控模板),然后点击 Load。 - 在下一个页面,为仪表盘起个名字(比如“Host Metrics”),并在 Prometheus 下拉框中选择你刚才添加的数据源。
- 点击 Import。瞬间,一个包含CPU、内存、磁盘、网络、负载等全方位信息的专业仪表盘就出现了!
导入cAdvisor容器监控大盘:
- 同样点击 Import。
- 这次输入模板ID
193(这是一个经典的Docker容器监控模板),点击 Load。 - 选择数据源后点击 Import。现在你就能看到所有主机上每个容器的CPU、内存、网络IO、磁盘IO等详细指标了。
你可以通过页面左上角的下拉框,在不同仪表盘之间切换。试着在主机仪表盘里,把右上角的时间范围改成 Last 1 hour,看看图表的变化。Grafana的强大之处在于,你可以基于这些模板,轻松地自定义、添加或删除面板,打造完全符合你团队需求的监控视图。至此,一个直观、美观的监控可视化平台已经搭建完成。
6. 第四步:配置告警,让系统主动“说话”
监控的最终目的不是事后查看,而是事前预警。Prometheus的告警分为两步:首先在Prometheus Server中定义告警规则(Rule),当规则被触发时,产生告警并发送给Alertmanager;然后由Alertmanager负责处理这些告警,进行去重、分组、路由,并最终通过邮件、钉钉等方式通知到人。
6.1 部署与配置Alertmanager
首先,在 docker1 上启动一个临时的Alertmanager容器以获取默认配置。
docker run --name alertmanager-temp -d prom/alertmanager:latest
docker cp alertmanager-temp:/etc/alertmanager/alertmanager.yml ./
docker rm -f alertmanager-temp
编辑复制出来的 alertmanager.yml 文件。我们将配置一个使用QQ邮箱发送告警邮件的示例(其他邮箱服务商类似,需修改SMTP服务器地址和端口)。
global:
resolve_timeout: 5m
smtp_from: 'your_email@qq.com' # 发件人邮箱
smtp_smarthost: 'smtp.qq.com:465' # QQ邮箱SMTP服务器
smtp_auth_username: 'your_email@qq.com' # 发件人邮箱
smtp_auth_password: 'your_authorization_code' # 注意!这里是邮箱的授权码,不是登录密码
smtp_require_tls: true # QQ邮箱要求TLS
route:
group_by: ['alertname'] # 按告警名称分组
group_wait: 10s # 同一组告警等待10秒,以便合并
group_interval: 10s
repeat_interval: 1h # 重复告警的间隔
receiver: 'email-receiver' # 默认接收者
receivers:
- name: 'email-receiver'
email_configs:
- to: 'recipient@example.com' # 收件人邮箱
send_resolved: true # 当告警恢复时也发送通知
重要:你需要登录QQ邮箱,在“设置”->“账户”中开启POP3/SMTP服务,并生成一个授权码,用它替换上面的 smtp_auth_password。
保存配置文件后,正式启动Alertmanager:
docker run -d \
--name alertmanager \
--net=host \
-p 9093:9093 \
-v $(pwd)/alertmanager.yml:/etc/alertmanager/alertmanager.yml \
prom/alertmanager:latest
访问 http://192.168.10.11:9093 可以打开Alertmanager的Web UI,目前是空的,因为我们还没有告警规则。
6.2 在Prometheus中配置告警规则
告警规则定义了“在什么情况下触发告警”。规则文件通常以 .rules 或 .yml 结尾。我们在宿主机上创建一个规则目录和文件。
# 在 docker1 上执行
mkdir -p prometheus/rules
cd prometheus/rules
vim node-up.rules
在 node-up.rules 文件中写入如下内容:
groups:
- name: host-status
rules:
- alert: HostDown
expr: up{job="node-exporter"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "主机 {{ $labels.instance }} 下线"
description: "{{ $labels.instance }} 的 node-exporter 已超过1分钟无法访问。"
这个规则的意思是:对于 job="node-exporter" 的所有监控目标,如果其 up 指标的值等于0(即Prometheus无法拉取到数据),并且这种状态持续了1分钟(for: 1m),则触发一个名为 HostDown 的告警。告警级别(severity)为 critical。在告警信息中,会用变量 {{ $labels.instance }} 自动替换成具体的主机IP。
接下来,我们需要修改 prometheus.yml 配置文件,告诉Prometheus去哪里加载我们的告警规则文件,以及Alertmanager的地址在哪里。
打开之前修改的 prometheus.yml 文件,添加/修改以下部分:
# 在 alerting 部分配置 Alertmanager 地址
alerting:
alertmanagers:
- static_configs:
- targets: ['localhost:9093'] # Alertmanager的地址
# 指定告警规则文件的路径
rule_files:
- "/etc/prometheus/rules/*.rules" # 容器内的路径,我们将宿主机目录挂载进去
# scrape_configs 部分保持不变...
6.3 重新启动Prometheus Server
由于修改了配置并添加了规则文件,我们需要重新启动Prometheus容器,并挂载规则文件的目录。
# 在 docker1 上,先停止旧容器
docker rm -f prometheus
# 重新启动,挂载规则目录
docker run -d \
--name prometheus \
--net=host \
-p 9090:9090 \
-v $(pwd)/prometheus.yml:/etc/prometheus/prometheus.yml \
-v $(pwd)/prometheus/rules:/etc/prometheus/rules \
prom/prometheus:latest
启动后,访问 http://192.168.10.11:9090/alerts。你应该能看到我们定义的 HostDown 告警规则,并且状态是绿色的 Inactive,因为目前所有主机都是正常的。
6.4 模拟故障,测试告警流程
现在我们来模拟一个故障,验证整个告警链路是否畅通。 在 docker3 主机上,停止 node_exporter 容器:
# 在 docker3 上执行
docker stop node-exporter
等待大约2-3分钟后:
- 刷新Prometheus的 Alerts 页面 (
http://192.168.10.11:9090/alerts)。HostDown规则的状态应该会变成黄色的 Pending(表示已触发但未满足for持续时间),最终变成红色的 Firing(表示告警已激活)。 - 访问Alertmanager的UI (
http://192.168.10.11:9093)。你应该能在 Alerts 页面看到一个HostDown的告警,里面包含了192.168.10.13:9100这个实例信息。 - 检查你在
alertmanager.yml中配置的收件人邮箱,应该会收到一封标题为[FIRING:1] HostDown (主机 192.168.10.13:9100 下线)的告警邮件。
测试完成后,在docker3上重新启动 node-exporter:docker start node-exporter。再过一会儿,告警状态会恢复,你也会收到一封“告警已解决”的邮件。
通过这个完整的流程,你已经搭建了一个能够自动发现故障、并通过邮件通知的监控告警系统。你可以依葫芦画瓢,定义更多实用的告警规则,比如“CPU使用率超过80%持续5分钟”、“容器内存使用超过限制”、“HTTP请求错误率飙升”等等。Alertmanager还支持配置多个接收器(Receiver),可以将不同严重等级的告警发送到不同的渠道,比如紧急告警发钉钉/短信,一般告警发邮件,实现告警的精细化管理。
更多推荐
所有评论(0)