Grafana 是云原生时代最主流的可视化平台,但"能用"和"好用"之间隔着一套设计方法论。一个混乱的仪表盘会让值班人员在海量面板中迷失,而一个设计良好的仪表盘能在 5 秒内传递系统健康状态。从设计原则出发,覆盖变量系统、面板选型、告警集成,最后用一个完整的 SLO 仪表盘串联所有知识点。
参考来源:Grafana 官方文档
一、仪表盘设计原则
1.1 五秒规则
一个仪表盘应该在 5 秒内回答最核心的问题:系统现在是否正常? 超过 5 秒才理解,说明信息层次不对。
实践方法:
- 顶部放置全局状态行:用 Stat 或 Gauge 面板展示 SLO 达成率、核心错误率、P99 延迟,绿/黄/红阈值一目了然。
- 中部放置趋势图:Time series 面板展示过去 1-6 小时的指标趋势。
- 底部放置明细表:Table 面板列出实例级明细,供深入排障。
1.2 从左到右、从上到下
人类阅读习惯是从左上到右下,仪表盘的信息流应顺应这一规律:
┌─────────────────────────────────────────────┐
│ [SLO] [错误率] [P99延迟] [流量] │ ← 第一行:一眼看状态
├─────────────────────────────────────────────┤
│ CPU 趋势图 │ 内存趋势图 │ ← 第二行:趋势
│ 请求量趋势图 │ 错误率趋势图 │
├─────────────────────────────────────────────┤
│ 实例明细表 │ ← 第三行:明细
└─────────────────────────────────────────────┘
1.3 其他设计要点
- 一个仪表盘只服务一个主题:不要把"数据库监控"和"业务指标"混在一个仪表盘里。
- 合理利用阈值颜色:绿色=正常,黄色=警告,红色=严重,不要滥用颜色。
- 默认时间范围设为"最近 1 小时":值班场景最常用。
- 命名清晰:面板标题写"CPU 使用率 (%)“而非"cpu”。
二、变量模板系统
变量(Variables)是仪表盘可复用性的核心。通过变量可以实现"一套模板,多环境切换"。
2.1 创建变量
在 Dashboard Settings → Variables 中添加变量。以下是常用变量配置:
数据源变量 $datasource
Type: Datasource
Name: datasource
Query: Prometheus
服务器变量 $server
Type: Query
Name: server
Query: label_values(node_uname_info, instance)
实例变量 $instance(级联依赖 $server)
Type: Query
Name: instance
Query: label_values(node_uncpu_info{instance=~"$server"}, cpu)
自定义变量 $environment
Type: Custom
Name: environment
Query: prod, staging, dev
2.2 变量引用方式
# 在面板查询中引用变量
up{instance=~"$server"}
# 多选变量(Multi-value 开启时)
up{instance=~"$server"} # $server 展开为 node-1|node-2|node-3
# 在面板标题中使用
CPU 使用率 - $server
# 在仪表盘链接中使用
/dashboard/sre-overview?var-server=$server
2.3 变量链式联动
多级变量可以实现"选环境 → 选集群 → 选节点"的级联过滤:
# 第一级:$environment(Custom: prod, staging, dev)
# 第二级:$cluster(依赖 $environment)
label_values(kube_node_info{cluster=~"$environment"}, node)
# 第三级:$pod(依赖 $cluster)
label_values(kube_pod_info{node="$cluster"}, pod)
三、面板类型选择指南
| 面板类型 | 适用场景 | 典型指标 |
|---|---|---|
| Time series | 时序趋势分析 | CPU、内存、QPS、延迟趋势 |
| Stat | 单个关键数值 | SLO 达成率、当前在线用户数 |
| Gauge | 仪表盘式数值展示 | 磁盘使用率、CPU 使用率 |
| Bar gauge | 多实例横向对比 | 各节点内存使用率对比 |
| Table | 结构化明细 | 实例列表、告警列表 |
| Heatmap | 分布式延迟分析 | 请求延迟分布 |
| Pie chart | 占比分析 | 各 status code 流量占比 |
| State timeline | 状态变化时间线 | 节点存活状态 |
选型决策树
需要展示单个关键数值?
├── 是 → 需要仪表盘效果? → Gauge
│ 不需要 → Stat
└── 否 → 需要趋势?
├── 是 → Time series
└── 否 → 需要对比多个实例?
├── 是 → Bar gauge
└── 否 → 需要明细? → Table
关键面板配置示例
Stat 面板:SLO 达成率
# Query
1 - (
sum(rate(http_requests_total{status=~"5..", service="$service"}[5m]))
/ sum(rate(http_requests_total{service="$service"}[5m]))
)
# Thresholds
Thresholds:
- Base: 0 (Green)
- T1: 0.01 (Yellow) # 错误率 > 1% 变黄
- T2: 0.05 (Red) # 错误率 > 5% 变红
# Color mode: Background
# Unit: Percent (0.0-1.0)
Bar Gauge 面板:各节点 CPU 对比
# Query
100 * (1 - avg by (instance) (
rate(node_cpu_seconds_total{mode="idle", instance=~"$server"}[5m])
))
# Calculation: Last *
# Orientation: Horizontal
# Display mode: Gradient
四、告警集成:Grafana Alerting
Grafana 统一告警(Unified Alerting)支持跨数据源告警,相比在 Prometheus 侧单独配置 Alertmanager,它更适合"可视化告警管理"场景。
4.1 告警架构
Alert Rule → Notification Policy → Contact Point → 通知渠道
↓
Notification Policy(路由匹配)→ Silences(静默)
4.2 创建告警规则
通过 UI 或 Terraform 配置告警规则。以下是一个 YAML 形式的规则示例(Grafana provisioning):
# alerting/alert_rules.yaml
apiVersion: 1
groups:
- orgId: 1
name: SLO Alerts
interval: 60s
rules:
- uid: slo-error-rate-high
title: "SLO 错误率告警 - {{ $labels.service }}"
condition: B
data:
- refId: A
relativeTimeRange:
from: 600 # 过去 10 分钟
to: 0
datasourceUid: prometheus
model:
expr: |
sum(rate(http_requests_total{status=~"5..", service="$service"}[5m]))
/ sum(rate(http_requests_total{service="$service"}[5m]))
instant: true
- refId: B
relativeTimeRange:
from: 600
to: 0
datasourceUid: __expr__
model:
type: threshold
expression: A
conditions:
- evaluator:
params: [0.05]
type: gt
noDataState: NoData
execErrState: Error
for: 5m
annotations:
summary: "服务 {{ $labels.service }} 错误率超过 5%"
description: "当前错误率: {{ $values.A }},SLO 阈值: 5%"
labels:
severity: critical
team: sre
notification_settings:
group_by: ['service', 'alertname']
group_wait: 30s
group_interval: 5m
repeat_interval: 4h
4.3 通知策略与联系点
# alerting/notification_policies.yaml
apiVersion: 1
policies:
- receiver: default
group_by: ['alertname', 'service']
routes:
- receiver: critical-team
matchers:
- severity="critical"
group_wait: 0s
repeat_interval: 1h
- receiver: warning-team
matchers:
- severity="warning"
group_wait: 30s
repeat_interval: 4h
contactPoints:
- orgId: 1
name: critical-team
receivers:
- uid: webhook-critical
type: webhook
settings:
url: https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=YOUR_KEY
httpMethod: POST
- uid: email-critical
type: email
settings:
addresses: ['oncall@example.com']
- orgId: 1
name: default
receivers:
- uid: default-slack
type: slack
settings:
url: https://hooks.slack.com/services/xxx
五、实战:构建完整的 SLO 仪表盘
以下通过 JSON 模型片段展示一个 SLO 仪表盘的核心结构,包含多面板联动。
5.1 仪表盘变量定义
{
"templating": {
"list": [
{
"name": "datasource",
"type": "datasource",
"query": "prometheus",
"current": { "text": "Prometheus", "value": "Prometheus" }
},
{
"name": "service",
"type": "query",
"datasource": "$datasource",
"query": "label_values(http_requests_total, service)",
"refresh": 2,
"includeAll": false
},
{
"name": "status_filter",
"type": "custom",
"query": "2xx,3xx,4xx,5xx",
"default": "2xx"
}
]
}
}
5.2 面板一:SLO 达成率(Stat)
{
"title": "SLO 达成率 - $service",
"type": "stat",
"datasource": "$datasource",
"targets": [
{
"expr": "1 - (sum(rate(http_requests_total{status=~\"5..\", service=\"$service\"}[5m])) / sum(rate(http_requests_total{service=\"$service\"}[5m])))",
"legendFormat": "SLO"
}
],
"fieldConfig": {
"defaults": {
"unit": "percentunit",
"thresholds": {
"mode": "absolute",
"steps": [
{ "value": null, "color": "red" },
{ "value": 0.95, "color": "yellow" },
{ "value": 0.99, "color": "green" }
]
}
}
},
"options": {
"colorMode": "background",
"reduceOptions": { "calcs": ["lastNotNull"] }
}
}
5.3 面板二:错误率趋势(Time Series)
{
"title": "错误率趋势 - $service",
"type": "timeseries",
"datasource": "$datasource",
"targets": [
{
"expr": "sum(rate(http_requests_total{status=~\"5..\", service=\"$service\"}[5m])) / sum(rate(http_requests_total{service=\"$service\"}[5m])) * 100",
"legendFormat": "5xx Error Rate (%)"
}
],
"fieldConfig": {
"defaults": {
"unit": "percent",
"custom": {
"drawStyle": "line",
"lineInterpolation": "smooth",
"fillOpacity": 20
},
"thresholds": {
"steps": [
{ "value": null, "color": "green" },
{ "value": 1, "color": "yellow" },
{ "value": 5, "color": "red" }
]
}
}
}
}
5.4 面板三:P99/P50 延迟对比(Time Series)
{
"title": "请求延迟 P50 / P99 - $service",
"type": "timeseries",
"targets": [
{
"expr": "histogram_quantile(0.50, sum by (le) (rate(http_request_duration_seconds_bucket{service=\"$service\"}[5m])))",
"legendFormat": "P50"
},
{
"expr": "histogram_quantile(0.99, sum by (le) (rate(http_request_duration_seconds_bucket{service=\"$service\"}[5m])))",
"legendFormat": "P99"
}
],
"fieldConfig": {
"defaults": {
"unit": "s",
"custom": {
"drawStyle": "line",
"fillOpacity": 10
}
}
}
}
5.5 面板四:各实例 QPS 明细(Table)
{
"title": "实例 QPS 明细",
"type": "table",
"targets": [
{
"expr": "sum by (instance) (rate(http_requests_total{service=\"$service\"}[5m]))",
"format": "table",
"instant": true
}
],
"transformations": [
{
"id": "organize",
"options": {
"excludeByName": { "Time": true },
"renameByName": { "Value": "QPS" }
}
}
]
}
六、JSON 模型导出与版本管理
6.1 导出 JSON
在 Dashboard 页面点击顶部菜单 → Share → Export → Save to file,即可获得完整的 JSON 模型。
6.2 通过 Git 版本管理
将导出的 JSON 文件存入 Git 仓库,实现仪表盘的版本控制:
mkdir -p dashboards/slo
cp exported-dashboard.json dashboards/slo/slo-overview.json
git add dashboards/
git commit -m "feat: add SLO overview dashboard"
6.3 Provisioning 自动加载
Grafana 支持通过文件系统自动加载仪表盘 JSON,无需手动导入:
# /etc/grafana/provisioning/dashboards/dashboards.yaml
apiVersion: 1
providers:
- name: SRE Dashboards
orgId: 1
folder: SRE
folderUid: sre-folder
type: file
disableDeletion: false
updateIntervalSeconds: 30
allowUiUpdates: true
options:
path: /var/lib/grafana/dashboards
将 JSON 文件放到 /var/lib/grafana/dashboards/ 目录后,Grafana 每 30 秒自动扫描并加载。
6.4 使用 Terraform 管理(推荐生产环境)
# terraform/main.tf
resource "grafana_dashboard" "slo" {
folder = grafana_folder.sre.uid
config_json = file("${path.module}/dashboards/slo-overview.json")
}
resource "grafana_folder" "sre" {
title = "SRE"
}
terraform plan
terraform apply
优势:基础设施即代码,仪表盘变更可审计、可回滚,适合多人协作团队。
七、性能优化建议
- 减少面板数量:单个仪表盘面板数不超过 12 个,过多会导致浏览器卡顿和 Prometheus 查询风暴。
- 使用记录规则:将复杂 PromQL 预计算为指标,仪表盘只查询预计算结果。
- 合理设置查询间隔:面板的
Interval不要低于30s,减少对后端的压力。 - 使用
$__rate_interval:Grafana 内置变量,自动根据面板时间范围和抓取间隔计算合适的 rate 窗口:
# 推荐
rate(http_requests_total[$__rate_interval])
# 而非固定窗口
rate(http_requests_total[5m])
- 限制返回序列数:在数据源设置中配置
Max data points,避免返回过多序列导致浏览器崩溃。
总结
Grafana 仪表盘设计的核心不是"把所有指标都堆上去",而是围绕"值班人员能否在 5 秒内判断系统状态"来组织信息。记住三个层次:顶部看状态、中部看趋势、底部看明细。配合变量模板系统实现多环境复用,通过 Provisioning 或 Terraform 实现版本管理,就能构建出专业级运维仪表盘。
更多详情请参阅 Grafana 官方文档
参考资料与致谢
本文在撰写过程中参考了以下资料,感谢原作者的贡献:
- Grafana 官方文档 — Grafana,参考了Grafana 官方文档相关内容