Grafana Grafana

在 Grafana 配置中管理密钥

使用环境变量、文件和加密清单,让密码和令牌远离 Git。

10 min 中级

配置即代码只有在仓库可以被共享时才行得通,而包含密码的仓库是无法共享的。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 会扫描提交中的密钥。

热门指南