企业级服务器监控体系搭建指南:从 Prometheus 到全链路可观测性
引言
在现代 IT 基础设施中,服务器监控早已从”看 CPU 够不够用”的简单需求演进为涵盖指标(Metrics)、日志(Logging)、链路追踪(Tracing)三大支柱的全链路可观测性体系。据统计,超过 70% 的生产故障在监控系统正确配置的前提下可以在用户感知前被自动发现并恢复。本文将手把手带你从零搭建一套生产级服务器监控体系,涵盖开源方案选型、数据采集架构、告警策略设计及常见坑点。
核心概念
1. 监控的四层黄金指标(USE / RED 方法)
监控体系的设计应遵循两大方法论:
– USE 方法(资源视角):每个资源的 Utilization(利用率)、Saturation(饱和度)、Errors(错误率)
– RED 方法(服务视角):每个服务的 Rate(请求速率)、Errors(错误数)、Duration(响应时长)
2. 技术选型对比
| 组件 | 推荐方案 | 替代方案 | 适用场景 |
|---|---|---|---|
| 指标采集 | Prometheus + Node Exporter | Telegraf / Zabbix | 云原生 / 传统 IDC |
| 日志收集 | Loki + Promtail | ELK Stack / Graylog | Kubernetes / 轻量 |
| 链路追踪 | OpenTelemetry + Jaeger | SkyWalking / Zipkin | 微服务架构 |
| 告警引擎 | Alertmanager + Webhook | Grafana Alerting | 多通道通知 |
| 可视化 | Grafana | Chronograf / Netdata | 统一仪表盘 |
3. 架构总览
┌──────────────────────────────────────────────────────────┐
│ 告警通道 (钉钉/飞书/邮件) │
└────────────────────────▲─────────────────────────────────┘
│
┌────────────────────────┴─────────────────────────────────┐
│ Alertmanager │
│ (去重/分组/静默/抑制) │
└────▲─────────────────────▲────────────────────▲──────────┘
│ │ │
┌────┴──────┐ ┌────────┴────────┐ ┌───────┴────────┐
│Prometheus │ │ Prometheus │ │ Prometheus │
│ (主节点) │ │ (机房A) │ │ (机房B) │
└───▲──▲──▲─┘ └───▲──▲──▲──────┘ └───▲──▲──▲──────┘
│ │ │ │ │ │ │ │ │
Node│cAdvisor Node│cAdvisor Node│cAdvisor
Exporter│ Exporter│ Exporter│
实战步骤
步骤 1:安装 Prometheus + Node Exporter
使用 Docker Compose 一键部署核心监控栈:
version: '3.8'
services:
prometheus:
image: prom/prometheus:v2.53.0
container_name: prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus
ports:
- "9090:9090"
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.retention.time=30d'
restart: unless-stopped
node_exporter:
image: prom/node-exporter:v1.8.2
container_name: node_exporter
volumes:
- /proc:/host/proc:ro
- /sys:/host/sys:ro
- /:/rootfs:ro
command:
- '--path.procfs=/host/proc'
- '--path.sysfs=/host/sys'
- '--path.rootfs=/rootfs'
- '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
ports:
- "9100:9100"
restart: unless-stopped
grafana:
image: grafana/grafana:11.1.0
container_name: grafana
environment:
- GF_SECURITY_ADMIN_PASSWORD=your_secure_password
- GF_INSTALL_PLUGINS=grafana-piechart-panel
volumes:
- grafana-data:/var/lib/grafana
ports:
- "3000:3000"
restart: unless-stopped
volumes:
prometheus-data:
grafana-data:
步骤 2:配置 Prometheus 抓取目标
# prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_timeout: 10s
# 告警规则文件
rule_files:
- "alerts/*.yml"
scrape_configs:
# 自监控
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
# 主机指标
- job_name: 'node_exporter'
static_configs:
- targets:
- '192.168.1.10:9100' # 主服务器
- '192.168.1.11:9100' # 应用服务器
- '192.168.1.12:9100' # 数据库服务器
# Docker 容器指标
- job_name: 'cadvisor'
static_configs:
- targets: ['cadvisor:8080']
# Kubernetes 集群(使用 kube-state-metrics)
- job_name: 'kubernetes-pods'
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true
步骤 3:编写告警规则
# alerts/host_alerts.yml
groups:
- name: host_alerts
interval: 30s
rules:
# CPU 使用率超过 90% 持续 5 分钟
- alert: HighCpuUsage
expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 90
for: 5m
labels:
severity: warning
annotations:
summary: "{{ $labels.instance }} CPU 使用率过高"
description: "CPU 已使用 {{ $value | humanizePercentage }} 持续超过 5 分钟"
# 磁盘空间低于 10%
- alert: DiskSpaceLow
expr: (node_filesystem_avail_bytes{mountpoint="/", fstype!~"tmpfs|overlay"} /
node_filesystem_size_bytes{mountpoint="/", fstype!~"tmpfs|overlay"}) * 100 < 10
for: 2m
labels:
severity: critical
annotations:
summary: "{{ $labels.instance }} 磁盘空间不足"
description: "{{ $labels.mountpoint }} 剩余 {{ $value | humanizePercentage }}"
# 内存使用率超过 90%
- alert: HighMemoryUsage
expr: (1 - (node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes)) * 100 > 90
for: 5m
labels:
severity: warning
annotations:
summary: "{{ $labels.instance }} 内存使用率过高"
description: "内存使用率 {{ $value | humanizePercentage }}"
# 实例离线
- alert: InstanceDown
expr: up == 0
for: 1m
labels:
severity: critical
annotations:
summary: "实例 {{ $labels.instance }} 已离线"
description: "实例 {{ $labels.instance }} (job={{ $labels.job }}) 已离线超过 1 分钟"
步骤 4:配置 Alertmanager 对接飞书/钉钉通知
# alertmanager.yml
global:
resolve_timeout: 5m
# 飞书 Webhook(企业版)
# 也可替换为钉钉 / Slack / Telegram
route:
receiver: 'feishu-critical'
group_by: ['alertname', 'cluster']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
routes:
- receiver: 'feishu-critical'
match:
severity: critical
repeat_interval: 1h
- receiver: 'feishu-warning'
match:
severity: warning
repeat_interval: 4h
receivers:
- name: 'feishu-critical'
webhook_configs:
- url: 'https://open.feishu.cn/open-apis/bot/v2/hook/your-webhook-id'
send_resolved: true
http_config:
headers:
Content-Type: application/json
- name: 'feishu-warning'
webhook_configs:
- url: 'https://open.feishu.cn/open-apis/bot/v2/hook/your-webhook-id'
send_resolved: true
步骤 5:Python 脚本实现服务器健康检查自愈
当告警触发时,可以通过 Webhook 接收器联动自动化修复脚本:
#!/usr/bin/env python3
"""服务器健康检查与自动修复脚本"""
import json
import subprocess
import logging
from datetime import datetime
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
filename='/var/log/self_healing.log'
)
logger = logging.getLogger(__name__)
def check_disk_usage(path="/"):
"""检查磁盘使用率"""
result = subprocess.run(
["df", "-h", path], capture_output=True, text=True
)
lines = result.stdout.strip().split("n")
if len(lines) < 2:
return None
usage = lines[1].split()[4].replace("%", "")
return int(usage)
def clean_docker_logs():
"""清理 Docker 容器日志(最常见的磁盘杀手)"""
logger.info("开始清理 Docker 容器日志...")
# 清理所有容器的日志文件
subprocess.run(
["sh", "-c", "truncate -s 0 /var/lib/docker/containers/*/*.log"],
capture_output=True
)
logger.info("Docker 日志清理完成")
def restart_unhealthy_containers():
"""重启状态异常的 Docker 容器"""
result = subprocess.run(
["docker", "ps", "--filter", "status=unhealthy", "--format", "{{.Names}}"],
capture_output=True, text=True
)
unhealthy = result.stdout.strip().split("n")
for container in unhealthy:
if container:
logger.warning(f"重启异常容器: {container}")
subprocess.run(["docker", "restart", container])
def main():
logger.info(f"=== 定期健康检查开始: {datetime.now()} ===")
# 1. 磁盘检查
disk_usage = check_disk_usage("/")
if disk_usage and disk_usage > 85:
logger.warning(f"磁盘使用率 {disk_usage}%,触发自动清理")
clean_docker_logs()
# 2. 容器健康检查
restart_unhealthy_containers()
logger.info(f"=== 健康检查结束: {datetime.now()} ===")
if __name__ == "__main__":
main()
步骤 6:配置 crontab 定期执行
# 每 5 分钟执行一次健康检查自愈脚本
*/5 * * * * /usr/bin/python3 /opt/monitoring/self_heal.py
# 每 30 分钟检查 Prometheus 和 Node Exporter 进程
*/30 * * * * /usr/bin/pgrep prometheus > /dev/null || docker restart prometheus
*/30 * * * * /usr/bin/pgrep node_exporter > /dev/null || docker restart node_exporter
# 每天凌晨 3 点清理超过 30 天的 Prometheus TSDB 数据块
0 3 * * * /usr/bin/docker exec prometheus sh -c 'find /prometheus -name "*.db" -mtime +30 -delete'
步骤 7:搭建 Grafana 统一仪表盘
通过 Grafana 的 Provisioning 功能实现仪表盘声明式部署:
# grafana/dashboards/server-monitoring.json (片段)
{
"title": "服务器监控总览",
"panels": [
{
"title": "CPU 使用率 (按核心)",
"type": "graph",
"targets": [{
"expr": "100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)",
"legendFormat": "{{ instance }}"
}]
},
{
"title": "内存使用量 / 总量",
"type": "graph",
"targets": [{
"expr": "node_memory_MemTotal_bytes - node_memory_MemAvailable_bytes",
"legendFormat": "Used"
}, {
"expr": "node_memory_MemTotal_bytes",
"legendFormat": "Total"
}]
},
{
"title": "磁盘 IO 等待时间",
"type": "heatmap",
"targets": [{
"expr": "rate(node_disk_io_time_seconds_total[5m])"
}]
},
{
"title": "TCP 连接状态分布",
"type": "stat",
"targets": [{
"expr": "node_netstat_Tcp_CurrEstab"
}]
}
]
}
常见问题
Q1:Prometheus 数据量太大,磁盘占用暴涨怎么办?
解决方案:
1. 调整 --storage.tsdb.retention.time 缩短保留周期(默认 15d → 7d)
2. 降低 scrape_interval (从 15s 改为 30s)
3. 使用远程存储如 Thanos 或 VictoriaMetrics 做分层存储
4. 开启 Prometheus 压缩:--storage.tsdb.retention.size=50GB 限制最大存储
Q2:Node Exporter 采集不到某些指标?
常见原因及排查:
# 检查端口是否正常
curl -s http://localhost:9100/metrics | head -20
# 某些指标(如 diskstats)需要宿主机 procfs 挂载
# 确保容器启动时正确挂载了 /proc 和 /sys
docker logs node_exporter 2>&1 | grep -i error
Q3:Alertmanager 告警重复轰炸怎么办?
分组与抑制策略:
– 通过 group_by: ['alertname'] 将同类告警聚合
– repeat_interval: 4h 避免同一告警反复触发
– 使用 inhibit_rules 配置抑制规则(如”节点宕机时抑制该节点其他告警”)
Q4:Grafana 图表显示断点或数据缺失?
排查步骤:
1. 检查 Prometheus UI 的 /targets 页面确定采集正常
2. 查看 Grafana 的 Query Inspector 中的原始数据时间戳
3. 确认 Prometheus 和数据源之间的时区一致
4. Grafana 中的 Min step 设置不要小于 scrape_interval
Q5:如何监控多机房分布式部署?
推荐架构:
– 每个机房部署独立的 Prometheus 实例,采集本地指标
– 使用 Thanos Sidecar 将数据上传到对象存储(S3/MinIO)
– 中央 Thanos Query 提供全局统一查询视图
– Alertmanager 采用 Gossip 协议多实例集群部署,避免单点
总结
一套生产级的服务器监控体系不仅仅是安装几个工具,而是需要从业务视角出发设计指标、告警和可观测性策略。本文从 Prometheus 生态出发,完整演示了从指标采集、告警配置、自动化自愈到可视化仪表盘的端到端搭建流程。
核心要点回顾:
1. 遵循 USE + RED 方法论设计监控指标,避免”监控了但没监控到”;
2. 使用 Alertmanager 的分组、抑制、静默三件套,告警要有”质量”而非数量;
3. 结合自动化自愈脚本,从”发现故障”进化到”修复故障”;
4. Grafana Provisioning 实现仪表盘版本管理和 IaC 部署。
监控体系的建设是一个持续迭代的过程——建议从一个核心机房的 CPU / 内存 / 磁盘三大件开始,逐步扩展到网络、应用层和业务指标。最终目标是:在用户发现问题之前,系统已经修复了它。















暂无评论内容