从命令行重新加载、验证并排查 Provisioning 问题
找出 Grafana 加载了什么,无需重启即可重新加载,并修复常见的 provisioning 错误。
当一切都在文件中定义时,故障也存在于文件中:错误的缩进、缺失的 UID、容器中不存在的路径。Grafana 会告诉你它做了什么,但你得知道去哪里看。本指南涵盖 reload 端点、一些验证命令,以及你最常遇到的错误,这样你无需打开 UI 就能修复它们。
什么时候应用什么
| 资源 | 何时读取 | 如何重新应用 |
|---|---|---|
grafana.ini 和 GF_* 环境变量 | 仅在启动时 | 重启 Grafana |
| 数据源 | 启动时 | 重启,或使用 reload 端点 |
| 仪表板 | 启动时,之后每隔 updateIntervalSeconds | 等待,或使用 reload 端点 |
| 告警资源 | 启动时 | 重启(或按你所用版本的文档,通过 Admin API 重新运行 provisioning) |
| 插件应用设置 | 启动时 | 重启,或使用 reload 端点 |
无需重启即可重新加载
这些管理端点会重新读取 provisioning 文件。它们使用 POST,以及用 Grafana 管理员用户进行的基本认证;API 令牌不适用于 Admin API:
BASE=http://localhost:3000
AUTH="admin:$GRAFANA_ADMIN_PASSWORD"
curl -X POST -u "$AUTH" $BASE/api/admin/provisioning/dashboards/reload
curl -X POST -u "$AUTH" $BASE/api/admin/provisioning/datasources/reload
curl -X POST -u "$AUTH" $BASE/api/admin/provisioning/plugins/reload
curl -X POST -u "$AUTH" $BASE/api/admin/provisioning/notifications/reload
成功的调用会返回一条说明配置已重新加载的 JSON 消息。不要公开暴露这些端点,因为它们需要管理员凭据。对于其他任何情况,重启始终是安全的。
检查 Grafana 实际加载了什么
将文件与 API 的视图进行比较:
# health
curl -s $BASE/api/health
# effective server settings (sensitive values masked)
curl -s -u "$AUTH" $BASE/api/admin/settings | jq '.paths, .server'
# data sources, with read-only flag for provisioned ones
curl -s -u "$AUTH" $BASE/api/datasources | jq '.[] | {name, uid, type, readOnly}'
# data source connectivity
curl -s -u "$AUTH" $BASE/api/datasources/uid/prometheus/health
# dashboards and folders
curl -s -u "$AUTH" "$BASE/api/search?type=dash-db" | jq '.[] | {title, uid, folderTitle}'
curl -s -u "$AUTH" $BASE/api/folders | jq '.[] | {title, uid}'
# alerting
curl -s -u "$AUTH" $BASE/api/v1/provisioning/alert-rules | jq '.[] | {uid, title}'
curl -s -u "$AUTH" $BASE/api/v1/provisioning/contact-points | jq '.[].name'
curl -s -u "$AUTH" $BASE/api/v1/provisioning/policies | jq .
如果你 provision 的某个东西没有出现在这些列表中,日志会告诉你原因。
阅读日志
Provisioning 消息来自名称以 provisioning 开头的 logger。调试时提高详细程度:
# docker compose
GF_LOG_LEVEL=debug docker compose up -d grafana
docker compose logs grafana | grep -i provision
# kubernetes
kubectl logs deploy/grafana -n monitoring -c grafana | grep -i provision
在消息中查找文件名。Grafana 会指明它解析失败的文件,或它拒绝的资源。
在文件到达 Grafana 之前检查它们
大多数错误都可以在 CI 中捕获:
# YAML syntax
yamllint grafana/provisioning
# JSON syntax and required fields
jq empty dashboards/**/*.json
jq -e '.uid and .title' dashboards/*/*.json >/dev/null
# duplicate dashboard UIDs
jq -r '.uid' dashboards/*/*.json | sort | uniq -d
# every provisioned file starts with apiVersion: 1
grep -L '^apiVersion: 1' grafana/provisioning/*/*.yaml
一个廉价的端到端测试是:在 CI 中用相同的文件启动一个一次性的 Grafana,等待 /api/health,并对上面的 API 输出进行断言。
常见问题与修复
数据源或仪表板没有出现。 provisioning 文件夹没有挂载到 Grafana 查找的位置。确认 [paths] provisioning(默认 /etc/grafana/provisioning)与你的挂载匹配,并且子文件夹名称恰好是 datasources、dashboards、alerting 和 plugins。
读取文件时出现”Permission denied”。 官方镜像以非 root 用户运行,所以挂载的文件必须对它可读。将它们设为全局可读(chmod -R a+rX),或在卷上设置匹配的所有权。
仪表板失败,提示”Dashboard title cannot be empty”。 JSON 被包在 API 信封中({"dashboard": {...}})。被 provision 的文件必须包含仪表板模型本身。
仪表板加载了,但面板显示找不到数据源。 面板引用了一个没有被 provision 的 UID,或者文件中仍有来自导出的 ${DS_...} 占位符。在数据源文件中设置 uid,并在仪表板 JSON 中使用同样的 UID。
两个仪表板互相争夺,或其中一个不断被还原。 它们共用了一个 uid,或者在同一文件夹中标题相同。让每个 UID 在整个安装范围内唯一。如果某次 UI 编辑不断被覆盖,那是文件在获胜,这是设计使然,除非 provider 设有 allowUiUpdates: true。
删除了文件,但仪表板仍在。 provider 设有 disableDeletion: true,或者该仪表板被手动移到了某个文件夹。通过 API 删除它,或关闭 disableDeletion。
在多实例设置中,数据源的更改被忽略。 对于多个 Grafana 副本,只有当文件的 version 与已存储的相同或更高时,实例才会更新数据源。更改文件时请提高 version。
环境变量没有被替换。 插值适用于值,而不是键。它在仪表板 JSON、告警规则注解、查询模型、静默时段或模板中不起作用。检查该变量确实已在容器中设置(docker compose exec grafana env | grep NAME)。
告警导入冲突。 存在一个因手动编辑而产生的、具有相同 UID 或名称的资源。删除手工创建的那个,或将其加入文件中的某个 delete... 块,然后重启。
重建之后密钥不再工作。 secret_key 变了,所以已存储的密钥无法解密。恢复原来的密钥,或重新 provision 需要凭据的数据源。
管理员密码没有改变。 admin_password 只在首次创建数据库时应用。使用 grafana cli admin reset-admin-password,或重新创建该卷。
Helm 或 Operator 资源没有同步。 对于 chart,检查 sidecar 容器日志中的标签或命名空间不匹配。对于 Operator,对该资源运行 kubectl describe 并阅读它的状态条件。
可靠的变更流程
- 在分支中更改文件。
- CI 运行上面的 linter,并用这些文件启动一个一次性的 Grafana。
- 合并。交付机制重启或调谐 Grafana。
- 检查
/api/health和验证命令。 - 如果出现问题,回退这次提交。因为文件就是事实,回退会恢复之前的状态。
热门指南
-
将 Grafana 作为代码运维:全景图 哪些可以放在文件里,哪些需要 API,以及各部分如何组合在一起。 -
使用 grafana.ini 和环境变量配置 Grafana 服务器 了解配置文件的位置、覆盖的顺序,以及如何将设置保存在 Git 中。 -
从 JSON 文件 Provision 仪表板 从磁盘加载仪表板,从目录映射文件夹,并在不丢失变更的前提下创作仪表板。 -
Provision 告警规则、联系点与通知策略 用 YAML 定义整条告警管线,使其像代码一样被审查和版本化。 -
使用 Helm 和 Provisioning Values 在 Kubernetes 上部署 Grafana 通过 Helm chart 运行 Grafana,数据源、仪表板和设置都来自 values 文件。