Grafana 系列-GaC-2-Grafana Terraform Provider 基礎(chǔ)

系列文章

概述

前文最后總結(jié)了我的工具選型:

  • Grafana Terraform provider
  • Jsonnet

我們今天先簡(jiǎn)單介紹 Grafana Terraform provider.

Grafana Terraform Provider

Grafana provider 為 Grafana 提供配置管理資源。是目前 Grafana 官方提供的系宜,覆蓋的 Grafana 資源最全的 IaC 工具照激。

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

通過(guò) 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 也有這個(gè)功能)
      • 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

實(shí)戰(zhàn)

因?yàn)?Grafana 資源相對(duì)比較清晰和獨(dú)立盹牧,不像 AWS 會(huì)有很多復(fù)雜的關(guān)聯(lián)關(guān)系俩垃。

所以關(guān)于 Grafana TF 代碼的組織形式可以簡(jiǎn)單點(diǎn):

  • 可以使 AllInOne 的 .tf 文件
  • 也可以根據(jù)資源類(lèi)型,簡(jiǎn)單拆分為如下即可:
├── dashboard.tf
├── datasource.tf
├── grafana-ds-info.auto.tfvars.json
├── jsonnet (jsonnet 文件夾汰寓,dashboard 相關(guān)內(nèi)容都在該文件夾下)
├── main.tf
├── outputs.tf
├── variables.tf
└── versions.tf

下面以第二種組織結(jié)構(gòu)來(lái)詳細(xì)介紹口柳。

創(chuàng)建 Grafana Provider

main.tf 中,創(chuàng)建 Grafana Provider:

provider "grafana" {
}

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

如果有多套 Grafana, 則可以通過(guò)指定 Grafana provider 的 alias 來(lái)實(shí)現(xiàn)跃闹。具體如下:

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

后續(xù)使用資源的時(shí)候,可以通過(guò)指定 provider 來(lái)區(qū)分,實(shí)例如下:

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

??Notes:
后續(xù)為了演示代碼的簡(jiǎn)潔辣卒,不展示多 Grafana provider 的情況掷贾。
Resource 里也不會(huì)有 provider 字段。

Grafana 通過(guò) Terraform 使用荣茫,是至少需要提供 url 和 apikey 2 類(lèi)信息的想帅。這 2 類(lèi)信息可以直接通過(guò)環(huán)境變量的形式提供,具體如下:

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

GRAFANA_AUTH 的值可以是一個(gè) Grafana API 密鑰啡莉,basic auth 就是 用戶(hù)名:密碼港准,或可以點(diǎn)擊這個(gè)鏈接申請(qǐng) Grafana API 密鑰

除此之外咧欣,Grafana Cloud/Synthetic Monitoring/Grafana Oncall 會(huì)有一些專(zhuān)用的 apikey 或 token, 這里就不詳細(xì)介紹了浅缸。

創(chuàng)建 Grafana 組織

??Notes:

因?yàn)槲抑饕玫氖?AWS Managed Grafana, 其只有一個(gè)默認(rèn)的 org 1. 也沒(méi)有開(kāi)放相關(guān)的創(chuàng)建多個(gè) org 的組織。所以我基本上不會(huì)用到該資源魄咕。

如果有用到該資源衩椒,可以創(chuàng)建一個(gè) org.tf, 具體內(nèi)容是:

// 創(chuàng)建組織
resource "grafana_organization" "my_org" {
  name     = "my_org"
}

// 在組織內(nèi)創(chuàng)建資源
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"
}

創(chuàng)建 DataSource

該資源所需的參數(shù)根據(jù)所選擇的數(shù)據(jù)源類(lèi)型(通過(guò) type 參數(shù))而有所不同。

可以在 datasource.tf 下創(chuàng)建哮兰。

以下是創(chuàng)建:

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

的簡(jiǎn)單示例毛萌。

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 的創(chuàng)建:

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) 的創(chuàng)建:

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 使用。

當(dāng)然喝滞,如果你直接在創(chuàng)建 Jaeger Datasource 的時(shí)候指定了 uid, 如下所示阁将,那么后面在被其他 Datasource 引用時(shí)可以直接指定寫(xiě)死。

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}"
      }
    ]
  })
}

這里右遭,有以下幾個(gè)需要注意的地方:

  • database_name = "[example.*-]YYYY.MM.DD" 在 type 為 es 的情況下做盅,database_name 就是 es 的索引名稱(chēng)
  • dataLinks 這里通過(guò) data link 鏈接到 Jagger Datasource: datasourceUid = data.grafana_data_source.jaeger-example.uid (Jaeger Datasource 就是上一節(jié)創(chuàng)建的)
  • url = "${"$"}{__value.raw}" 這里要特別注意,實(shí)際上傳給 Grafana 的是:${__value.raw}, 但是這個(gè)恰好也是 Terraform 的模板/變量替換語(yǔ)法窘哈,所以如果直接這樣寫(xiě)會(huì)將其解析為模板/變量吹榴,從而出現(xiàn)該變量不存在的報(bào)錯(cuò)。通過(guò)${"$"} 轉(zhuǎn)義為 $ + {__value.raw} 拼成正確的 ${__value.raw} 傳給 Grafana.

Prometheus

基礎(chǔ)配置如下:

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 兼容實(shí)現(xiàn) - 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"
  })
}

創(chuàng)建 Dashboard

dashboard.tf 中滚婉,創(chuàng)建 dashboard 示例如下:

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

也可以通過(guò)如下方式創(chuàng)建:

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

??注意:

config_json 是 String 類(lèi)型腊尚,具體是完整的 Dashboard model JSON。

可以直接通過(guò) file("grafana-dashboard.json") 獲取满哪。

如第二個(gè)實(shí)例,jsonencode 的作用就是使用 JSON 語(yǔ)法將一個(gè) Object 轉(zhuǎn)換為 String.

總結(jié)

好了劝篷,本次我們介紹了 Grafana Terraform Provider 的基礎(chǔ)知識(shí)哨鸭,還是比較簡(jiǎn)單的,我們使用其:

  • 創(chuàng)建 Provider
  • 創(chuàng)建組織
  • 創(chuàng)建文件夾
  • 創(chuàng)建各類(lèi)常見(jiàn)的 Datasources
  • 創(chuàng)建 Dashboard

非常直白清晰娇妓。希望對(duì)各位有所幫助像鸡。

???參考文檔

三人行, 必有我?guī)? 知識(shí)共享, 天下為公. 本文由東風(fēng)微鳴技術(shù)博客 EWhisper.cn 編寫(xiě).

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子只估,更是在濱河造成了極大的恐慌志群,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蛔钙,死亡現(xiàn)場(chǎng)離奇詭異锌云,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)吁脱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)桑涎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人兼贡,你說(shuō)我怎么就攤上這事攻冷。” “怎么了遍希?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵等曼,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我凿蒜,道長(zhǎng)禁谦,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任篙程,我火速辦了婚禮枷畏,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘虱饿。我一直安慰自己拥诡,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布氮发。 她就那樣靜靜地躺著渴肉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪爽冕。 梳的紋絲不亂的頭發(fā)上仇祭,一...
    開(kāi)封第一講書(shū)人閱讀 52,441評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音颈畸,去河邊找鬼乌奇。 笑死,一個(gè)胖子當(dāng)著我的面吹牛眯娱,可吹牛的內(nèi)容都是我干的礁苗。 我是一名探鬼主播,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼徙缴,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼试伙!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤疏叨,失蹤者是張志新(化名)和其女友劉穎潘靖,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體蚤蔓,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡卦溢,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了昌粤。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片既绕。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖涮坐,靈堂內(nèi)的尸體忽然破棺而出凄贩,到底是詐尸還是另有隱情,我是刑警寧澤袱讹,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布疲扎,位于F島的核電站,受9級(jí)特大地震影響捷雕,放射性物質(zhì)發(fā)生泄漏椒丧。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一救巷、第九天 我趴在偏房一處隱蔽的房頂上張望壶熏。 院中可真熱鬧,春花似錦浦译、人聲如沸棒假。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)帽哑。三九已至,卻和暖如春叹俏,著一層夾襖步出監(jiān)牢的瞬間妻枕,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工粘驰, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留屡谐,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓蝌数,卻偏偏與公主長(zhǎng)得像康嘉,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子籽前,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容