
监控体系的价值在于让问题在用户反馈之前被发现。本文用 Prometheus 采集指标、Grafana 做可视化、Alertmanager 发送告警,搭建一套完整的服务器与服务监控。内容涵盖组件职责、Docker 部署、节点与容器指标采集、面板配置、告警规则编写与通知对接,以及指标缺失和存储膨胀的排查方法。
先理清各组件分工,配置时才不会混淆。
组件 | 职责 |
|---|---|
Prometheus | 定期从各目标拉取指标并存储,执行告警规则判断 |
Exporter | 部署在被监控对象上,把系统或应用状态暴露为指标接口 |
Grafana | 从 Prometheus 查询数据并渲染成图表面板 |
Alertmanager | 接收 Prometheus 触发的告警,去重分组后发送通知 |
数据流向是:Exporter 暴露指标 → Prometheus 定期拉取并存储 → Grafana 查询展示,同时 Prometheus 根据规则判断异常 → 触发告警给 Alertmanager → 发送通知。
这里有个关键概念:Prometheus 采用主动拉取模式,是它去访问各个 Exporter,而不是 Exporter 推送给它。所以网络连通性方向是 Prometheus 能访问被监控目标,配置时要确认这个方向的可达性和端口放通。
项目 | 最低配置 | 建议配置 |
|---|---|---|
CPU | 2 核 | 2~4 核 |
内存 | 2 GB | 4 GB 及以上 |
磁盘 | 40 GB | 100 GB 以上 |
磁盘是这里需要认真估算的项。Prometheus 把所有采集到的指标按时间序列存储,占用与监控目标数量、指标数量和保留时长成正比。
粗略估算方式:每个时间序列每天约产生几 MB 数据。监控十几台机器时,默认配置下一个月的数据通常在几 GB 到几十 GB 之间。实际用量差异较大,建议先按较大值规划,运行一段时间后根据实际增长调整保留策略。
需要放通的端口:
端口 | 协议 | 用途 |
|---|---|---|
22 | TCP | SSH 登录(默认已放通) |
80 / 443 | TCP | 通过反向代理访问面板 |
9100 | TCP | 节点指标接口,仅对监控服务器放通 |
9100 这类指标端口的放通范围要特别注意。指标接口会暴露主机名、磁盘挂载点、进程信息等内部细节,对公网开放等于泄露基础设施信息。这些端口只应对 Prometheus 所在的机器或内网网段放通。轻量应用服务器在实例详情页的「防火墙」页签添加规则时可指定来源;云服务器 CVM 在安全组入站规则中同样支持按网段限定。
mkdir -p ~/apps/monitor && cd ~/apps/monitor
mkdir -p prometheus grafana alertmanager编写 compose.yaml:
services:
prometheus:
image: prom/prometheus:v3.0.1
ports:
- "127.0.0.1:9090:9090"
volumes:
- ./prometheus:/etc/prometheus
- prom-data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--storage.tsdb.retention.time=30d'
- '--web.enable-lifecycle'
restart: unless-stopped
alertmanager:
image: prom/alertmanager:v0.28.0
ports:
- "127.0.0.1:9093:9093"
volumes:
- ./alertmanager:/etc/alertmanager
restart: unless-stopped
grafana:
image: grafana/grafana:11.4.0
ports:
- "127.0.0.1:3000:3000"
volumes:
- grafana-data:/var/lib/grafana
environment:
GF_SECURITY_ADMIN_PASSWORD: 替换为强密码
GF_USERS_ALLOW_SIGN_UP: "false"
GF_SERVER_ROOT_URL: https://monitor.example.com
TZ: Asia/Shanghai
restart: unless-stopped
node-exporter:
image: prom/node-exporter:v1.8.2
ports:
- "9100:9100"
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.sysfs=/host/sys'
- '--path.rootfs=/rootfs'
restart: unless-stopped
cadvisor:
image: gcr.io/cadvisor/cadvisor:v0.49.1
ports:
- "127.0.0.1:8080:8080"
volumes:
- /:/rootfs:ro
- /var/run:/var/run:ro
- /sys:/sys:ro
- /var/lib/docker/:/var/lib/docker:ro
restart: unless-stopped
volumes:
prom-data:
grafana-data:几处配置的说明:
retention.time=30d 设置数据保留 30 天。这个值直接影响磁盘占用,按实际需求和磁盘容量调整。GF_USERS_ALLOW_SIGN_UP: "false" 关闭 Grafana 的开放注册,避免任何人都能创建账号。127.0.0.1,通过反向代理访问。node-exporter 需要被 Prometheus 从其他机器访问,所以对外监听,但要用防火墙限制来源。编写 Prometheus 配置 prometheus/prometheus.yml:
global:
scrape_interval: 30s
evaluation_interval: 30s
alerting:
alertmanagers:
- static_configs:
- targets: ['alertmanager:9093']
rule_files:
- '/etc/prometheus/rules/*.yml'
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node'
static_configs:
- targets:
- 'node-exporter:9100'
- '10.0.1.20:9100'
- '10.0.1.21:9100'
labels:
env: 'prod'
- job_name: 'containers'
static_configs:
- targets: ['cadvisor:8080']scrape_interval 决定采集频率。30 秒对多数场景够用,缩短能提高精度但会增加存储和负载。
其他被监控机器只需部署 node-exporter,然后把它们的地址加入 targets 列表。
启动服务:
docker compose up -d
docker compose ps创建规则目录和文件:
mkdir -p prometheus/rules
nano prometheus/rules/basic.yml写入基础告警规则:
groups:
- name: node-basic
rules:
- alert: 实例不可达
expr: up{job="node"} == 0
for: 3m
labels:
severity: critical
annotations:
summary: "{{ $labels.instance }} 已失联"
description: "目标已持续 3 分钟无法采集"
- alert: CPU 使用率过高
expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 85
for: 10m
labels:
severity: warning
annotations:
summary: "{{ $labels.instance }} CPU 使用率偏高"
description: "当前值 {{ $value | printf \"%.1f\" }}%,已持续 10 分钟"
- alert: 内存可用率过低
expr: node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes * 100 < 15
for: 10m
labels:
severity: warning
annotations:
summary: "{{ $labels.instance }} 可用内存不足"
description: "可用内存仅剩 {{ $value | printf \"%.1f\" }}%"
- alert: 磁盘空间不足
expr: node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"} / node_filesystem_size_bytes{fstype!~"tmpfs|overlay"} * 100 < 15
for: 15m
labels:
severity: warning
annotations:
summary: "{{ $labels.instance }} 磁盘空间不足"
description: "挂载点 {{ $labels.mountpoint }} 剩余 {{ $value | printf \"%.1f\" }}%"
- alert: 磁盘将在数天内写满
expr: predict_linear(node_filesystem_avail_bytes{fstype!~"tmpfs|overlay"}[6h], 4*24*3600) < 0
for: 30m
labels:
severity: warning
annotations:
summary: "{{ $labels.instance }} 磁盘预计将写满"
description: "按当前增长趋势,挂载点 {{ $labels.mountpoint }} 预计 4 天内写满"几个设计要点:
for 字段避免误报。 它要求条件持续满足指定时长才触发告警。没有这个约束,一次短暂的 CPU 尖峰就会发一条告警,很快就会让人对告警脱敏。
阈值要留出处置时间。 磁盘告警设在剩余 15% 而不是 5%,是为了留出处理窗口。等到只剩 5% 时往往已经开始影响业务了。
趋势预测比静态阈值更有价值。 最后一条规则基于增长趋势预测磁盘写满时间,能在还有充足空间时就发出提醒。这类规则对容量规划很实用。
过滤掉临时文件系统。 不加 fstype 过滤会对容器的临时挂载点产生大量无意义告警。
配置 Alertmanager alertmanager/alertmanager.yml:
global:
resolve_timeout: 5m
route:
receiver: 'default'
group_by: ['alertname', 'instance']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
routes:
- matchers:
- severity = "critical"
receiver: 'urgent'
repeat_interval: 1h
receivers:
- name: 'default'
webhook_configs:
- url: 'https://你的通知接收地址'
send_resolved: true
- name: 'urgent'
webhook_configs:
- url: 'https://你的紧急通知接收地址'
send_resolved: truegroup_by 把同类告警合并成一条通知,避免十台机器同时告警时收到十条消息。repeat_interval 控制未恢复告警的重复提醒间隔,设太短会造成骚扰,设太长可能忘记处理。
重载配置:
curl -X POST http://127.0.0.1:9090/-/reload
docker compose restart alertmanager先配好反向代理访问:
monitor.example.com {
reverse_proxy 127.0.0.1:3000
}访问域名并用配置的管理员密码登录。
添加数据源:进入连接设置,添加 Prometheus 类型的数据源,地址填 http://prometheus:9090(容器间通过服务名通信)。保存并测试,显示连接成功即可。
导入现成面板:社区提供了大量成熟的面板模板。在面板导入页面输入模板编号即可导入。常用的有节点资源总览、容器资源监控等类型。导入后选择刚配置的数据源。
导入的面板通常需要微调。指标名称在不同 Exporter 版本间可能有差异,如果某些图表显示无数据,检查该图表使用的查询语句中的指标名是否与实际采集到的一致。
验证指标名是否存在:在 Prometheus 界面的查询框输入指标名,看是否有返回。这比在 Grafana 里猜测更直接。
监控系统本身失效是很危险的——你会以为一切正常。逐项验证。
采集目标全部健康
访问 Prometheus 的目标页面(通过反向代理或 SSH 转发),确认所有目标状态为 UP。有目标显示 DOWN 时,页面会给出错误原因。
也可以用接口查询:
curl -s http://127.0.0.1:9090/api/v1/targets | grep -o '"health":"[^"]*"' | sort | uniq -c指标能查到数据
在 Prometheus 查询框执行:
up
node_memory_MemAvailable_bytes应返回各实例的数据点。
Grafana 面板有数据:打开导入的面板,确认图表正常渲染而不是显示无数据。
告警规则已加载:在 Prometheus 的规则页面确认所有规则都已加载且无语法错误。
告警能真实触发并送达。这一项最关键,必须主动测试而不是等真实故障。方法是临时构造一个必然满足的条件:
- alert: 告警链路测试
expr: up{job="node"} == 1
for: 1m
labels:
severity: warning
annotations:
summary: "这是一条测试告警"加入规则后重载,等待触发并确认收到了通知。验证完立即删除这条规则。
没有做过这一步验证的监控系统,等于不知道告警到底能不能送达。很多人是在真实故障发生后才发现通知配置有误。
恢复通知也要验证:删除测试规则后,确认收到了告警恢复的通知。只有触发没有恢复通知,会让人不清楚问题是否已解决。
目标显示为 DOWN
按顺序检查:目标机器上的 Exporter 是否运行;9100 端口是否对 Prometheus 所在机器放通;目标地址填写是否正确。从 Prometheus 所在机器实测:
docker compose exec prometheus wget -qO- http://10.0.1.20:9100/metrics | head -5能返回指标内容说明网络通,问题在配置;不通则是网络或防火墙问题。
Grafana 面板显示无数据
先在 Prometheus 中验证该指标是否存在。存在但面板无数据,检查面板的数据源选择和时间范围;指标不存在则是 Exporter 版本差异导致指标名变化,需要调整查询语句。
告警不触发
检查规则是否已加载、表达式在 Prometheus 中执行是否返回结果、for 时长是否已满足。可以在查询框直接运行告警表达式验证。
告警触发但收不到通知
查看 Alertmanager 日志:
docker compose logs alertmanager --tail 50常见原因是通知地址配置错误或目标服务拒绝请求。
告警太多形成噪音
这是监控系统最常见的失败模式——告警多到没人看。处理思路:提高阈值到真正需要干预的水平;延长 for 时长过滤瞬时波动;用 group_by 合并同类;区分严重级别,只让真正紧急的走即时通知渠道。
能触发但不知道该怎么处理的告警,应该删掉或降级。 每条告警都应该对应一个明确的处置动作。
磁盘占用增长快
docker compose exec prometheus du -sh /prometheus
df -h处理方式:缩短数据保留时长;减少采集频率;减少不需要的指标采集。如果确实需要长期保留,考虑配置远程存储把历史数据归档出去。
内存占用高
Prometheus 的内存占用与活跃时间序列数量相关。监控目标或指标维度过多时会明显上升。检查是否有高基数标签(例如把请求 ID 作为标签),这类标签会产生大量时间序列。
备份要点
内容 | 说明 |
|---|---|
Prometheus 配置与规则 | 采集配置和告警规则,是核心配置资产 |
Grafana 数据卷 | 面板定义、数据源配置、用户账号 |
指标数据 | 历史监控数据,可按需决定是否备份 |
配置文件建议纳入版本管理,改动有记录可追溯。Grafana 的面板也可以导出为 JSON 文件保存。
指标数据是否备份取决于是否需要长期趋势分析。多数场景下丢失历史指标的影响有限,配置反而更重要。
变更前创建快照:升级组件版本前给实例创建快照。回滚会把整块系统盘恢复到快照时间点,之后写入的数据会被清除,运行中的实例会自动关机。使用存储型套餐的实例不支持创建快照。
访问控制
日常检查
监控系统自身也需要被监控
这是个容易被忽略的问题:如果 Prometheus 挂了,谁来告警?简单的做法是配置一个外部的可用性检查,定期访问监控服务的健康接口,异常时通过独立渠道通知。至少要保证监控失效时你能知道。
监控搭起来之后,如果需要把日志也纳入统一观测,或为关键业务接口配置更细粒度的可用性监控,可以作为下一步方向。
监控服务需要持续运行且对磁盘容量有一定要求,云服务器 CVM 的规格可按需调整;指标数据增长后可使用云硬盘扩容,历史数据归档可使用对象存储 COS。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。