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

系列文章

概述

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配置示例如下:

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

️参考文档

三人行, 必有我师; 知识共享, 天下为公. 本文由东风微鸣技术博客 EWhisper.cn 编写.

你可能感兴趣的:(Grafana系列-GaC-1-Grafana即代码的几种实现方式)