深色模式
Grafana 看板最佳实践:分层、模板变量与三信号关联
摘要:本文面向生产 SRE / 平台工程师,把 Grafana 看板从"一堆图"变成"事故时能用的工具"。覆盖三层看板模型(概览/服务/下钻)、模板变量避免硬编码、RED/USE 面板组织、dashboard JSON 进 Git、以及指标↔日志↔追踪的一键关联。适用 Kubernetes v1.28+,Grafana 10/11(dashboard JSON 结构随版本演进)。
适用版本与前提
- Kubernetes:v1.28+
- 组件:Grafana 10+(含 Loki/Tempo/Jaeger/Prometheus 数据源)、kube-prometheus-stack 自带 Grafana
- 前提:已在 Grafana 配好 Prometheus/Loki/Tempo 数据源;看板需由 Git/Terraform 管理
背景与问题
看板是大多数团队做可观测性的起点,也是终点——很多人建完一堆图就停了。结果是:没人维护、互相拷贝、事故时找不到该看哪个、环境名硬编码导致生产/staging 各一份且逐渐不同步。Grafana 官方把看板成熟度分低/中/高三档:低档是"人人能改、大量拷贝、无版本控制";高档是"分层、模板化、Git 化、与服务绑定"。
Grafana 官方两条铁律
- "USE tells you how happy your machines are, RED tells you how happy your users are." 告警应基于 RED(症状),USE 用于诊断。
- 一个看板 8–12 个 panel 为宜,多了就是"报表"不是"看板",每个 panel 必须能回答一个具体运维问题,否则不该存在。
核心概念:三层看板模型
不要把所有东西堆在一个看板上。按"值班时的认知路径"分层:
| 层级 | 受众 | 内容 | 回答 |
|---|---|---|---|
| L1 概览(fleet) | 值班/SRE | 集群健康、错误预算总览、红绿状态 | "现在系统整体健康吗?" |
| L2 服务(RED) | 服务 owner / oncall | Rate/Errors/Duration、饱和度、SLO | "我的服务是不是出问题了?" |
| L3 下钻(instance/debug) | 开发/SRE | 单 Pod、单端点、trace 关联、日志流 | "具体哪台、哪段、哪行?" |
架构与原理
Grafana 本身是"查询层",不存数据,连多个数据源(Prometheus/Loki/Tempo)。看板由 dashboard JSON 描述,含 templating(变量)、panels、annotations、links。关键能力:
- 模板变量(template variables):把环境/集群/服务/命名空间变成下拉,避免硬编码。一个看板适配所有环境。
- Data links / Derived fields:面板值或日志字段生成跳转 URL,实现信号关联。
- Exemplars:Prometheus 直方图开启后,Grafana 面板可直接从样本跳到 trace。
生产实践一:用模板变量消除硬编码
json
{
"templating": {
"list": [
{
"name": "cluster",
"type": "query",
"datasource": "Prometheus",
"query": "label_values(up, cluster)",
"current": { "text": "prod", "value": "prod" }
},
{
"name": "namespace",
"type": "query",
"datasource": "Prometheus",
"query": "label_values(kube_pod_info{cluster=\"$cluster\"}, namespace)",
"refresh": 2
},
{
"name": "service",
"type": "query",
"datasource": "Prometheus",
"query": "label_values(http_server_request_duration_seconds_count{namespace=\"$namespace\"}, service_name)"
}
]
}
}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
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
禁止硬编码环境名
env=production 写死在查询里,意味着 staging 要克隆一份、每个新区域再克隆——最终 N 份不同步。用 $cluster/$namespace 变量,一份看板走天下。这正是低成熟度看板的典型特征。
生产实践二:RED 面板组织(L2 服务看板)
同一服务用统一三 panel 组,套模板覆盖所有服务:
json
{
"panels": [
{
"title": "Rate (req/s)",
"type": "timeseries",
"targets": [
{ "expr": "sum(rate(http_server_request_duration_seconds_count{service_name=\"$service\"}[5m]))" }
]
},
{
"title": "Errors (ratio)",
"type": "timeseries",
"targets": [
{ "expr": "sum(rate(http_server_request_duration_seconds_count{service_name=\"$service\",http_response_status_code=~\"5..\"}[5m])) / sum(rate(http_server_request_duration_seconds_count{service_name=\"$service\"}[5m]))" }
],
"fieldConfig": { "defaults": { "custom": { "thresholdsStyle": "background" } } },
"thresholds": { "steps": [ { "color": "green", "value": 0 }, { "color": "red", "value": 0.01 } ] }
},
{
"title": "Duration p99 (s)",
"type": "timeseries",
"targets": [
{ "expr": "histogram_quantile(0.99, sum by (le) (rate(http_server_request_duration_seconds_bucket{service_name=\"$service\"}[5m])))" }
]
}
]
}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
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
阈值用法
错误率 panel 设背景阈值(绿<1%、红>1%),让异常一眼可见。但阈值只是可视化辅助,page 级告警仍应由 Prometheus Alerting Rule 按 SLO 燃烧速率触发(见 alerting.md),不要依赖 Grafana 自带的 alert(弱、易漏)。
生产实践三:三信号关联跳转
- Metrics → Traces:Prometheus 数据源开启 exemplar,面板样本点带
trace_id,点击跳 Tempo/Jaeger。 - Logs → Traces:Loki 数据源配置
derived fields,从日志行正则提取trace_id生成跳转链接。 - 面板 → 日志:在 RED 面板加
Data link,URL 指向 Loki 查询{service="$service"} |= "..."并带入$__timeRange。
json
{
"datasource": "Loki",
"name": "Logs",
"url": "https://grafana/explore?orgId=1&left={\"datasource\":\"Loki\",\"queries\":[{\"expr\":\"{service=\\\"$service\\\"} | json\"}],\"range\":{\"from\":\"${__from}\",\"to\":\"${__to}\"}}"
}1
2
3
4
5
2
3
4
5
生产实践四:看板 JSON 进 Git(版本化)
bash
# 导出看板
curl -s -H "Authorization: Bearer $GRAFANA_TOKEN" \
https://grafana/api/dashboards/uid/$UID > dashboards/checkout-red.json
# 提交到 Git;用 Grafana provisioning 或 Terraform provider 重新加载1
2
3
4
2
3
4
为什么必须 Git 化
看板只存在于 UI 会漂移、会坏、出事后无法追溯改了什么。Git 化后:评审、回滚、跨环境一致、与代码同仓库。Grafana Terraform provider 可直接 terraform apply 看板,杜绝手工漂移。
验证
bash
# 1. 模板变量能列出服务
# 在看板顶部确认 $service 下拉含 checkout
# 2. 关联跳转可用
# 点 RED 面板样本 → 应跳 Tempo;点日志 trace_id → 应跳 Jaeger
# 3. JSON 可被 Grafana 加载(CI 校验)
curl -s -H "Authorization: Bearer $GRAFANA_TOKEN" \
-X POST https://grafana/api/dashboards/db \
-d @dashboards/checkout-red.json # dry-run 用 --data 前先 lint1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
回滚与清理
生产危险
直接 UI 删看板不可逆(除非有 Git 备份)。回滚用 Git 重新 apply 旧版本 JSON,而非手动重建。
bash
git revert <commit> && terraform apply # 推荐
# 勿在 UI 直接删生产看板1
2
2
故障排查
| 现象 | 根因 | 处理 |
|---|---|---|
| 变量下拉为空 | 查询数据源无该 label | 确认 Prometheus 有 service_name label;变量 query 用 label_values |
| 关联跳转 404 | derived field 正则错 / trace_id 格式不符 | 核对 Loki derived fields 正则;确认日志输出 trace_id |
| panel "no data" | 查询窗口/label 不匹配 | 检查 $service 已选;rate 窗口与采集间隔 |
| 看板慢 | 单 panel 查询 30d 原始 | 用 Recording Rule;降采样;缩短默认范围 |
| 阈值不显示 | panel 类型不支持 thresholds | timeseries 需 thresholdsStyle 配置 |
性能、容量与成本
- 单看板 panel 数影响加载;8–12 为健康上限。
- 默认时间范围别设 30d 做逐点图,昂贵;概览用短窗口。
- 长周期 SLI(错误预算剩余)用 Recording Rule 预聚合,避免每次算
[30d]原始计数器。
常见坑
- 把所有指标塞一个看板 → 报表而非看板,事故时无从下手。
- 硬编码环境/集群名 → 多份克隆不同步。
- 用 Grafana 自带告警做 page → 弱、易漏,page 应由 Prometheus 负责。
- 看板只在 UI、不进 Git → 漂移无法回滚。
- 阈值当 SLO → 阈值是可视化,SLO 燃烧速率才是告警依据。
替代方案与权衡
- Grafana Provisioning:文件即配置,启动自动加载,比手动 UI 更稳。
- Grafana Terraform Provider:看板/数据源/文件夹全 IaC,适合多环境。
- Grafana OnCall:把值班/升级/runbook 接进看板,闭环告警到响应。
FAQ
Q:一个看板几个 panel 合适? A:8–12。超过就是报表。每个 panel 必须有明确要回答的运维问题。
Q:RED 和 USE 能放一个看板吗? A:不建议混。每看板聚焦一种方法(RED 服务 / USE 节点),混用事故时难读。L2 用 RED,L3 下钻时再切到 USE 节点面板。
参考资料
- Grafana 官方文档 - Dashboard best practices,访问日期:2026-10-08。
- Grafana 官方文档 - Template variables,访问日期:2026-10-08。
- Grafana 官方文档 - Data links,访问日期:2026-10-08。
- Grafana 官方文档 - Loki derived fields,访问日期:2026-10-08。
- Grafana Terraform Provider,访问日期:2026-10-08。