Grafana Grafana

使用 Helm 和 Provisioning Values 在 Kubernetes 上部署 Grafana

通过 Helm chart 运行 Grafana,数据源、仪表板和设置都来自 values 文件。

15 min 中级

在 Kubernetes 上,Grafana Helm chart 将 provisioning 文件夹变成你在 values.yaml 中编写的配置。chart 会渲染 ConfigMap 和 Secret,把它们挂载到 Grafana 期望的路径,并在它们变化时重启或重新加载。这使 Grafana 非常适合 GitOps,因为 values 文件是你唯一需要编辑的东西。本指南构建一个 values 文件,用于 provision 数据源、仪表板、告警和服务器设置。

chart 的托管位置正在变化:一些 Grafana Labs 的 chart 正在迁移到社区维护的仓库。在安装之前,请查看 chart 的 README,确认要使用的仓库 URL 和 chart 版本,并固定该版本。下面的 values 键遵循 chart 文档所述的结构,但请在你安装的版本的 values.yaml 中确认它们。

安装

helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
helm install grafana grafana/grafana \
  --namespace monitoring --create-namespace \
  --version <chart-version> \
  -f values.yaml

如果 chart 已经迁移,请把仓库 URL 替换为 README 中的那个。把命令、--version 和 values 文件都保存在 Git 中,使安装可重复。

服务器设置:grafana.ini

任何你本会放进 grafana.ini 的内容,都放在 grafana.ini 键下,按 section 组织:

grafana.ini:
  server:
    root_url: https://grafana.example.com/
  users:
    allow_sign_up: false
  analytics:
    reporting_enabled: false
    check_for_updates: false
  log:
    mode: console

不能提交的值可以引用环境变量或文件,如配置指南中所示(例如 password: $__file{/etc/secrets/db/password})。

管理员凭据与其他 secret

使用现有的 Kubernetes Secret,而不是在 values 中写密码:

admin:
  existingSecret: grafana-admin
  userKey: admin-user
  passwordKey: admin-password

envFromSecret: grafana-secrets   # every key becomes an environment variable
apiVersion: v1
kind: Secret
metadata:
  name: grafana-secrets
  namespace: monitoring
stringData:
  POSTGRES_PASSWORD: change-me
  SLACK_WEBHOOK_URL: https://hooks.slack.com/services/XXX/YYY/ZZZ

provisioning 文件随后可以使用 $POSTGRES_PASSWORD 和 ${SLACK_WEBHOOK_URL}。请用 SOPS 加密该 Secret,或用 External Secrets 同步它,而不是把它作为明文 YAML 提交(参见密钥指南)。

数据源

datasources 键会被渲染成一个 provisioning 文件:

datasources:
  datasources.yaml:
    apiVersion: 1
    datasources:
      - name: Prometheus
        uid: prometheus
        type: prometheus
        access: proxy
        url: http://prometheus-server.monitoring.svc.cluster.local
        isDefault: true
        editable: false

仪表板:三种方式

1. 来自 chart 文件夹中文件的内联方式。 声明一个 provider,并按来源列出仪表板:

dashboardProviders:
  dashboardproviders.yaml:
    apiVersion: 1
    providers:
      - name: default
        orgId: 1
        folder: ''
        type: file
        disableDeletion: false
        allowUiUpdates: false
        options:
          path: /var/lib/grafana/dashboards/default

dashboards:
  default:
    node-exporter:
      gnetId: 1860
      revision: 37
      datasource: Prometheus
    kubernetes-overview:
      json: |
        { "uid": "k8s-overview", "title": "Kubernetes Overview", "panels": [] }

条目可以来自 grafana.com(gnetId 和 revision)、URL 或内联 JSON。dashboards 下的键(这里是 default)必须与 provider 的 options.path 文件夹名称一致。

2. 来自你自己管理的 ConfigMap。 将仪表板 JSON 保存在它自己的 ConfigMap 中(例如由 Kustomize 从仓库生成),并挂载它们:

dashboardsConfigMaps:
  default: grafana-dashboards

3. 使用 sidecar。 一个 sidecar 容器监视集群中带有某个标签的 ConfigMap(或 Secret),并将它们加载为仪表板,这样每个应用团队都可以把自己的仪表板与清单放在一起发布:

sidecar:
  dashboards:
    enabled: true
    label: grafana_dashboard
    labelValue: "1"
    searchNamespace: ALL
    folderAnnotation: grafana_folder
    provider:
      foldersFromFilesStructure: true
  datasources:
    enabled: true
    label: grafana_datasource
  alerts:
    enabled: true
    label: grafana_alert
apiVersion: v1
kind: ConfigMap
metadata:
  name: webapp-dashboard
  namespace: webapp
  labels:
    grafana_dashboard: "1"
  annotations:
    grafana_folder: Applications
data:
  webapp.json: |
    { "uid": "webapp-overview", "title": "Webapp Overview", "panels": [] }

sidecar 方式在跨团队时扩展性最好:没有人需要为添加仪表板而编辑 Grafana 的 values。

告警

告警 provisioning 文件可以来自 alerting 键,使用告警指南中的 YAML 格式:

alerting:
  contactpoints.yaml:
    secret:
      apiVersion: 1
      contactPoints:
        - orgId: 1
          name: team-slack
          receivers:
            - uid: team-slack-1
              type: slack
              settings:
                url: ${SLACK_WEBHOOK_URL}
                recipient: '#alerts'
  policies.yaml:
    apiVersion: 1
    policies:
      - orgId: 1
        receiver: team-slack

secret: 包装会把该文件放入 Secret 而不是 ConfigMap。请查看 chart 的 values.yaml,了解你的版本中的确切结构。告警规则可以来自同一个键,也可以来自 sidecar 的 alerts 设置。

持久化与副本

persistence:
  enabled: true
  size: 5Gi
replicas: 1

持久卷上的 SQLite 只支持一个副本。要实现高可用,请通过 grafana.ini 让 Grafana 指向 PostgreSQL,并提高 replicas。

使用 Flux 部署

如果你使用 Flux,chart 就变成一个 HelmRelease,上面的 values 放在 spec.values 中:

apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
  name: grafana
  namespace: monitoring
spec:
  interval: 10m
  chart:
    spec:
      chart: grafana
      version: "<chart-version>"
      sourceRef:
        kind: HelmRepository
        name: grafana
        namespace: flux-system
  valuesFrom:
    - kind: ConfigMap
      name: grafana-values

Git 中 values 的变更会自动推出。关于 HelmRepository、remediation 和漂移检测,参见 Flux 系列中的 Helm 指南。

验证

kubectl get pods -n monitoring
kubectl port-forward svc/grafana 3000:80 -n monitoring &
curl -s http://localhost:3000/api/health
kubectl logs deploy/grafana -n monitoring -c grafana | grep -i provisioning

如果缺少某个仪表板或数据源,请先检查 provisioning 日志行,然后检查 sidecar 的日志(-c grafana-sc-dashboard),看是否有标签或命名空间问题。

热门指南