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_exportercAdvisor,它们分别负责收集主机硬件/系统指标和容器运行指标。

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_totalnode_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_exportercAdvisor 都加进去。为了清晰,我们可以定义两个监控任务。

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'

这里我们创建了三个“任务”:

  1. prometheus:监控Prometheus Server自己的健康状态。
  2. node-exporter:监控三台主机的系统资源。
  3. 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数据从哪里来。

  1. 点击左侧导航栏的齿轮图标(Configuration),选择 Data sources
  2. 点击 Add data source
  3. 选择 Prometheus
  4. HTTP 部分的 URL 栏,填写 http://localhost:9090(因为Grafana和Prometheus在同一主机且用了host网络)。
  5. 其他选项保持默认,滚动到页面最下方,点击 Save & test。如果看到绿色的 “Data source is working” 提示,说明连接成功。

5.3 导入现成的监控仪表盘

从头创建仪表盘很费时间,好在Grafana社区有海量优秀的模板。我们直接导入两个最常用的。

导入Node Exporter主机监控大盘

  1. 点击左侧导航栏的 + 号,选择 Import
  2. Import via grafana.com 输入框中,填入模板ID 1860(这是一个非常全面和流行的Node Exporter监控模板),然后点击 Load
  3. 在下一个页面,为仪表盘起个名字(比如“Host Metrics”),并在 Prometheus 下拉框中选择你刚才添加的数据源。
  4. 点击 Import。瞬间,一个包含CPU、内存、磁盘、网络、负载等全方位信息的专业仪表盘就出现了!

导入cAdvisor容器监控大盘

  1. 同样点击 Import
  2. 这次输入模板ID 193(这是一个经典的Docker容器监控模板),点击 Load
  3. 选择数据源后点击 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分钟后:

  1. 刷新Prometheus的 Alerts 页面 (http://192.168.10.11:9090/alerts)。HostDown 规则的状态应该会变成黄色的 Pending(表示已触发但未满足for持续时间),最终变成红色的 Firing(表示告警已激活)。
  2. 访问Alertmanager的UI (http://192.168.10.11:9093)。你应该能在 Alerts 页面看到一个 HostDown 的告警,里面包含了 192.168.10.13:9100 这个实例信息。
  3. 检查你在 alertmanager.yml 中配置的收件人邮箱,应该会收到一封标题为 [FIRING:1] HostDown (主机 192.168.10.13:9100 下线) 的告警邮件。

测试完成后,在docker3上重新启动 node-exporterdocker start node-exporter。再过一会儿,告警状态会恢复,你也会收到一封“告警已解决”的邮件。

通过这个完整的流程,你已经搭建了一个能够自动发现故障、并通过邮件通知的监控告警系统。你可以依葫芦画瓢,定义更多实用的告警规则,比如“CPU使用率超过80%持续5分钟”、“容器内存使用超过限制”、“HTTP请求错误率飙升”等等。Alertmanager还支持配置多个接收器(Receiver),可以将不同严重等级的告警发送到不同的渠道,比如紧急告警发钉钉/短信,一般告警发邮件,实现告警的精细化管理。

更多推荐