系列文章
概述
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 的几种官方方案
官方推荐这么几种方案, 另外我也会加几个我认为可行的方案:
- 基于 Terraform 的 Grafana Terraform provider
- 基于 Ansible 的 Grafana Ansible collection
- Grizzly: Grafana 官方开源的一个部署和配置Grafana 一体化 cli 工具.
- Tanka: Grafana 官方开源的一个基于 jsonnet 的 Kubernetes 集群管理工具
- 基于 Crossplane 的Grafana Crossplane provider
- 基于 Kubernetes CRD 的 Kubernetes Grafana Operator
- 基于 API 的定制化开发:
- 基于 Jsonnet 的 Dashboard as Code
- grafana/jsonnet-libs: Grafana Labs' Jsonnet libraries (github.com)
- grafana/grafonnet: Jsonnet library for generating Grafana dashboards. (github.com)
- grafana/grafonnet-lib: Jsonnet library for generating Grafana dashboard files. (github.com) (🐾已弃用, 但是仍有很多 Dashboard 资源依赖它)
- Prometheus Monitoring Mixins | Monitoring Mixins
- kubernetes-monitoring/kubernetes-mixin: A set of Grafana dashboards and Prometheus alerts for Kubernetes. (github.com)
是不是有点琳琅满目, 是不是有点挑花眼了? 😄😄😄
我刚开始也是这样, 不用担心, 我们一一过一下. 很快 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配置示例如下:
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: 最底层的 API 接口。
- grafana-api-golang-client: 基于 Grafana API 的低级别的 golang 客户端. 也是 Grafana Terraform provider 的底层实现
如果使用 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 的示例可以参考这个测试用例:
grafana-api-golang-client/dashboard_test.go at master · grafana/grafana-api-golang-client · GitHub
适用用户
首先, 基于 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