系列文章

概述

GaC(Grafana as Code, Grafana 即代码) 很明显是扩展自 IaC(Infrastructure as Code, 基础设施即代码)的概念.

Terraform 系列 - 什么是 IaC?一文中, 我们已经详细地说明了相关的概念, 我们可以直接套用在 GaC 上:

Grafana 即代码 (Grafana as Code, GaC) 是指通过 代码 而不是手动流程 / 控制台点击来管理和配置 Grafana。

这里有 2 个关键词:

  • Grafana
  • Code

Grafana 是被管理对象,在这里,不仅仅是指 Grafana OSS 这一款产品, 还包括 Grafana Labs 提供的商业产品和云服务. 包括不限于:

  • Grafana Alerting
  • Grafna Cloud Stack, 包括 Grafana Cloud 的:
    • 认证
    • 权限
    • 策略
    • Service Account
    • 组织
    • ...
  • Grafana Enterprise (企业版)
  • Grafana OnCall: 事件响应和管理平台(IRM)
  • Grafana SLO: SLA 和 可用性管理
  • Grafana Synthetic Monitoring: 拨测, 类似 BlackBoxProbe

Code 是管理方式,即像管理代码一样管理 Grafana 资源。那么管理代码最重要的部分: 版本管理是绕不开的。
...

当然, 这一系列文章, 主要还是关注于通过代码的形式来管理 Grafana 这个产品.

这篇文章主要跟着Grafana as code: A complete guide to tools, tips, and tricks 这篇官方文章的逻辑来进行, 变穿插笔者的评价和最终选择.

GaC 的几种官方方案

官方推荐这么几种方案, 另外我也会加几个我认为可行的方案:

是不是有点琳琅满目, 是不是有点挑花眼了? 😄😄😄

我刚开始也是这样, 不用担心, 我们一一过一下. 很快 GaC 的脉络就会清晰起来.

Jsonnet

根据 Grafana 的一些官方演讲视频和代码库以及博客文章, Grafana 是重度依赖 Jsonnet 这一配置语言的. 后面我们会详细介绍其历史及使用方法.

无论我们使用哪一种 GaC 方案, 基于 Jsonnet 的 Dashboard as Code 都是必选的.

  • 在 Terraform 中, 可以通过Jsonnet Provider 和 Grafana 配合使用
  • 在 Ansible 中, 可以在 task 之前加入对 jsonnet 相关依赖的安装, 以及 jsonnet 生成 Dashboard 的前置 tasks
  • 在 Grizzly 和 Tanka 中, jsonnet 就是一级公民. 如 Grizzly 可以直接使用 Jsonnet
  • ...

小结, Jsonnet 是目前几乎唯一的深度 Dashboard as Code 方案, 必选.

Grafana Terraform provider

Grafana 管理员可以使用Grafana的Terraform Provider 管理 dashboards 和 alerts,添加 synthetic monitoring probes 和检查,管理身份和访问,等等。

用于创建仪表盘的Terraform配置示例如下:

resource "grafana_dashboard" "metrics" {
  config_json = jsonencode({
    title   = "as-code dashboard"
    uid     = "ascode"
  })
}

适用用户

Grafana Terraform Provider 更适合那些已经在非Grafana使用案例中使用Terraform的用户。

对于目前希望在Grafana Cloud 或Grafana的OSS部署上管理整个Grafana生态系统资源的用户,最好使用Grafana Terraform Provider,因为与Grafana的其他作为代码的解决方案相比,它还支持最多的Grafana资源

笔者的最终选择, 就是:

  • Grafana Terraform Provider + Jsonnet

其中很大的一个原因就是上面提到的: 支持最多的Grafana资源.

笔者计划在 Aws Managed Grafana 中使用 Grafana, Aws Managed Grafana 相比 Grafana OSS, 功能还是有一点点的细微差别:

  • AWS Managed Grafana 有 DataSource 的 Permission 管理功能, 而 Grafana OSS 并没有这项功能.

但是 Grafana Terraform Provider 是提供这一功能的, 该功能位于 Grafana Enterprise 下面. 但确实可用.

目前我需要用到的 Grafana 功能有:

  • Grafana 用户
  • Grafana Team
  • Grafana 组织
  • Grafana DataSource
  • Grafana DataSource Permission
  • Grafana Folder
  • Grafana Folder Permission
  • Grafana Dashboard
  • Grafana Dashboard Permission
  • Grafana Alerting

只有 Grafana Terraform Provider 提供了完整的功能.

已知的限制

管理仪表盘并不是一个最简单的过程--用户必须处理长长的JSON,这也会变得难以审查和更新。Grafonnet可以帮助生成可用于Terraform的仪表盘JSON,但Grafonnet需要了解Jsonnet,所以这对一些用户来说是不可取的。

不管哪种方案, Jsonnet 其实是对所有进入 GaC 深水区的用户都必须掌握的, 逃不掉的.

Grafana Ansible collection

配置管理的资源可以通过Ansible Collection for Grafana提供。它可以用来管理各种资源,包括 folders、cloudstack和dashboards。用户可以通过编写使用HTTP API管理Grafana资源的Ansible playbooks,以编程方式管理Grafana上目前还不属于Grafana Ansible集合的资源。

创建仪表盘的Ansible配置示例如下:

- name: dashboard as code
  grafana.grafana.dashboard:
    dashboard: {
      "title": "as-code dashboard",
      "uid": "ascode"
    }
    stack_slug: "{{ stack_slug }}"
    grafana_api_key: "{{ grafana_api_key }}"
    state: present

适用用户

和Terraform一样,Grafana Ansible Collection 更适合已经将Ansible用于非Grafana用例的人。此外,该 Collection 目前只适用于Grafana Cloud,所以它对那些希望使用Ansible声明式管理资源的Grafana Cloud客户最有意义。

已知的限制

截至目前,Grafana Ansible Collection 只适用于Grafana Cloud,并且只支持8种资源

  • API密钥
  • Cloud Stack
  • plugins
  • dashboards
  • folders
  • data sources
  • alert contact points
  • alert notification policies

对于希望用Ansible以代码形式管理整个Grafana生态系统的用户来说,这可能是一个缺点。与Terraform一样,仪表盘的构建也不是最简单的过程。

小结, Grafana Ansible Collection 最大的缺点在于: 只适用于Grafana Cloud,并且只支持8种资源.

Grizzly

Grizzly 是一个命令行工具,允许你用代码管理你的可观察性资源。Grizzly支持Kubernetes启发的YAML表示的Grafana资源,这使得它更容易熟悉。Grizzly支持在Grafana实例内移动仪表盘,也可以检索已经配置的Grafana资源的信息。Grizzly目前支持:

  • Grafana dashboards/dashboard folders
  • Grafana data sources
  • Grafana Cloud 中的 Prometheus recording rules/alerts
  • Grafana Cloud Synthetic Monitoring checks

Grizzly也可以使用 Grafonnet 部署在Jsonnet中构建的仪表盘。(在Grafonnet文档中了解更多信息)。

用于创建仪表盘的Kubernetes风格的Grizzly配置样本看起来是这样的:

apiVersion: grizzly.grafana.com/v1alpha1
kind: Dashboard
metadata:
    name: as-code-dashboard
spec:
    title: as-code dashboard
    uid: ascode

适用用户

Grizzly最适合使用Jsonnet来管理Grafana资源的用户,或者喜欢用Kubernetes风格的YAML定义他们的Grafana资源。

已知的限制

Grizzly目前不支持Grafana OnCall和Grafana Alerting资源。

也不支持 DataSource/Folder/Dashboard Permission 等资源.

小结, Grizzly最适合使用Jsonnet来管理Grafana资源的用户. 但是支持的 Grafana 资源也不够全.

Grafana Crossplane provider

Grafana Crossplane Provider 使用Terrajet构建,为Grafana Terraform Provider 支持的所有资源提供支持。它使用户能够将Grafana资源定义为Kubernetes清单,也会帮助那些使用ArgoCD等工具围绕Kubernetes清单建立GitOps管道的用户。

要开始使用Grafana Crossplane Provider,请在Kubernetes集群中安装Crossplane,并使用此命令安装 provider:

kubectl crossplane install provider grafana/crossplane-provider-grafana:v0.1.0

在安装 provider 的过程中,Terraform provider 支持的所有资源的CRD被添加到集群中,因此用户可以开始将他们的Grafana资源定义为Kubernetes自定义资源。Crossplane provider 确保在 CRD 中所定义的内容在Grafana用户界面中是可见的。如果在用户界面中直接进行了任何更改,那么当提供者重新同步时,这些更改将被丢弃。这有助于确保集群中的任何声明性定义都将是Grafana资源的真实来源。

要开始使用,请参考Grafana Crossplane资源库中的示例文件夹

用于创建 Dashboard 的Kubernetes CRD 样本看起来像这样:

apiVersion: grafana.jet.crossplane.io/v1alpha1
kind: Dashboard
metadata:
  name: as-code-dashboard
spec:
  forProvider:
    configJson: |
      {
        "title": "as-code dashboard",
        "uid": "ascode"
      }
  providerConfigRef:
    name: grafana-crossplane-provider

适用用户

Grafana Crossplane provider 适合现有的Crossplane用户,他们希望从Kubernetes内管理Grafana资源,并作为Kubernetes清单用于GitOps管道。

已知限制

Crossplane provider 依赖于在Kubernetes集群中安装了Crossplane CLI和Crossplane。这种依赖性对于非Crossplane用户来说是没有吸引力的。它也处于alpha阶段,所以还没有达到稳定的状态。

小结, 适合已经用了 CrossPlane 的用户, 但对于非Crossplane用户来说就没啥吸引力了. 另外, 它还不稳定.

Kubernetes Grafana Operator

Grafana Operator 是一个 Kubernetes Operator,用于配置和管理Grafana及其使用Kubernetes CR 的资源。它是一个由Grafana社区建立的Kubernetes原生解决方案。它还可以把在Grafonnet中构建的仪表盘作为仪表盘配置的来源。

请参考grafana-operator仓库中的文档部分来开始使用。

一个使用Grafana操作器创建仪表盘的Kubernetes配置样本看起来是这样的:

apiVersion: integreatly.org/v1alpha1
kind: GrafanaDashboard
metadata:
  name: simple-dashboard
  labels:
    app: grafana
spec:
  json: >
    {
      "title": "as-code dashboard",
      “uid” : “ascode”
    }

适用用户

对于希望从Kubernetes内管理Grafana资源的用户来说,Grafana-operator非常好用,并作为Kubernetes清单用于GitOps管道。

已知的限制

这只适用于Grafana OSS,所以Grafana Cloud用户将无法使用它。另外,Grafana-operator没有Helm Chart,这对于拥有围绕Helm构建的管道的组织来说可能是个问题。

小结, 笔者个人认为, Kubernetes Grafana Operator 是非常适合这类用户的:

  • 自托管 Grafana OSS
  • Grafana OSS 部署在 Kubernetes 集群内

并且其还有这些优势:

  • 支持 Grafana OSS 各种细节配置
  • Grafana Dashboard 可以来自 Grafana com 的 id(其他工具好像都没有)
  • 支持安装 Grafana Plugin(其他工具好像都没有)
  • 完美契合 GitOps

相应地, 也有一些劣势:

  • 社区开发的, 缺少 Grafana 官方支持
  • 不支持 Grafana Cloud/AWS Managed Grafana 等云服务.

Tanka

为你的Kubernetes集群提供干净、简洁和超级灵活的YAML替代品

  • 💥 简洁:Jsonnet语言比YAML更明显地表达了你的应用程序。
  • 📚 复用:构建库,随时导入它们,甚至在GitHub上分享它们
  • 📌 简洁:使用Kubernetes库和抽象,你将永远不会再看到模板!
  • 🎯 信心:停止猜测,使用tk diff来看看到底会发生什么
  • 🔭 Helm:可重现的Helm Chart 中的 vendor、修改和导出。
  • 🚀 生产就绪:Tanka部署了Grafana Cloud和更多的生产设置

一个使用 tanka 创建 Prometheus + Grafana K8s 资源的配置样本看起来是这样的:

local k = import "github.com/grafana/jsonnet-libs/ksonnet-util/kausal.libsonnet";

{
  _config:: {
    grafana: {
      port: 3000,
      name: "grafana",
    },
    prometheus: {
      port: 9090,
      name: "prometheus"
    }
  },

  local deployment = k.apps.v1.deployment,
  local container = k.core.v1.container,
  local port = k.core.v1.containerPort,
  local service = k.core.v1.service,

  prometheus: {
    deployment: deployment.new(
      name=$._config.prometheus.name, replicas=1,
      containers=[
        container.new($._config.prometheus.name, "prom/prometheus")
        + container.withPorts([port.new("api", $._config.prometheus.port)]),
      ],
    ),
    service: k.util.serviceFor(self.deployment),
  },
  grafana: {
    deployment: deployment.new(
      name=$._config.grafana.name, replicas=1,
      containers=[
        container.new($._config.grafana.name, "grafana/grafana")
        + container.withPorts([port.new("ui", $._config.grafana.port)]),
      ],
    ),
    service:
      k.util.serviceFor(self.deployment)
      + service.mixin.spec.withType("NodePort"),
  },
}

适用用户

严格来说, Tanka 不应该出现在这里. Tanka 本质上是一个 Kubernetes 基础设施管理工具. 对标的竞品是:

  • Kustomize
  • Helm
  • Kubernetes Operator

甚至是:

  • Terraform
  • Ansible

如果你是 Jsonnet 配置语言的狂热粉丝, 并且想要通过 Jsonnet 管理 Kubernetes 基础设施和可观察性的 Grafana Dashboard、Prometheus rule 和 Alert rule。那么 tanka 是适合你的。

已知的限制

抛弃 Kubernetes YAML,完全采用 jsonnet 管理资源,你需要另外掌握以下知识:

  • Jsonnet
  • Tanka 使用
  • Kubernetes 资源的相关 Jsonnet Library
  • Grafana 相关的 Jsonnet Library

小结,不建议使用 tanka, 除非你是 Jsonnet 配置语言的狂热粉丝和专家。

基于 API 的定制化开发

Grafana 的 API,我也仔细找了一圈,官方有这么几种 API:

如果使用 Grafana API, 创建 Dashboard 的示例如下:

POST /api/dashboards/db HTTP/1.1
Accept: application/json
Content-Type: application/json
Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk

{
  "dashboard": {
    "id": null,
    "uid": null,
    "title": "Production Overview",
    "tags": [ "templated" ],
    "timezone": "browser",
    "schemaVersion": 16,
    "version": 0,
    "refresh": "25s"
  },
  "folderId": 0,
  "folderUid": "l3KqBxCMz",
  "message": "Made changes to xyz",
  "overwrite": false
}

如果使用 grafana-api-golang-client, 创建 Dashboard 的示例可以参考这个测试用例:

https://github.com/grafana/grafana-api-golang-client/blob/master/dashboard_test.go

适用用户

首先, 基于 API 的定制化开发都适用于开发能力强、有更多自定义需求、上述 GaC 方案都不满足需求、需要和公司企业内部的自动化工具整合的情况.

其次, Grafana 提供了基于 golang 的 grafana-api-golang-client, 如果您的技术栈是 golang, 建议直接使用 grafana-api-golang-client.

如果您的技术栈不是 golang, 则建议基于 Grafana API 开发.

已知限制

唯一的限制就是您/贵团队/贵司的技术能力和资源投入.

总结

这里有一个方便的对比表格,对比了上面提到的所有属性和工具。

我的最终选择是:

  • Grafana Terraform provider
  • Jsonnet

我的 Grafana 主要是以下几类:

  • AWS Managed Grafana
  • Grafana OSS
  • Grafana Cloud Free

我需要用到的 Grafana 功能有:

  • Grafana 用户
  • Grafana Team
  • Grafana 组织
  • Grafana DataSource
  • Grafana DataSource Permission
  • Grafana Folder
  • Grafana Folder Permission
  • Grafana Dashboard
  • Grafana Dashboard Permission
  • Grafana Alerting

欲了解更多信息或开始使用 Grafana ,请查看每个工具的代码库或和我交流, 敬请期待我的后续文章。💪💪💪

📚️参考文档

06-19 03:15