Grafana 系列 -GaC-1-Grafana 即代码的几种实现方式

本文最后更新于:2023年6月17日 下午

系列文章

概述

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 的脉络就会清晰起来.

📝Notes:

这里面 Crossplane 大家可能没怎么听过, 刚好我 2021 年有一篇介绍其的文章, 感兴趣的可以作为扩展阅读.

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 方案, 必选.

📝Notes:
如果是浅显地应用 GaC, 那么 Dashboard 直接通过 Dashboard json 文件作为代码管理也可以.
但是进入使用深水区, 在 Dashboard 多起来, 且有大量重复的配置的情况下, Jsoonet 是唯一选择.

Grafana Terraform provider

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

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

1
2
3
4
5
6
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 配置示例如下:

1
2
3
4
5
6
7
8
9
- 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 配置样本看起来是这样的:

1
2
3
4
5
6
7
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:

1
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 样本看起来像这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
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 配置样本看起来是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
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 资源的配置样本看起来是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
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 的示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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 Grafana Ansible Collection Grizzly Tanka Grafana CrossPlane Provider Grafana Operator Grafana API
支持的 Grafana 资源 所有资源 Grafana Cloud Stack, plugins, API keys, dashboards, data sources, folders Synthetic Monitoring checks, dashboards, data sources, folders, Prometheus rules Unknown 所有主要资源 Folders, data sources, dashboards, notification channels, Grafana plugin, Grafana oss deploy 所有资源
格式化工具 HCL/JSON/Jsonnet YAML Jsonnet/YAML/JSON Jsonnet YAML/JSON YAML 取决于你
Kubernetes 风格清单 ✔️ ✔️ ✔️ 取决于你
在 K8s 中管理定义资源 ✔️ ✔️ ✔️ 取决于你
简单的 Dashboard 构建流程 ✔️ 取决于你
获取 Grafana 资源信息 ✔️ ✔️ Unknown 取决于你
内置资源同步流程 ✔️ Unknown ✔️ ✔️ 取决于你
适用用户 已在用 Terraform 的用户 已在用 Ansible 的用户 期望 Kubernetes 风格清单管理 Grafana, 内置工作流和同步流程的用户 部署在 K8s 上且是 Jsonnet 粉丝 / 专家的用户 已在用 CrossPlane, 或期望用 K8s 资源管理 Grafana 的用户 全部使用 Grafana OSS, 并且部署在 K8s 中, 期望使用 K8s 资源管理的用户. 现有方案都不满足, 定制需求较多, 需要和内部工具集成的用户

这里定义的大多数工具可以相互结合使用,使用户实现 1 + 1 > 2 的效果.

我的最终选择是:

  • 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 ,请查看每个工具的代码库或和我交流, 敬请期待我的后续文章。💪💪💪

📚️参考文档