在云原生时代,监控与可观测性(Observability)已经成为后端工程师和运维人员的必备技能。传统的监控方案往往只关注服务器的 CPU、内存等基础指标,但在微服务架构和容器化部署日益普及的今天,我们需要一套更完整的可观测性体系来应对复杂的系统环境。
本文将带你从零搭建一套基于 Prometheus + Grafana + Loki 的现代监控体系,涵盖指标收集、可视化展示、日志聚合和告警配置,并分享生产环境部署的最佳实践。
一、可观测性的三大支柱
在深入技术实现之前,我们先理解可观测性的核心概念。现代可观测性体系通常包含三大支柱:
| 支柱 | 工具 | 解决的问题 |
|---|---|---|
| Metrics(指标) | Prometheus | 系统性能趋势、异常检测 |
| Logs(日志) | Loki / ELK | 事故根因分析、审计追踪 |
| Traces(链路追踪) | Jaeger / Tempo | 请求链路分析、性能瓶颈定位 |
本文将重点覆盖 Metrics 和 Logs 两大支柱,它们也是日常运维中最常用的两部分。链路追踪我们会在后续文章中单独讨论。
二、Prometheus:指标收集与存储
Prometheus 是目前最流行的开源监控系统,它采用 Pull 模式从目标服务拉取指标数据,并内置了强大的时序数据库。它的核心优势在于:多维数据模型(基于标签)、灵活的 PromQL 查询语言,以及强大的告警能力。
2.1 安装 Prometheus
我们使用 Docker Compose 来部署整套监控栈,这是最快捷也最易于维护的方式。首先创建项目目录结构:
1
2 mkdir -p /opt/monitoring/{prometheus,grafana,loki,promtail}
cd /opt/monitoring
创建 docker-compose.yml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 version: '3.8'
services:
prometheus:
image: prom/prometheus:v2.50.1
container_name: prometheus
volumes:
- ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus_data:/prometheus
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--storage.tsdb.path=/prometheus'
- '--storage.tsdb.retention.time=30d'
- '--web.console.libraries=/etc/prometheus/console_libraries'
- '--web.console.templates=/etc/prometheus/consoles'
- '--web.enable-lifecycle'
ports:
- '9090:9090'
restart: unless-stopped
volumes:
prometheus_data:
2.2 Prometheus 配置文件详解
创建 prometheus/prometheus.yml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_timeout: 10s
alerting:
alertmanagers:
- static_configs:
- targets:
- alertmanager:9093
rule_files:
- 'rules/*.yml'
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node_exporter'
static_configs:
- targets: ['node_exporter:9100']
- job_name: 'cadvisor'
static_configs:
- targets: ['cadvisor:8080']
这里我们配置了三个抓取目标:Prometheus 自身、Node Exporter(服务器指标)、cAdvisor(容器指标)。scrape_interval: 15s 表示每15秒采集一次数据,retention.time=30d 表示数据保留30天。
2.3 PromQL 实战查询
PromQL 是 Prometheus 的查询语言,掌握它才能真正用好监控数据。以下是一些常用的查询示例:
CPU 使用率:
1 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
内存使用率:
1 (1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100
磁盘使用率:
1 (node_filesystem_size_bytes{fstype!="tmpfs"} - node_filesystem_free_bytes{fstype!="tmpfs"}) / node_filesystem_size_bytes{fstype!="tmpfs"} * 100
HTTP 请求错误率:
1 rate(http_requests_total{status=~"5.."}[5m])
这些查询表达式可以直接在 Grafana 面板中使用,也可以用于配置告警规则。
三、Grafana:数据可视化与告警
Grafana 是目前最流行的开源数据可视化平台,它支持 Prometheus、Loki、Elasticsearch、InfluxDB 等数十种数据源。我们用它来创建监控仪表盘和配置告警规则。
3.1 部署 Grafana
在 docker-compose.yml 中添加 Grafana 服务:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 grafana:
image: grafana/grafana:10.4.1
container_name: grafana
volumes:
- grafana_data:/var/lib/grafana
- ./grafana/provisioning:/etc/grafana/provisioning
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=Chang3Th!sPwd
- GF_INSTALL_PLUGINS=grafana-piechart-panel
ports:
- '3000:3000'
restart: unless-stopped
volumes:
grafana_data:
Grafana 支持 Provisioning 机制,可以在启动时自动配置数据源和仪表盘,无需手动操作。创建 grafana/provisioning/datasources/prometheus.yml:
1
2
3
4
5
6
7
8
9 apiVersion: 1
datasources:
- name: Prometheus
type: prometheus
access: proxy
url: http://prometheus:9090
isDefault: true
editable: false
3.2 创建高效的仪表盘
一个优秀的监控仪表盘应该遵循黄金信号原则——即 Google SRE 提出的四个关键指标:
- 延迟(Latency):请求处理时间,关注 P50、P95、P99 分位数
- 流量(Traffic):每秒请求数(RPS)、网络吞吐量
- 错误(Errors):错误率、HTTP 5xx 比例
- 饱和度(Saturation):CPU、内存、磁盘、连接数使用率
我们可以通过 Grafana 的变量功能实现动态切换:
1
2 # 定义变量 $instance,查询所有可用的实例标签
label_values(up, instance)
然后在面板中使用 $instance 变量,即可实现切换查看不同服务器的指标。
3.3 配置告警规则
告警是可观测性体系中至关重要的一环。Grafana 内置了强大的告警引擎,支持多种通知渠道:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 # Grafana 告警规则示例(通过 API 或 UI 配置)
apiVersion: 1
groups:
- name: server_alerts
interval: 30s
rules:
- alert: HighCPUUsage
expr: 100 - (avg by(instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100) > 80
for: 5m
labels:
severity: warning
annotations:
summary: "{{ $labels.instance }} CPU 使用率超过 80%"
description: "当前 CPU 使用率: {{ $value | humanizePercentage }}"
- alert: DiskSpaceLow
expr: (node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) < 0.1
for: 2m
labels:
severity: critical
annotations:
summary: "{{ $labels.instance }} 磁盘空间不足"
description: "可用磁盘空间小于 10%"
告警通知渠道可以配置为钉钉、企业微信、Slack、邮件等。这里以钉钉为例:
1
2
3 # 在 Grafana 中配置钉钉通知
# 设置 -> 通知渠道 -> 添加 -> DingDing
# Webhook URL: https://oapi.dingtalk.com/robot/send?access_token=YOUR_TOKEN
需要注意的是,告警频率不宜过高,对于瞬时的抖动可以设置 for: 5m 来避免误报。
四、Loki:轻量级日志聚合
Loki 是 Grafana Labs 推出的日志聚合系统,灵感来自 Prometheus,采用相同的标签体系。与 ELK 相比,Loki 最大的优势在于:它不全文索引日志内容,而是只索引标签,因此存储成本更低,查询速度也更快。
4.1 部署 Loki
1
2
3
4
5
6
7
8
9
10 loki:
image: grafana/loki:2.9.4
container_name: loki
volumes:
- ./loki/loki-config.yml:/etc/loki/loki-config.yml
- loki_data:/loki
ports:
- '3100:3100'
command: -config.file=/etc/loki/loki-config.yml
restart: unless-stopped
创建 loki/loki-config.yml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 auth_enabled: false
server:
http_listen_port: 3100
common:
path_prefix: /loki
storage:
filesystem:
chunks_directory: /loki/chunks
rules_directory: /loki/rules
replication_factor: 1
schema_config:
configs:
- from: 2024-01-01
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
4.2 Promtail:日志采集器
Promtail 是 Loki 官方的日志采集代理,负责从各个节点收集日志并发送到 Loki:
1
2
3
4
5
6
7
8
9
10
11 promtail:
image: grafana/promtail:2.9.4
container_name: promtail
volumes:
- ./promtail/promtail-config.yml:/etc/promtail/promtail-config.yml
- /var/log:/var/log
- /var/lib/docker/containers:/var/lib/docker/containers:ro
command: -config.file=/etc/promtail/promtail-config.yml
restart: unless-stopped
depends_on:
- loki
创建 promtail/promtail-config.yml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
scrape_configs:
- job_name: system
static_configs:
- targets:
- localhost
labels:
job: varlogs
__path__: /var/log/*.log
- job_name: containers
pipeline_stages:
- docker: {}
static_configs:
- targets:
- localhost
labels:
job: docker
__path__: /var/lib/docker/containers/*/*-json.log
这里配置了两个采集任务:系统日志(/var/log/*.log)和容器日志(Docker JSON 日志)。每个日志条目都会自动带上 job 标签,方便在 Grafana 中筛选。
4.3 LogQL 日志查询
LogQL 是 Loki 的查询语言,语法与 PromQL 类似。以下是一些常用查询:
查询 Nginx 错误日志:
1 {job="varlogs", filename="/var/log/nginx/error.log"} |= "error"
查询特定容器的日志:
1 {job="docker", container="my-app"} |= "ERROR" | json | line_format "{{.message}}"
统计错误率:
1 rate({job="docker", container="api-server"} |= "HTTP 5" [5m])
Grafana 的 Explore 面板是调试日志的最佳工具,可以实时查看和过滤日志流。
五、Node Exporter + cAdvisor:全面采集服务器指标
仅有 Prometheus 还不够,我们需要额外的采集器来获取服务器和容器的详细指标。
5.1 Node Exporter
Node Exporter 是 Prometheus 官方的服务器指标采集器,可以收集 CPU、内存、磁盘、网络等上百种指标:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 node_exporter:
image: prom/node-exporter:v1.7.0
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
5.2 cAdvisor
cAdvisor 是 Google 开源的容器监控工具,可以采集每个容器的资源使用情况:
1
2
3
4
5
6
7
8
9
10
11
12 cadvisor:
image: gcr.io/cadvisor/cadvisor:v0.49.1
container_name: cadvisor
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'
restart: unless-stopped
部署完成后,访问 http://服务器IP:9100/metrics 和 http://服务器IP:8080/metrics 即可看到采集到的原始指标数据。
六、生产环境部署最佳实践
经过前面的步骤,我们已经搭建了一套完整的监控体系。但在生产环境中,还需要注意以下几点:
6.1 数据持久化与备份
Prometheus 和 Loki 的数据都存储在 Docker 卷中,建议定期备份:
1
2
3
4
5
6
7 # 备份 Prometheus 数据
# 可以使用 Prometheus 的快照 API 实现热备份
curl -XPOST http://localhost:9090/api/v1/admin/tsdb/snapshot
# 备份 Loki 数据
# 直接备份 /loki/chunks 和 /loki/index 目录
tar czf loki_backup_$(date +%Y%m%d).tar.gz /var/lib/docker/volumes/monitoring_loki_data/_data
6.2 高可用部署
对于关键业务系统,建议部署高可用架构:
- Prometheus 高可用:部署两个 Prometheus 实例,使用相同的抓取配置,配合 Thanos 实现全局视图
- Grafana 高可用:使用共享数据库(MySQL/PostgreSQL)存储配置,多实例部署
- Loki 高可用:使用对象存储(S3/MinIO)作为后端存储,部署多个 Loki 微服务组件
6.3 资源限制与性能调优
1
2
3
4
5
6
7
8
9
10
11 # 限制 Prometheus 内存使用
--storage.tsdb.retention.time=30d # 保留30天
--storage.tsdb.retention.size=50GB # 最大50GB
# Loki 性能优化
# 在 loki-config.yml 中配置
chunk_target_size: 1536000 # 1.5MB
max_chunk_age: 2h
# 限制 Grafana 日志级别
GF_LOG_LEVEL=warn
6.4 安全加固
监控系统本身不能成为安全短板:
- 为 Grafana 配置 HTTPS 和反向代理(Nginx)
- 使用强密码,开启 Grafana 的 OAuth 或 LDAP 认证
- Prometheus 和 Loki 的管理接口不要暴露在公网
- 使用 Prometheus 的 Basic Auth 或 OAuth2 保护抓取端点和查询接口
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 # Nginx 反向代理 Grafana 示例
server {
listen 443 ssl;
server_name monitor.example.com;
ssl_certificate /etc/nginx/ssl/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
七、总结与下一步
本文从零搭建了一套完整的可观测性体系,涵盖了 Prometheus 指标收集、Grafana 可视化与告警、Loki 日志聚合三大核心组件。这套方案完全开源、社区活跃、生态丰富,适合中小型团队快速落地。
下一步可以探索的方向:
- 链路追踪:接入 Jaeger 或 Grafana Tempo,实现分布式请求追踪
- 告警收敛:使用 Alertmanager 的抑制和分组功能,减少告警噪音
- 自定义 Exporter:为业务指标编写自定义 Prometheus Exporter
- Thanos 集群:实现跨集群的全局监控视图和长期存储
- Kubernetes 集成:使用 kube-prometheus-stack Helm Chart 在 K8s 中一键部署
如果你在搭建过程中遇到任何问题,欢迎在评论区留言交流。监控体系的建设是一个持续优化的过程,希望本文能帮你迈出第一步。
汤不热吧