Prometheus/Grafana 监控体系深度部署:从指标采集到告警闭环的全链路实践
一、监控不是装个 Dashboard 就完事了:体系化思维的缺失
很多团队的监控建设路径是这样的:先装 Prometheus,再装 Grafana,导入几个社区 Dashboard,完事。等真正出故障时,发现 Dashboard 上的曲线虽然有了,但该告警的没告警,不该告警的狂告警,关键指标缺失,无法定位问题。
监控体系的核心不是工具,而是指标设计。指标是否覆盖了 SLI(服务等级指标),告警规则是否与 SLO(服务等级目标)对齐,Dashboard 是否能回答"服务是否健康"这个根本问题。如果指标设计不合理,再精美的 Dashboard 也只是摆设。
深度部署 Prometheus/Grafana,需要从指标设计、采集架构、存储策略、告警规则到可视化呈现,做系统化的规划。本文覆盖这些环节的关键决策和最佳实践。
二、监控体系的全链路架构
一个完整的监控体系,从指标产生到告警通知,经过五个核心环节。每个环节都有独立的设计考量。
graph TD subgraph 指标采集层 A1[应用埋点:RED 指标] A2[基础设施:USE 指标] A3[业务指标:SLI 指标] A4[ServiceMonitor 自动发现] end subgraph 存储与处理层 B1[Prometheus 本地存储] B2[远程写入 Thanos/Cortex] B3[降采样与长期存储] end subgraph 告警管理层 C1[Prometheus 告警规则] C2[Alertmanager 去重分组] C3[告警路由与静默] end subgraph 可视化层 D1[Grafana Dashboard] D2[SLI/SLO 仪表盘] D3[容量规划看板] end subgraph 反馈闭环 E1[告警触发] E2[Dashboard 确认] E3[规则调优] end A1 --> B1 A2 --> B1 A3 --> B1 A4 --> B1 B1 --> B2 B2 --> B3 B1 --> C1 C1 --> C2 C2 --> C3 B1 --> D1 D1 --> E2 C3 --> E1 E1 --> E3 E2 --> E3 style A1 fill:#e1f5fe style C2 fill:#fff3e0 style D2 fill:#e8f5e9指标采集遵循两个经典方法论。应用层使用 RED 方法(Rate、Errors、Duration),覆盖请求速率、错误率和延迟三个维度。基础设施层使用 USE 方法(Utilization、Saturation、Errors),覆盖使用率、饱和度和错误率。两者结合,形成完整的监控视角。
存储策略需要平衡查询性能和存储成本。Prometheus 本地存储适合近期数据(15 天以内),查询延迟低。长期数据通过远程写入到 Thanos 或 Cortex,支持降采样和对象存储,成本可控。
告警管理的核心是降噪。Alertmanager 的分组(group_by)、抑制(inhibit_rules)和静默(silences)三大机制,将原始告警转化为可操作的通知。
三、生产级配置:Prometheus/Grafana 全链路部署
以下配置覆盖了指标采集、告警规则、Alertmanager 降噪和 Grafana Dashboard 的完整链路。
# prometheus-values.yaml # Prometheus Helm Chart 生产级配置 # 核心决策:资源限制、存储保留期、远程写入、告警规则 # Prometheus Server 配置 prometheus: prometheusSpec: # 资源限制:根据集群规模调整 # 每百万时间序列约需 1GB 内存 resources: requests: cpu: "2" memory: 8Gi limits: cpu: "4" memory: 16Gi # 本地存储保留期:15 天,覆盖两个完整的业务周期 # 超过 15 天的数据通过远程写入到 Thanos retention: 15d # 存储卷配置:使用 SSD,保证写入性能 storageSpec: volumeClaimTemplate: spec: storageClassName: ssd accessModes: ["ReadWriteOnce"] resources: requests: storage: 100Gi # 远程写入配置:将数据同步到 Thanos 实现长期存储 # 写入队列大小和批次需要根据网络延迟调整 remoteWrite: - url: http://thanos-receive:19291/api/v1/receive queueConfig: maxSamplesPerSend: 10000 maxShards: 10 # 写入超时设为 30 秒,避免慢写入阻塞采集 sendTimeout: 30s # ServiceMonitor 自动发现:自动采集带特定注解的 Service additionalServiceMonitors: - name: application-metrics selector: matchLabels: monitoring: enabled # 应用只需打上此标签即可被监控 namespaceSelector: any: true endpoints: - port: metrics interval: 15s path: /metrics # Alertmanager 配置 alertmanager: alertmanagerSpec: resources: requests: cpu: 100m memory: 256Mi limits: cpu: 500m memory: 512Mi config: global: resolve_timeout: 5m # 路由树:根据告警标签决定分组和通知通道 route: receiver: "default" group_by: ["alertname", "namespace", "service"] # 分组等待时间:同一组告警等待 30 秒再发送, # 避免同一故障的多个告警逐条发送 group_wait: 30s # 组内间隔:同一组的新告警间隔 5 分钟再发送 group_interval: 5m # 重复间隔:同一告警 4 小时内不重复发送 repeat_interval: 4h routes: # Critical 级别走电话+短信 - match: severity: critical receiver: "critical-channel" group_wait: 10s repeat_interval: 1h # Warning 级别走 IM - match: severity: warning receiver: "warning-channel" # 抑制规则:高级别告警抑制低级别 inhibit_rules: - source_match: severity: critical target_match: severity: warning # 同一告警名和服务的 critical 告警抑制 warning equal: ["alertname", "namespace", "service"] receivers: - name: "default" webhook_configs: - url: http://alertmanager-webhook:8080/notify - name: "critical-channel" # 电话和短信通知(集成第三方服务) webhook_configs: - url: http://alertmanager-webhook:8080/critical - name: "warning-channel" # IM 通知 webhook_configs: - url: http://alertmanager-webhook:8080/warning# alerting-rules.yaml # Prometheus 告警规则定义 # 遵循 SLI 对齐原则:每条规则对应一个服务等级指标 groups: # ---- 可用性告警 ---- - name: availability-alerts rules: - alert: HighErrorRate expr: | ( sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) ) > 0.01 for: 5m labels: severity: critical category: availability annotations: summary: "服务 {{ $labels.service }} 错误率超过 1%" description: | 服务 {{ $labels.service }} 在过去 5 分钟内 5xx 错误率为 {{ $value | printf "%.2%%" }}, 超过 SLO 阈值 1%。 请检查最近的部署变更和下游依赖状态。 - alert: PodNotReady expr: | kube_pod_status_phase{phase!="Running"} == 1 for: 10m labels: severity: warning category: availability annotations: summary: "Pod {{ $labels.namespace }}/{{ $labels.pod }} 未就绪" description: | Pod 已超过 10 分钟未进入 Running 状态, 可能是镜像拉取失败、健康检查不通过或资源不足。 # ---- 延迟告警 ---- - name: latency-alerts rules: - alert: HighLatencyP99 expr: | histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le, service) ) > 3 for: 10m labels: severity: warning category: latency annotations: summary: "服务 {{ $labels.service }} P99 延迟超过 3 秒" description: | P99 延迟为 {{ $value | printf "%.1f" }} 秒, 超过 SLO 阈值 3 秒。 请检查慢查询日志和下游依赖响应时间。 # ---- 资源告警 ---- - name: resource-alerts rules: - alert: NodeMemoryPressure expr: | ( node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes ) < 0.1 for: 5m labels: severity: warning category: resource annotations: summary: "节点 {{ $labels.instance }} 可用内存不足 10%" description: | 节点可用内存仅剩 {{ $value | printf "%.1%%" }}, 可能触发 OOM Killer。请检查内存占用最高的 Pod。 - alert: PVCAlmostFull expr: | ( kubelet_volume_stats_used_bytes / kubelet_volume_stats_capacity_bytes ) > 0.85 for: 1h labels: severity: warning category: resource annotations: summary: "PVC {{ $labels.namespace }}/{{ $labels.persistentvolumeclaim }} 使用率超过 85%" description: | 存储卷使用率 {{ $value | printf "%.1%%" }}, 建议扩容或清理数据。// Grafana Dashboard JSON - SLI/SLO 概览仪表盘 // 核心设计:一个 Dashboard 回答"服务是否健康" { "dashboard": { "title": "SLI/SLO 服务健康概览", "tags": ["slo", "overview"], "panels": [ { "title": "错误率 (SLO: < 1%)", "type": "stat", "targets": [ { "expr": "sum(rate(http_requests_total{status=~\"5..\"}[5m])) / sum(rate(http_requests_total[5m]))", "legendFormat": "错误率" } ], "fieldConfig": { "defaults": { "thresholds": { "steps": [ { "value": 0, "color": "green" }, { "value": 0.005, "color": "yellow" }, { "value": 0.01, "color": "red" } ] }, "unit": "percentunit" } } }, { "title": "P99 延迟 (SLO: < 3s)", "type": "time_series", "targets": [ { "expr": "histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le, service))", "legendFormat": "{{ service }}" } ], "fieldConfig": { "defaults": { "thresholds": { "steps": [ { "value": 0, "color": "green" }, { "value": 1, "color": "yellow" }, { "value": 3, "color": "red" } ] }, "unit": "s" } } } ] } }配置设计说明:Prometheus 保留 15 天本地数据,超过部分远程写入 Thanos,兼顾查询性能和长期存储。告警规则按 SLI 维度组织(可用性、延迟、资源),每条规则包含 for 持续时间,避免瞬时波动触发告警。Alertmanager 的分组策略按 alertname+namespace+service 聚合,确保同一故障只产生一条通知。Grafana Dashboard 使用阈值着色,一眼可判断服务健康状态。
四、监控体系的架构权衡:性能、成本与覆盖率的三角
采集频率与存储成本。15 秒采集一次,指标量是 1 分钟采集的 4 倍,存储成本也翻 4 倍。但低频采集会丢失短时异常。生产环境建议核心指标 15 秒,普通指标 1 分钟,历史数据降采样到 5 分钟。
高可用与复杂度。Prometheus 本身不支持集群模式,单实例存在单点风险。Thanos 和 Cortex 提供了高可用方案,但引入了额外的组件和运维复杂度。小规模集群可以用两个 Prometheus 实例做双写,大规模集群再考虑 Thanos。
告警规则的 for 时间。for 时间太短,容易误报;太长,故障响应不及时。核心服务的 Critical 告警 for 设为 2-5 分钟,Warning 告警 for 设为 10-15 分钟。for 时间需要根据 MTTR 目标反推。
Dashboard 的信息密度。一个 Dashboard 放太多面板,信息过载;太少,需要频繁切换。建议按"概览→详情→排障"三层组织:概览页回答"是否健康",详情页展示指标趋势,排障页提供下钻链接。
五、总结
Prometheus/Grafana 监控体系的深度部署,核心在于指标设计与业务对齐。RED 方法覆盖应用层,USE 方法覆盖基础设施层,两者结合形成完整的监控视角。告警规则与 SLO 对齐,确保每条告警都有明确的业务含义。
存储策略需要平衡查询性能和成本,本地存储保近期、远程写入保长期。告警管理的关键是降噪,分组、抑制、静默三管齐下。Dashboard 按三层组织,从概览到排障逐层下钻。
监控体系的建设不是一次性工程,而是持续迭代的过程。随着业务发展,新的 SLI 需要补充,旧的告警规则需要调优。就像调整相机的参数一样,需要根据场景不断微调,才能拍出清晰的画面。