从 JSON 文件 Provision 仪表板
从磁盘加载仪表板,从目录映射文件夹,并在不丢失变更的前提下创作仪表板。
仪表板是 JSON 文档,这使它们很容易存放在 Git 中。仪表板 provider 告诉 Grafana 监视哪个文件夹,Grafana 会加载在那里找到的每个 JSON 文件,并持续检查变化。本指南涵盖 provider 文件、文件夹映射、仪表板 JSON 本身,以及一个创作仪表板而不会留下仅存在于 UI 中的编辑的工作流。
Provider 文件
provisioning/dashboards/providers.yaml:
apiVersion: 1
providers:
- name: default
orgId: 1
type: file
disableDeletion: false
updateIntervalSeconds: 30
allowUiUpdates: false
options:
path: /var/lib/grafana/dashboards
foldersFromFilesStructure: true
每个字段的作用:
name是必需的,并且在所有 provider 中必须唯一。options.path是 Grafana 扫描 JSON 文件的目录。它必须存在于容器内。updateIntervalSeconds是 Grafana 多久重新扫描一次该路径。所有仪表板在启动时加载,此后无需重启即可拾取变更。allowUiUpdates:为false时,被 provision 的仪表板无法从 UI 保存,这使 Git 保持权威。为true时,UI 的保存会保留在数据库中,直到源文件发生变化,那时文件会覆盖它们。disableDeletion:为true时,删除文件不会从 Grafana 中删除其仪表板。如果 Git 应是事实,请保持为false。folder或folderUid将所有仪表板放入一个指定的文件夹。没有它们时,仪表板会放到根目录。foldersFromFilesStructure: true将path的子目录映射为 Grafana 文件夹。使用它时请让folder和folderUid留空。不支持嵌套文件夹,所以子目录只能有一层。
按文件夹组织仓库
在 foldersFromFilesStructure: true 下,这样的布局:
dashboards/
├── infrastructure/
│ ├── node-exporter.json
│ └── kubernetes.json
└── applications/
└── webapp.json
会创建两个 Grafana 文件夹,infrastructure 和 applications,其中包含相应的仪表板。如果你需要为不同的分组使用不同的设置,例如为一个”草稿”区域使用 allowUiUpdates: true 的 provider,请改用多个独立的 provider。
仪表板 JSON 要点
被 provision 的文件必须包含仪表板模型本身,并且顶层有 uid 和 title。不要把它包在 HTTP API 所使用的 {"dashboard": {...}, "overwrite": true} 信封中,这是导致”Dashboard title cannot be empty”错误的常见原因。
{
"uid": "webapp-overview",
"title": "Webapp Overview",
"tags": ["webapp", "provisioned"],
"schemaVersion": 39,
"version": 1,
"refresh": "30s",
"time": { "from": "now-6h", "to": "now" },
"templating": {
"list": [
{
"name": "namespace",
"type": "query",
"datasource": { "type": "prometheus", "uid": "prometheus" },
"query": "label_values(kube_pod_info, namespace)"
}
]
},
"panels": [
{
"id": 1,
"type": "timeseries",
"title": "Request rate",
"gridPos": { "h": 8, "w": 12, "x": 0, "y": 0 },
"datasource": { "type": "prometheus", "uid": "prometheus" },
"targets": [
{
"refId": "A",
"expr": "sum(rate(http_requests_total{namespace=\"$namespace\"}[5m]))",
"datasource": { "type": "prometheus", "uid": "prometheus" }
}
]
}
]
}
让仪表板作为代码时表现良好的准则:
- 设置稳定的
uid。 Grafana 每次加载时都会更新具有该 UID 的仪表板。避免在多个文件中重复使用同一个 UID,或在同一文件夹中使用两次相同的标题。 - 省略数字
id。 它由数据库分配,并且在不同实例之间不同。 - 按 UID 引用数据源,与你 provision 的
uid相匹配({"type": "prometheus", "uid": "prometheus"})。为分享而导出的仪表板可能包含诸如${DS_PROMETHEUS}之类的占位符,你必须将其替换为真实的 UID,或替换为数据源模板变量。 - 环境变量插值在仪表板 JSON 内部不起作用。 请使用仪表板模板变量来处理各环境的差异。
- Grafana 13 在内部以更新的 schema 存储仪表板,并在加载时迁移较旧的 JSON,所以现有文件仍可工作。
在 UI 中创作,再把结果带回 Git
手写面板 JSON 很慢,所以大多数团队先在 UI 中起草再导出。一个保持文件为事实的工作流:
- 运行一个临时实例(前面指南中的 compose 配置),其中某个 provider 设有
allowUiUpdates: true。 - 在 UI 中构建或调整仪表板。
- 从仪表板的分享或导出菜单将其导出为 JSON。如果你希望数据源被替换为输入,请选择面向外部分享的导出选项,然后设置真实的 UID。
- 移除数字
id,设置稳定的uid,并将文件提交到仓库文件夹中。 - 打开拉取请求。合并之后,生产环境的 Grafana 会拾取它,而那里的
allowUiUpdates: false会阻止任何人产生分歧。
你也可以通过 API 获取已有的仪表板:
curl -s -u admin:$GRAFANA_ADMIN_PASSWORD \
http://localhost:3000/api/dashboards/uid/webapp-overview \
| jq '.dashboard | del(.id)' > dashboards/applications/webapp.json
一致地格式化 JSON(例如 jq -S .),使 diff 只显示真正的变更。
用代码生成仪表板
如果许多仪表板具有相同的形态,请生成 JSON,而不是复制。Grafana Foundation SDK(Go、TypeScript、Python、PHP、Java)可以从类型化代码构建仪表板,其输出就是你放入 provider 文件夹的同样的 JSON。本系列中的 Foundation SDK 指南对此有介绍。
在 CI 中验证
在错误到达 Grafana 之前将其捕获:
# valid JSON?
jq empty dashboards/**/*.json
# every file has a uid and title?
for f in dashboards/*/*.json; do
jq -e '.uid and .title' "$f" >/dev/null || echo "missing uid/title: $f"
done
# duplicate uids?
jq -r '.uid' dashboards/*/*.json | sort | uniq -d
应用与验证
变更会在 updateIntervalSeconds 之内被拾取。要强制重新扫描:
curl -X POST -u admin:$GRAFANA_ADMIN_PASSWORD \
http://localhost:3000/api/admin/provisioning/dashboards/reload
curl -s -u admin:$GRAFANA_ADMIN_PASSWORD \
"http://localhost:3000/api/search?type=dash-db" | jq '.[] | {title, uid, folderTitle}'
如果某个仪表板没有出现,请检查来自 provisioning logger 的启动和重新扫描日志行。通常的原因是容器中不存在该路径、JSON 被包在 API 信封中,或两个文件共用了一个 uid。
热门指南
-
将 Grafana 作为代码运维:全景图 哪些可以放在文件里,哪些需要 API,以及各部分如何组合在一起。 -
使用 grafana.ini 和环境变量配置 Grafana 服务器 了解配置文件的位置、覆盖的顺序,以及如何将设置保存在 Git 中。 -
Provision 告警规则、联系点与通知策略 用 YAML 定义整条告警管线,使其像代码一样被审查和版本化。 -
使用 Helm 和 Provisioning Values 在 Kubernetes 上部署 Grafana 通过 Helm chart 运行 Grafana,数据源、仪表板和设置都来自 values 文件。 -
从命令行重新加载、验证并排查 Provisioning 问题 找出 Grafana 加载了什么,无需重启即可重新加载,并修复常见的 provisioning 错误。