乐趣区

关于运维:Grafana-系列GaC2Grafana-Terraform-Provider-基础

系列文章

  • Grafana 系列文章
  • Terraform 系列文章

概述

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

  • 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

十分直白清晰。心愿对各位有所帮忙。

📚️参考文档

  • Docs overview | grafana/grafana | Terraform Registry
  • grafana_folder | Resources | grafana/grafana | Terraform Registry
  • grafana_data_source | Resources | grafana/grafana | Terraform Registry
  • grafana_dashboard | Resources | grafana/grafana | Terraform Registry
  • jsonencode – Functions – Configuration Language | Terraform | HashiCorp Developer
  • Strings and Templates – Configuration Language | Terraform | HashiCorp Developer

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

退出移动版