在 Grafana 配置中管理密钥
使用环境变量、文件和加密清单,让密码和令牌远离 Git。
配置即代码只有在仓库可以被共享时才行得通,而包含密码的仓库是无法共享的。Grafana 提供了多种方式,让密钥远离文件,同时仍然声明式地定义一切。本指南展示密钥出现在哪里、如何注入它们,以及对于 Grafana 自己存储的密钥应当怎么做。
密钥出现在哪里
- 服务器设置: 管理员密码、数据库密码、SMTP 凭据、OAuth 客户端密钥,以及
secret_key。 - 数据源:
secureJsonData中的密码、令牌和 TLS 密钥。 - 联系点:
settings中的 webhook URL、API 密钥和路由密钥。 - 为其他工具所做的 provisioning: Terraform、Operator 和 Git Sync 各自都需要一个 API 令牌或 Git 凭据。
方法 1:环境变量
最简单的选项。Provisioning YAML 支持在值中使用 $VAR 和 ${VAR},而 grafana.ini 支持 ${VAR} 和 $__env{VAR}:
# provisioning/datasources/postgres.yaml
datasources:
- name: Postgres
uid: postgres-main
type: postgres
url: $POSTGRES_HOST:5432
secureJsonData:
password: $POSTGRES_PASSWORD
# grafana.ini
[security]
admin_password = ${GF_ADMIN_PASSWORD}
需要记住的规则:
- 插值只对值有效,对键无效。
- 当你需要字面的美元符号时(例如在
{{ $$labels }}这样的模板中),使用$$。 - 它在仪表板 JSON 中不起作用,并且在某些告警字段中不会被应用:规则注解、查询模型、
relativeTimeRange、静默时段的名称和间隔,以及通知模板。
在 Docker Compose 中,从未被跟踪的 .env 文件或 CI 的 secret 存储中读取变量。在 Kubernetes 中,将 Secret 映射进容器(见下文)。
方法 2:以文件形式提供密钥
Grafana 使用 $__file{} 将文件内容读入某个设置中,并去除首尾空白:
[database]
password = $__file{/run/secrets/grafana_db_password}
[security]
secret_key = $__file{/run/secrets/grafana_secret_key}
这适合 Docker secret 和以文件形式挂载的 Kubernetes Secret,并且避免了通过 docker inspect 或进程环境泄露值。官方 Docker 镜像还接受在 GF_* 变量名后加 __FILE 后缀:
services:
grafana:
image: grafana/grafana:13.1.0
environment:
GF_SECURITY_ADMIN_PASSWORD__FILE: /run/secrets/grafana_admin_password
secrets:
- grafana_admin_password
secrets:
grafana_admin_password:
file: ./secrets/grafana_admin_password.txt
方法 3:Kubernetes Secret
将凭据存放在 Secret 中,并以环境变量形式暴露:
apiVersion: v1
kind: Secret
metadata:
name: grafana-secrets
namespace: monitoring
type: Opaque
stringData:
admin-password: change-me
slack-webhook-url: https://hooks.slack.com/services/XXX/YYY/ZZZ
postgres-password: change-me-too
env:
- name: SLACK_WEBHOOK_URL
valueFrom:
secretKeyRef:
name: grafana-secrets
key: slack-webhook-url
Grafana Helm chart 可以为管理员用户使用已有的 Secret,并为环境变量挂载其他 Secret,Kubernetes 指南中有所展示。不要把该 Secret 作为明文 YAML 提交。请加密它,或从 secret 管理器生成它:
- SOPS 配合 Flux 或 Argo CD:以加密形式提交
grafana-secrets.yaml,让 GitOps 控制器在集群中解密它。本资料库中的 Flux 系列有一篇 SOPS 指南。 - External Secrets Operator 或 CSI 驱动:从 Vault、AWS Secrets Manager 或其他存储同步密钥,只提交引用。
secret_key 与已存储的密钥
Grafana 使用 secret_key 设置来加密它存储在数据库中的密钥(例如数据源密码)。有两个后果:
- 显式设置它,并让它在重启、副本和重建之间保持不变。默认值是公开的,所以不设置它会削弱这种加密。
- 不要随意更改它。 如果它变了,已有的加密值将无法解密。因为数据源是从文件 provision 的,用新密钥重新 provision 就能恢复它们,但仅在 UI 中输入的密钥会丢失。
管理员密码的注意事项
admin_password 只在 Grafana 首次创建数据库时生效。若要之后更改它,请通过容器内的 CLI 或 API 重置,或重新创建数据库:
grafana cli admin reset-admin-password 'new-password'
更好的做法是让人们转向 SSO,使本地管理员账号仅作为应急登录,并把它的密码存放在你的 secret 管理器中。
Grafana 周边工具的令牌
- Terraform 和 Operator 使用 service account 令牌进行认证。以最小角色创建该 service account,把令牌存入你的 CI 或集群 secret 存储,并按计划轮换。
- Git Sync 需要一个 Git 提供商凭据:个人访问令牌,或 GitHub App 或 OAuth app 连接。把令牌放在
Repository资源的secure块中传入,这样它被存为 secret,而不是放在 spec 里。 - 管理员 provisioning API 只接受使用管理员用户的基本认证,不接受 API 令牌,所以请限制谁能访问这些端点。
检查清单
- Git 历史中没有明文密钥。如果有泄漏,请轮换它,而不是仅仅删除那次提交。
secret_key已显式设置,并存放在你的 secret 管理器中。- 每个环境都有自己的数据库密码、管理员密码和 API 令牌。
.env和 secret 文件夹在.gitignore中,并且 CI 会扫描提交中的密钥。
热门指南
-
将 Grafana 作为代码运维:全景图 哪些可以放在文件里,哪些需要 API,以及各部分如何组合在一起。 -
使用 grafana.ini 和环境变量配置 Grafana 服务器 了解配置文件的位置、覆盖的顺序,以及如何将设置保存在 Git 中。 -
从 JSON 文件 Provision 仪表板 从磁盘加载仪表板,从目录映射文件夹,并在不丢失变更的前提下创作仪表板。 -
Provision 告警规则、联系点与通知策略 用 YAML 定义整条告警管线,使其像代码一样被审查和版本化。 -
使用 Helm 和 Provisioning Values 在 Kubernetes 上部署 Grafana 通过 Helm chart 运行 Grafana,数据源、仪表板和设置都来自 values 文件。 -
从命令行重新加载、验证并排查 Provisioning 问题 找出 Grafana 加载了什么,无需重启即可重新加载,并修复常见的 provisioning 错误。