# 看板与查询 · 怎么做一个有用的看板

> 大多数看板是装饰品。这一章讲让看板真正有用的几件事：变量与模板（一个看板服务所有服务）、看板即代码、以及那个决定成败的原则——看板的结构应该长得像排障的思路。

- 作者：David（道雾轩）
- 专栏：指标采集与观测（https://daiw.org/manual/observability.md）
- 最后更新：2026-07-15
- 原文：https://daiw.org/manual/observability/grafana-dashboards
- 转载与引用：请注明出处并附原文链接（https://daiw.org/about/copyright）

# 看板与查询 · 怎么做一个有用的看板

**大多数看板是装饰品**：漂亮、50 个图、出事时没人看。

这一章讲让看板**真正有用**的几件事。技术不难，难的是判断力——[和告警那章一样](https://daiw.org/manual/observability/alerting-philosophy)。

## 变量：一个看板服务所有服务

<Callout type="info">
  **最实用的功能，也是“看板不该复制粘贴”的关键。**

  ```
  变量 $service  ← 从 label_values(up, job) 动态取值
  变量 $instance ← 从 label_values(up{job="$service"}, instance) 级联
  ```
  然后面板里写：
  ```text
  sum(rate(http_requests_total{job="$service"}[5m]))
  ```

  **于是一个看板 = 所有服务的看板**，顶部下拉框一切换就换了对象。

  **几个关键用法：**

  - **级联变量** —— `$instance` 的取值依赖 `$service`。**选了服务，实例列表自动过滤。**
  - **`$__rate_interval`** —— **这个内置变量值得专门说**。[第 4 部分讲过 `rate()` 的窗口至少要 4 倍抓取间隔](https://daiw.org/manual/observability/promql-rate)，而 Grafana **不知道你的抓取间隔**。`$__rate_interval` 会**自动算出一个安全的窗口**（基于面板的 step 和数据源配置的 `scrape_interval`）。
    ```text
    rate(http_requests_total[$__rate_interval])   ← 比硬编码 [5m] 更稳
    ```
    **硬编码 `[5m]` 的问题**：用户把时间范围拉到 30 天，step 变成 30 分钟，而你的窗口还是 5 分钟——**大部分求值点的窗口里可能只有 0 个采样点**（[第 4 部分讲过会返回空](https://daiw.org/manual/observability/promql-rate)），图上全是断线。`$__rate_interval` 自动跟着 step 放大，**这个坑很多人踩过**。
  - **`repeat`（重复面板）** —— 按变量的每个值**自动生成一行/一个面板**。比如“每个实例一个 CPU 图”，不用手工加 20 个。

  **变量把“看板”从“一次性产物”变成了“[模板](https://daiw.org/manual/observability/grafana-dashboards)”**——这是[看板能被复用、被维护](https://daiw.org/manual/observability/grafana-dashboards)的前提。
</Callout>

## 看板即代码

<Callout type="warn">
  **UI 上点出来的看板，有三个必然的问题：**

  - **没有版本控制** —— 谁改的？改了什么？想回滚？**不知道。**
  - **没法复制到别的环境** —— 测试环境的看板要重新点一遍。
  - **会腐烂** —— 人走了，看板留着，没人知道它还准不准。

  **解法：把看板定义（JSON）放进 Git，用 provisioning 自动加载。**

  ```yaml
  # provisioning/dashboards/main.yaml
  apiVersion: 1
  providers:
    - name: 'my-dashboards'
      folder: 'Services'
      type: file
      options:
        path: /var/lib/grafana/dashboards    # ← 从这个目录加载 JSON
      allowUiUpdates: false    # ← 禁止 UI 改!强制走 Git
  ```

  **`allowUiUpdates: false` 是关键的一步**：它**强制所有变更走代码评审**。否则总有人在 UI 上“临时改一下”，然后那个改动就永远地和 Git 里的版本分叉了。

  **更进一步：用 Grafonnet（Jsonnet）或 Terraform 生成看板** —— 好处是**能抽象**：定义一个“标准服务看板”函数，20 个服务调用它生成 20 个看板。**改一处，20 个全更新。**

  **这和[告警规则该走代码](https://daiw.org/manual/observability/alertmanager)是同一条原则**：**可观测性配置是基础设施，该有和代码一样的工程纪律**（评审、版本、可复现）。**手工点出来的东西，注定腐烂。**
</Callout>

## 决定成败的：看板的结构

<Callout type="info">
  **这是本章最重要的一条，[第 2 部分提过](https://daiw.org/manual/observability/four-golden-signals)，这里落实：**看板的结构应该长得像排障的思路，而不是像“我们能采到的指标列表”**。**

  **❌ 典型的坏看板：**
  ```
  一页 50 个图,按"我们有什么指标"排列:
  [CPU] [内存] [磁盘] [网络] [GC] [线程] [连接池] [QPS] [延迟] [错误] ...
  ```
  **问题：出事时，你不知道该先看哪个。** 50 个图里有 48 个是绿的，而你要在剩下的里面找关联——**这是人肉做 join，效率极低**。

  **✅ 好看板：分层，一层一个问题**
  ```
  ┌─ 第一层:用户体验好吗?([黄金信号](https://daiw.org/manual/observability/four-golden-signals),4 个图)
  │   [成功率] [P50/P99] [QPS] [错误预算剩余]
  │        ↓ 红了才往下看
  ├─ 第二层:是哪一跳?([RED](https://daiw.org/manual/observability/red-method),按依赖分解)
  │   [本服务 RED] [下游 A 的 RED] [下游 B 的 RED]
  │        ↓ 定位到某跳才往下看
  └─ 第三层:是哪个资源?([USE](https://daiw.org/manual/observability/use-method))
      [CPU U/S] [内存 U/S] [连接池 U/S] [磁盘 U/S]
  ```

  **检验标准（再说一遍，因为它真的好用）：**

  > **如果值班的人被叫醒后，能顺着看板从上往下，在 5 分钟内定位到根因，这个看板就是好的。**
  > **如果他还是得去 `tail` 日志或者问人，那它就是装饰品。**

  **实现上，用 Grafana 的 **row（行）** 折叠**：第一层展开，二三层默认折叠。**平时只看 4 个图，出事了再逐层展开**——这直接把“分层”变成了物理结构。
</Callout>

## 几个实用技巧

<Callout type="info">
  - **面板上放 PromQL 的“意图”** —— 用面板的 description 写清“这个图在回答什么问题”。**三个月后你自己都会忘。**
  - **用 [recording rule](https://daiw.org/manual/observability/recording-rules) 喂看板** —— [不只是快](https://daiw.org/manual/observability/promql-performance)，而且**看板里的表达式变得极简**（`service:http_errors:ratio_rate5m` vs 一大坨嵌套查询），可读性天差地别。
  - **给关键面板配 [runbook 链接](https://daiw.org/manual/observability/alerting-philosophy)** —— 面板的 links 里放上“这个图异常时该怎么办”。
  - **注意时间范围的默认值** —— 默认 30 天 = [每次打开都是一次昂贵查询](https://daiw.org/manual/observability/promql-performance)。**默认 1 小时或 6 小时**。
  - **别在一个面板里画 500 条线** —— [人眼分辨不了](https://daiw.org/manual/observability/alerting-philosophy)，而且[数据传输和渲染都很贵](https://daiw.org/manual/observability/promql-performance)。用 `topk(10, ...)` 或者[聚合掉](https://daiw.org/manual/observability/promql-aggregation)。
</Callout>

## 小结与下一章

**变量把看板从“一次性产物”变成“模板”**：[级联变量、`repeat` 自动生成面板](https://daiw.org/manual/observability/grafana-dashboards)，尤其 **`$__rate_interval`**——[它自动算出安全的 `rate()` 窗口，避免“硬编码 `[5m]` + 用户拉到 30 天 → step 变大 → 窗口里没点 → 图上断线”这个高频坑](https://daiw.org/manual/observability/promql-rate)。**看板即代码**：[UI 点出来的必然没版本、不可复制、会腐烂](https://daiw.org/manual/observability/grafana-dashboards)；用 provisioning 从 Git 加载，**`allowUiUpdates: false` 强制变更走评审**；更进一步用 Grafonnet/Terraform **抽象出“标准服务看板”函数，改一处 20 个全更新**——[和告警规则该走代码是同一原则：可观测性配置是基础设施](https://daiw.org/manual/observability/alertmanager)。**决定成败的是结构**：[看板要**分层**（用户体验 → 哪一跳 → 哪个资源），长得像排障思路而非“我们有什么指标”](https://daiw.org/manual/observability/four-golden-signals)；用 row 折叠把分层变成物理结构；**检验标准：值班的人能否顺着它 5 分钟定位根因**。技巧：[写清面板意图、用 recording rule 喂看板（表达式极简）、配 runbook 链接、默认时间范围别太大、别画 500 条线](https://daiw.org/manual/observability/recording-rules)。

最后一章：[三支柱的桥](https://daiw.org/manual/observability/exemplars)在 UI 上怎么落地。👉 [Explore 与关联](https://daiw.org/manual/observability/grafana-explore)。

## 参考资料

- [1] Grafana 官方文档：Variables、`$__rate_interval`、Provisioning、Dashboard JSON model。
- [2] Grafonnet / Terraform Grafana provider（看板即代码）。
- [3] 关联[黄金信号的分层看板](https://daiw.org/manual/observability/four-golden-signals)、[recording rules](https://daiw.org/manual/observability/recording-rules)、[rate 窗口](https://daiw.org/manual/observability/promql-rate)。
