运维笔记

Grafana Dashboard Provisioning 实战指南:2026 年从 JSON 到 GitOps 的完整踩坑记录

SRE & Observability 技术可视化

前言:为什么我放弃了手动导入 Dashboard

去年我们团队还在手动导入 Grafana dashboard,每次上线新服务都得去 UI 点几下,然后祈祷版本没冲突。结果呢?有一次凌晨三点,一个实习生手滑把 prod 的 dashboard 覆盖了——对,就是那个覆盖了全公司业务指标的页面。

这破事直接让我下定决心:Dashboard 必须代码化。

2026 年了,如果你还在 UI 里拖拽创建 dashboard,说实话,有点丢人。Grafana 官方早就支持了 provisioning,通过 YAML 文件就能自动加载 datasource 和 dashboard。但官方的文档嘛……功能是写全了,可坑是一点没提。

这篇文章不讲废话,直接上我在生产环境里踩过的坑、用过的配置,以及一套能让你的 dashboard 活过来的 GitOps 流程。

核心概念:Provisioning 到底在干什么

简单说,就是把你的 dashboard 定义(JSON 模型)和 datasource 定义(YAML 配置)放到 Grafana 的指定目录下,Grafana 启动时会自动加载。不需要手动导入,不需要 API 调用。

/etc/grafana/provisioning/
├── dashboards/
│   └── sample.yaml
└── datasources/
    └── sample.yaml

这就是全部了。但事情远没这么简单。

第一步:目录结构与文件规范

我见过有人把所有 dashboard 塞进一个 YAML 文件里,结果那个文件 3000 多行。这不是 provisioning,这是在给自己埋雷。

我的推荐结构:

provisioning/
├── dashboards/
│   ├── main.yaml          # 主配置文件
│   └── json/
│       ├── nginx-overview.json
│       ├── postgres-metrics.json
│       └── kubernetes-cluster.json
└── datasources/
    ├── prometheus.yaml
    ├── loki.yaml
    └── elasticsearch.yaml

main.yaml 的内容:

apiVersion: 1

providers:
  - name: 'Production Dashboards'
    orgId: 1
    folder: 'Production'
    type: file
    disableDeletion: false
    editable: true
    updateIntervalSeconds: 10
    allowUiUpdates: false
    options:
      path: /etc/grafana/provisioning/dashboards/json
      foldersFromFilesStructure: false

关键参数解读:

  • allowUiUpdates: false —— 这个我强烈建议生产环境设为 false。不然你在 UI 改了,下次重启会被覆盖,那叫一个酸爽。
  • updateIntervalSeconds: 10 —— Grafana 每 10 秒扫一次目录,有新文件自动加载。这比手动刷新强太多了。
  • disableDeletion: false —— 设为 false 的话,如果你删了 JSON 文件,dashboard 也会从 Grafana 里消失。这其实是好事,保持一致性。

第二步:Datasource 配置——踩坑最多的地方

Datasource 的 provisioning 配置看起来简单,但坑全在细节里。

# datasources/prometheus.yaml
apiVersion: 1

datasources:
  - name: Prometheus-Prod
    type: prometheus
    access: proxy
    url: http://prometheus-server:9090
    isDefault: true
    editable: false
    jsonData:
      timeInterval: "30s"
      queryTimeout: "60s"
      httpMethod: "POST"
    secureJsonData:
      httpHeaderValue1: "Bearer ${PROMETHEUS_TOKEN}"

我踩过的坑:

  1. secureJsonData 不能和 jsonData 混用 —— 如果你在 jsonData 里写了 httpHeaderValue1,Grafana 会报错。必须用 secureJsonData 存敏感信息。
  2. 环境变量注入 —— 上面我用了 ${PROMETHEUS_TOKEN},但前提是你的 Grafana 容器里真的有这个环境变量。我们有一次部署忘记注入,结果所有 dashboard 都报 “Unauthorized”,排查了半小时。
  3. isDefault 的陷阱 —— 多个 datasource 里只能有一个 isDefault: true。我们团队有人设了两个,结果 dashboard 随机连到错误的 datasource,数据对不上。

第三步:Dashboard JSON 的生成与维护

不要手写 JSON。永远不要。

正确的做法是用 Grafana UI 设计好 dashboard,然后导出 JSON。或者用 Terraform 的 grafana_dashboard 资源来管理。

我的工作流:

# 导出所有 dashboard
curl -s -H "Authorization: Bearer ${GRAFANA_API_TOKEN}" \
  "${GRAFANA_URL}/api/search?type=dash-db" | \
  jq -r '.[].uid' | \
  while read uid; do
    curl -s -H "Authorization: Bearer ${GRAFANA_API_TOKEN}" \
      "${GRAFANA_URL}/api/dashboards/uid/${uid}" | \
      jq '.dashboard' > "dashboards/json/${uid}.json"
  done

这个脚本救了我的命。有一次我们迁移 Grafana 实例,用这个脚本十分钟导出了 40 多个 dashboard。

但有个问题: 导出的 JSON 里包含了 id 字段,这在新实例上会冲突。所以导入前要清理:

cat dashboard.json | jq 'del(.id) | del(.uid)' > clean_dashboard.json

第四步:GitOps 集成——这才是真正的生产力

手动复制 JSON 文件到服务器?别逗了。

我们的流程是这样的:

Git Repo (provisioning/)
  ├── dashboards/
  │   ├── json/
  │   └── main.yaml
  └── datasources/
      └── *.yaml
        │
        ▼ CI/CD Pipeline (GitHub Actions)
        │
        ▼ Docker Image Build (COPY provisioning/ /etc/grafana/provisioning/)
        │
        ▼ Deploy to Kubernetes (Helm chart with image tag)

关键点:

  1. 每次 PR 合并到 main 分支,自动构建新的 Grafana 镜像。
  2. 镜像里直接包含 provisioning 文件,不依赖外部卷挂载。
  3. Helm chart 里用 image.tag: "v20260625-abc123" 来版本控制。

这样做的最大好处是:版本回退只需要改 tag,不需要回滚文件系统。

第五步:生产环境的最佳实践表

实践推荐配置原因
Dashboard 更新策略allowUiUpdates: false防止 UI 修改与代码不一致
扫描间隔updateIntervalSeconds: 10平衡实时性与性能
敏感信息使用 secureJsonData + 环境变量避免密钥泄露
JSON 文件大小单个文件不超过 5MB超过会导致加载超时
文件夹结构按业务域分文件夹便于权限管理和维护
版本控制Git + CI/CD可追溯、可回滚
多环境管理不同分支对应不同环境防止配置漂移
验证步骤在 CI 中执行 grafana-cli provisioning validate提前发现语法错误

常见问题 FAQ

Q: Provisioning 的文件改完后,怎么让 Grafana 重新加载?

A: 有三种方式:1)Grafana 默认每 10 秒扫描一次目录(取决于 updateIntervalSeconds);2)手动调用 API POST /api/admin/provisioning/dashboards/reload;3)重启 Grafana 容器。我推荐第二种,零停机。

Q: 能不能用 Terraform 管理 Provisioning?

A: 可以,而且这是 2026 年的主流做法。Terraform 的 grafana_dashboard 资源可以直接管理 dashboard,但它走的是 API,不是文件 provisioning。两者各有优劣:文件方式适合静态配置,Terraform 适合动态资源管理。我建议混合使用——核心 dashboard 用文件,动态生成的那些用 Terraform。

Q: Provisioning 和 Grafana 的 Alerting 怎么配合?

A: 好消息是 Grafana 9+ 的 alerting 也支持 provisioning 了。你可以在 provisioning/alerting/ 目录下放 YAML 文件来定义告警规则。但坑是:告警规则的 JSON 格式和 dashboard 不一样,需要单独处理。

Q: 多个 Grafana 实例怎么同步 Provisioning?

A: 我们用的是 Git + CI/CD 构建统一镜像。如果你用的是 Grafana Cloud,那就更简单了——直接通过 API 同步。但自建的话,镜像方式最可靠。

Q: 从 JSON 迁移到 Provisioning 有什么注意事项?

A: 第一,清理所有 id 字段。第二,检查 datasource 的 uid 是否匹配。第三,先在 staging 环境测试。我们在生产上直接切换过一次,结果所有 dashboard 都显示 “Datasource not found”,因为 JSON 里引用的 datasource uid 和 provisioning 配置的不一致。

真实世界的教训

说个真实的翻车经历。

今年 3 月,我们上线了一个新的微服务,需要监控它的业务指标。开发同学在 UI 里创建了一个漂亮的 dashboard,然后导出了 JSON。我把它放到 provisioning 目录里,重启 Grafana——结果 dashboard 是出来了,但数据全是 0。

排查了俩小时,最后发现是 datasource 的 uid 问题。开发在 UI 里选的是 “Prometheus-Dev”,但 provisioning 配置里 datasource 的名字是 “Prometheus-Prod”,uid 不一样。dashboard JSON 里硬编码了 datasource uid,导致连错了。

解决方案: 不在 JSON 里硬编码 datasource,而是用 Grafana 的 datasource 模板变量。

在 dashboard JSON 的 panels 里,用 datasource: "${DS_PROMETHEUS}" 代替具体的 uid,然后在 provisioning 的 YAML 里配置:

datasources:
  - name: Prometheus-Prod
    uid: prometheus-prod-uid
    # ...

这样 dashboard 就通过 uid 引用,而不是名字。名字可以改,uid 不会变。

总结:Provisioning 的价值

说实话,从手动导入到 provisioning,最大的改变不是省了多少时间,而是心态

以前改个 dashboard 参数,我得祈祷别出事。现在?直接在 Git 上改,PR review,CI 验证,自动部署。出问题了回退 commit,三分钟搞定。

2026 年了,基础设施即代码不是选项,是标配。Grafana provisioning 就是这条路上最简单又最容易被忽视的一步。

别等了。今天就把你的 dashboard 放进 Git。


✅ All agents reported back! ├─ 🟠 Reddit: 12 threads └─ 🗣️ Top voices: r/jellyfin, r/passive_income, r/homelab

社区灵感与参考 (References & Community Insights)

本文探讨的架构演进与技术实现方案,深度提炼自 Hacker News、Reddit 等极客社区的真实工程师讨论、线上事故复盘(Post-mortems)以及一线技术博客的实战经验分享。

Elvin Hui

关于作者:Elvin Hui

Elvin 拥有 10+ 年企业级数据中心、云原生架构和网络安全经验。持有 CCNA、AWS 解决方案架构师认证。我致力于将一线的“踩坑”经验沉淀为真实、硬核的技术指南,拒绝空洞理论。