系列文章

概述

前文最后总结了我的工具选型:

  • Grafana Terraform provider
  • Jsonnet

我们今天先简单介绍 Grafana Terraform provider.

Grafana Terraform Provider

Grafana provider 为 Grafana 提供配置管理资源。是目前 Grafana 官方提供的,覆盖的 Grafana 资源最全的 IaC 工具。

Grafana Terraform Provider 的代码是建立在 grafana-api-golang-client 之上的。

通过 Grafana Terraform Provider, 我们可以管理:

  • Alerting

    • Resources

      • grafana_contact_point
      • grafana_message_template
      • grafana_mute_timing
      • grafana_notification_policy
      • grafana_rule_group
  • Cloud
    • Resources

      • grafana_cloud_access_policy
      • grafana_cloud_access_policy_token
      • grafana_cloud_api_key
      • grafana_cloud_plugin_installation
      • grafana_cloud_stack
      • grafana_cloud_stack_api_key
      • grafana_cloud_stack_service_account
      • grafana_cloud_stack_service_account_token
      • grafana_machine_learning_holiday
      • grafana_machine_learning_job
      • grafana_machine_learning_outlier_detector
    • DataSources
      • grafana_cloud_ips
      • grafana_cloud_organization
      • grafana_cloud_stack
  • Grafana Enterprise
    • Resources

      • grafana_builtin_role_assignment
      • grafana_data_source_permission (AWS Managed Grafana 也有这个功能)
      • grafana_report
      • grafana_role
      • grafana_role_assignment
      • grafana_team_external_group
  • Grafana OSS
    • Resources

      • grafana_annotation
      • grafana_api_key
      • grafana_dashboard
      • grafana_dashboard_permission
      • grafana_data_source
      • grafana_folder
      • grafana_folder_permission
      • grafana_library_panel
      • grafana_organization
      • grafana_organization_preferences
      • grafana_playlist
      • grafana_service_account
      • grafana_service_account_permission
      • grafana_service_account_token
      • grafana_team
      • grafana_team_preferences
      • grafana_user
    • DataSources
      • grafana_dashboard
      • grafana_dashboards
      • grafana_data_source
      • grafana_folder
      • grafana_folders
      • grafana_library_panel
      • grafana_organization
      • grafana_organization_preferences
      • grafana_team
      • grafana_user
      • grafana_users
  • OnCall
  • SLO
  • Synthetic Monitoring

实战

因为 Grafana 资源相对比较清晰和独立,不像 AWS 会有很多复杂的关联关系。

所以关于 Grafana TF 代码的组织形式可以简单点:

  • 可以使 AllInOne 的 .tf 文件
  • 也可以根据资源类型,简单拆分为如下即可:
├── dashboard.tf
├── datasource.tf
├── grafana-ds-info.auto.tfvars.json
├── jsonnet (jsonnet 文件夹,dashboard 相关内容都在该文件夹下)
├── main.tf
├── outputs.tf
├── variables.tf
└── versions.tf

下面以第二种组织结构来详细介绍。

创建 Grafana Provider

main.tf 中,创建 Grafana Provider:

provider "grafana" {
}

如果只有一套 Grafana, 那么如上的配置完全就够用了。

如果有多套 Grafana, 则可以通过指定 Grafana provider 的 alias 来实现。具体如下:

provider "grafana" {
alias = "aws-managed-grafana"
}

后续使用资源的时候,可以通过指定 provider 来区分,实例如下:

# provision folder
resource "grafana_folder" "play-grafana" {
provider = grafana.aws-managed-grafana
uid = "play-grafana"
title = "play-grafana"
}

Notes:

后续为了演示代码的简洁,不展示多 Grafana provider 的情况。

Resource 里也不会有 provider 字段。

Grafana 通过 Terraform 使用,是至少需要提供 url 和 apikey 2 类信息的。这 2 类信息可以直接通过环境变量的形式提供,具体如下:

export GRAFANA_URL=https://<your-grafana-domain>/
export GRAFANA_AUTH=<your-grafana-apikey>

GRAFANA_AUTH 的值可以是一个 Grafana API 密钥,basic auth 就是 用户名:密码,或可以点击这个链接申请 Grafana API 密钥

除此之外,Grafana Cloud/Synthetic Monitoring/Grafana Oncall 会有一些专用的 apikey 或 token, 这里就不详细介绍了。

创建 Grafana 组织

Notes:

因为我主要用的是 AWS Managed Grafana, 其只有一个默认的 org 1. 也没有开放相关的创建多个 org 的组织。所以我基本上不会用到该资源。

如果有用到该资源,可以创建一个 org.tf, 具体内容是:

// 创建组织
resource "grafana_organization" "my_org" {
name = "my_org"
} // 在组织内创建资源
provider "grafana" {
alias = "my_org"
org_id = grafana_organization.my_org.org_id
} resource "grafana_folder" "my_folder" {
provider = grafana.my_org title = "Test Folder"
}

创建 DataSource

该资源所需的参数根据所选择的数据源类型(通过 type 参数)而有所不同。

可以在 datasource.tf 下创建。

以下是创建:

  • stackdriver
  • influxdb
  • cloudwatch
  • zabbix
  • ES
  • Prometheus
  • Jaeger

的简单示例。

Stackdriver

resource "grafana_data_source" "arbitrary-data" {
type = "stackdriver"
name = "sd-arbitrary-data" json_data_encoded = jsonencode({
"tokenUri" = "https://oauth2.googleapis.com/token"
"authenticationType" = "jwt"
"defaultProject" = "default-project"
"clientEmail" = "client-email@default-project.iam.gserviceaccount.com"
}) secure_json_data_encoded = jsonencode({
"privateKey" = "-----BEGIN PRIVATE KEY-----\nprivate-key\n-----END PRIVATE KEY-----\n"
})
}

Influxdb

resource "grafana_data_source" "influxdb" {
type = "influxdb"
name = "myapp-metrics"
url = "http://influxdb.example.net:8086/"
basic_auth_enabled = true
basic_auth_username = "username"
database_name = influxdb_database.metrics.name json_data_encoded = jsonencode({
authType = "default"
basicAuthPassword = "mypassword"
})
}

Cloudwatch

基于 AKSK 的创建:

resource "grafana_data_source" "cloudwatch" {
type = "cloudwatch"
name = "cw-example" json_data_encoded = jsonencode({
defaultRegion = "us-east-1"
authType = "keys"
}) secure_json_data_encoded = jsonencode({
accessKey = "123"
secretKey = "456"
})
}

这是基于 role (external) 的创建:

resource "grafana_data_source" "cloudwatch" {
type = "cloudwatch"
name = "example_cw" json_data_encoded = jsonencode({
assumeRoleArn = "arn:aws:iam::<the-aws-id>:role/<...>"
authType = "ec2_iam_role"
defaultRegion = "us-east-1"
externalId = "<the-aws-id>"
})
}

Zabbix

resource "grafana_data_source" "zabbix" {
type = "alexanderzobnin-zabbix-datasource"
name = "Zabbix-example"
url = "http://<zabbix-domain>/api_jsonrpc.php" json_data_encoded = jsonencode({
trends = true
username = "Admin"
}) secure_json_data_encoded = jsonencode({
password = "Password"
})
}

注意:

Zabbix 的 type 是 alexanderzobnin-zabbix-datasource

使用的前提是安装 Zabbix Grafana 插件.

Jaeger

resource "grafana_data_source" "jaeger-example" {
type = "jaeger"
name = "example_jaeger"
uid = "example_jaeger"
url = "http://<jaeger-domain>/trace/" json_data_encoded = jsonencode({
"nodeGraph" : {
"enabled" : true
}
})
} data "grafana_data_source" "jaeger-example" {
name = grafana_data_source.jaeger-example.name
uid = grafana_data_source.jaeger-example.uid
}

上面的 data "grafana_data_source" "jaeger-example" 是将 Jaeger Datasource 的 uid 提供给 ES 使用。

当然,如果你直接在创建 Jaeger Datasource 的时候指定了 uid, 如下所示,那么后面在被其他 Datasource 引用时可以直接指定写死。

uid  = "example_jaeger"

ES

resource "grafana_data_source" "elasticsearch-example" {
type = "elasticsearch"
name = "es_example"
uid = "es_example"
url = "http://<es_host>:9200"
// 就是 es index
database_name = "[example.*-]YYYY.MM.DD" json_data_encoded = jsonencode({
esVersion = "6.0.0" interval = "Daily"
includeFrozen = false
maxConcurrentShardRequests = 256
timeField = "@timestamp" logLevelField = "level"
logMessageField = "_source"
dataLinks = [
{
datasourceUid = data.grafana_data_source.jaeger-example.uid
// 或 datasourceUid = "example_jaeger"
field = "trace_id",
url = "${"$"}{__value.raw}"
}
]
})
}

这里,有以下几个需要注意的地方:

  • database_name = "[example.*-]YYYY.MM.DD" 在 type 为 es 的情况下,database_name 就是 es 的索引名称
  • dataLinks 这里通过 data link 链接到 Jagger Datasource: datasourceUid = data.grafana_data_source.jaeger-example.uid (Jaeger Datasource 就是上一节创建的)
  • url = "${"$"}{__value.raw}" 这里要特别注意,实际上传给 Grafana 的是:${__value.raw}, 但是这个恰好也是 Terraform 的模板/变量替换语法,所以如果直接这样写会将其解析为模板/变量,从而出现该变量不存在的报错。通过${"$"} 转义为 $ + {__value.raw} 拼成正确的 ${__value.raw} 传给 Grafana.

Prometheus

基础配置如下:

resource "grafana_data_source" "prometheus" {
type = "prometheus"
name = "example_prom"
uid = "example_prom"
url = "http://my-instances.com" json_data_encoded = jsonencode({
httpMethod = "POST"
})
}

官方提供的 Prometheus 兼容实现 - Mimir 的配置如下:

resource "grafana_data_source" "prometheus" {
type = "prometheus"
name = "mimir"
url = "https://my-instances.com"
basic_auth_enabled = true
basic_auth_username = "username" json_data_encoded = jsonencode({
httpMethod = "POST"
prometheusType = "Mimir"
prometheusVersion = "2.4.0"
}) secure_json_data_encoded = jsonencode({
basicAuthPassword = "password"
})
}

创建 Dashboard

dashboard.tf 中,创建 dashboard 示例如下:

resource "grafana_dashboard" "metrics" {
config_json = file("grafana-dashboard.json")
}

也可以通过如下方式创建:

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

注意:

config_json 是 String 类型,具体是完整的 Dashboard model JSON。

可以直接通过 file("grafana-dashboard.json") 获取。

如第二个实例,jsonencode 的作用就是使用 JSON 语法将一个 Object 转换为 String.

总结

好了,本次我们介绍了 Grafana Terraform Provider 的基础知识,还是比较简单的,我们使用其:

  • 创建 Provider
  • 创建组织
  • 创建文件夹
  • 创建各类常见的 Datasources
  • 创建 Dashboard

非常直白清晰。希望对各位有所帮助。

️参考文档

Grafana 系列-GaC-2-Grafana Terraform Provider 基础的更多相关文章

  1. ldap配置系列三:grafana集成ldap

    ldap配置系列三:grafana集成ldap grafana的简介 grafana是一个类似kibana的东西,是对来自各种数据源的数据进行实时展示的平台,拥有这牛逼的外观.给一个官方的demo体验 ...

  2. Grafana 系列文章(一):基于 Grafana 的全栈可观察性 Demo

    ️Reference: https://github.com/grafana/intro-to-mlt 这是关于 Grafana 中可观察性的三个支柱的一系列演讲的配套资源库. 它以一个自我封闭的 D ...

  3. Grafana 系列文章(二):使用 Grafana Agent 和 Grafana Tempo 进行 Tracing

    ️URL: https://grafana.com/blog/2020/11/17/tracing-with-the-grafana-cloud-agent-and-grafana-tempo/ ✍A ...

  4. Grafana 系列文章(三):Tempo-使用 HTTP 推送 Spans

    ️URL: https://grafana.com/docs/tempo/latest/api_docs/pushing-spans-with-http/ Description: 有时,使用追踪系统 ...

  5. Grafana 系列文章(四):Grafana Explore

    ️URL: https://grafana.com/docs/grafana/latest/explore/ Description: Explore Grafana 的仪表盘 UI 是关于构建可视化 ...

  6. Grafana 系列文章(五):Grafana Explore 查询管理

    ️URL: https://grafana.com/docs/grafana/latest/explore/query-management/ Description: Explore 中的查询管理 ...

  7. Grafana 系列文章(六):Grafana Explore 中的日志

    ️URL: https://grafana.com/docs/grafana/latest/explore/logs-integration/#labels-and-detected-fields D ...

  8. Grafana 系列文章(七):Grafana Explore 中的 Tracing

    ️URL: https://grafana.com/docs/grafana/latest/explore/trace-integration/ Description: Tracing in Exp ...

  9. Grafana 系列文章(八):Grafana Explore 中的 Inspector

    ️URL: https://grafana.com/docs/grafana/latest/explore/explore-inspector/ Description: Explore 中的检查器 ...

  10. Grafana 系列文章(九):开源云原生日志解决方案 Loki 简介

    简介 Grafana Labs 简介 Grafana 是用于时序数据的事实上的仪表盘解决方案.它支持近百个数据源. Grafana Labs 想从一个仪表盘解决方案转变成一个可观察性 (observa ...

随机推荐

  1. flask配置config详解

    flask系列讲座与2017年12月6日开始,每周一篇.第三篇其中讲述flask的配置方法.使用app.config.from_object()方法,似乎很神奇.如果明白背后逻辑,实际上很自然.涉及代 ...

  2. [软件工程]TO B型IT软件企业在工程管理角度所存在的诸多问题

    组织架构与分工? 各子组织的职责.边界是否明确? (安装.升级)部署规范? 必须有部署文档. 各个模块/组件部署在哪台服务器?哪个路径下? 一切非正式启用的任务.文件(夹).安装资料必须依据实际用途以 ...

  3. 教程 - 在 Vue3+Ts 中引入 CesiumJS 的最佳实践@2023

    目录 1. 本篇适用范围与目的 1.1. 适用范围 1.2. 目的 2. 牛刀小试 - 先看到地球 2.1. 创建 Vue3 - TypeScript 工程并安装 cesium 2.2. 清理不必要的 ...

  4. Tomcat长轮询原理与源码解析

    Tomcat长轮询原理与源码解析 系列文章目录和关于我 零丶长轮询的引入 最近在看工作使用到的diamond配置中心原理,发现大多数配置中心在推和拉模型上做的选择出奇的一致选择了基于长轮询的拉模型 基 ...

  5. switch case 穿透 示例

    public class SwitchCase { //判断输入的月份属于第几季度 public static void main(String[] args) { //随机获得 1-12个月份中的一 ...

  6. 区块链——Lab2

    区块链的典型数据结构 比特币:UTXO模型,以交易后找零为中心 ETH:Account 模型,以账户余额为中心(就是账户的形式) 区块链交易 用户发起交易 矿工验证交易(能够得到 区块奖励) 验证成功 ...

  7. 教练!我不想遍历了!——用bool运算有效减少dataframe的时间复杂度

    方法参考:python - 降低python for循环的时间复杂度 - 堆栈内存溢出 (stackoom.com) 朋友们,朋友们,事情是这样的. 这几天博主在处理数据的时候遇到了这样的标注数据: ...

  8. Function-advanced

    函数进阶 1. 函数防抖 在频率触发的情况下 只有等待一定的时间才会触发 执行一次代码 特点 执行之前先清除之前的即将执行操作 保证只有最后一次生效 优化高频执行JS代码操作 提高性能 防抖代码实现 ...

  9. Prism Sample 10 10-CustomRegistrations

    作用同上节,这里是用修改注册的方式自定义View和ViewModel的关联. protected override void ConfigureViewModelLocator() { base.Co ...

  10. 在使用abaqus时可能会遇到的一些问题

    ​我收集了一些网友及客户在使用abaqus软件时遇到的一些问题,下面来看看是如何解决的~ (1)Linux平台使用Abaqus子程序的免费方案 gcc+gfortran 本方法在centos7和cen ...