Datadog Monitor の定義を Terraform で管理できます。
が、Datadog側がJSONで定義されており少々書き難いのと、 Monitor毎に同じ記載を繰り返す部分(通知本文や通知先)をテンプレート化できないものかと思い、考えてみた結果をメモ。
Terraform の Template Provider で実現します。 バージョンによっては動作しないですし、もっと良い方法・書き方が有りそうではあります。
目次
- 目次
— 要件
— 環境
— ファイル構成
—– datadog_key.auto.tfvars
—– datadog_monitor.auto.tfvars
—– datadog_monitor.tf
—– datadog_monitor_template.tf
—– templates/
—– message.tmpl
—– notify.tmpl
— 作成例
—– 作成結果
要件
- 複数 Monitor の通知本文、通知先を一括変更したい
- 通知先をアラートレベルにより変更したい
- 通知本文をヒアドキュメント化したい
- 改行文字(\n)入れつつ、1行で書くのを止めたい
環境
$ terraform version Terraform v0.11.3 + provider.datadog v1.0.3 + provider.template v1.0.0
ファイル構成
使用したファイルは tf-dd-prov-monitor-template に上げています。
. ├── datadog_key.auto.tfvars # APIKey定義 ├── datadog_monitor.auto.tfvars # 通知先定義 ├── datadog_monitor.tf # provider定義 ├── datadog_monitor_template.tf # template定義 ├── ec2.tf ├── templates # テンプレートファイル群 │ ├── message.tmpl # 通知本文用 │ └── notify.tmpl # 通知先用 ├── terraform.tfstate └── terraform.tfstate.backup
以下、上から順にファイル内容の説明です。
datadog_key.auto.tfvars
Datadog の API Key、 Application Key 値を設定します。 git 管理する場合等は .gitignore に入れる候補になるかと思います。
datadog_api_key="" datadog_app_key=""
datadog_monitor.auto.tfvars
通知先のリストを設定します。@slack-〜 が通知先です。(例ではSlackのみですがメールアドレス等や他インテグレーションでも良いです)
アラートレベルにより通知先が変更できるようにします。
# all notify_all = [ "@slack-alert0", "@slack-alert-all", ] # only alert notify_is_alert = [ "@slack-alert1", "@slack-alert-only", ] notify_is_alert_recovery = [] ・・・
datadog_monitor.tf
Datadog Provider を定義します。 公式Doc通りです。
# Variables variable "datadog_api_key" {} variable "datadog_app_key" {} # Configure the Datadog provider provider "datadog" { version = "~> 1.0" api_key = "${var.datadog_api_key}" app_key = "${var.datadog_app_key}" }
datadog_monitor_template.tf
今回の肝になるテンプレート定義です。 定義した通知先リスト変数を並べて、テンプレートに渡します。
# 通知先リスト変数定義 variable "notify_all" { type = "list" } variable "notify_is_alert" { type = "list" } variable "notify_is_alert_recovery" { type = "list" } ・・・ # 通知先リストを文字列置換 locals { notify_all_join = "${ length(var.notify_all) == 0 ? "" : join(" ", var.notify_all) }" notify_all = " ${local.notify_all_join} " # is notify_is_alert_join = "${ length(var.notify_is_alert) == 0 ? "" : join(" ", var.notify_is_alert) }" notify_is_alert = " {{#is_alert}} ${local.notify_is_alert_join} {{/is_alert}} " notify_is_alert_recovery_join = "${ length(var.notify_is_alert) == 0 ? "" : join(" ", var.notify_is_alert) }" notify_is_alert_recovery = " {{#is_alert_recovery}} ${local.notify_is_alert_recovery_join} {{/is_alert_recovery}} " ・・・ } # テンプレートファイルを定義 ## 変数渡し無し data "template_file" "message" { template = "${file("./templates/message.tmpl")}" } ## 変数渡し有り data "template_file" "notify" { template = "${file("./templates/notify.tmpl")}" vars { notify_all = "${ local.notify_all_join == "" ? "" : local.notify_all }" # is notify_is_alert = "${ local.notify_is_alert_join == "" ? "" : local.notify_is_alert }" notify_is_alert_recovery = "${ local.notify_is_alert_recovery_join == "" ? "" : local.notify_is_alert_recovery }" ・・・ } }
templates/
例では2つしか置いてませんが、定義を増やす事でテンプレートは増やせます。
message.tmpl
通知本文用のテンプレート、変数引渡し無しverの例になります。
Metric Value: {{value}} {{comparator}} threshold: {{#is_warning}}{{warn_threshold}}{{/is_warning}}{{#is_warning_recovery}}{{warn_threshold}}{{/is_warning_recovery}}{{#is_alert}}{{threshold}}{{/is_alert}}{{#is_alert_recovery}}{{threshold}}{{/is_alert_recovery}} - Host: {{host.name}}
notify.tmpl
通知先用のテンプレート例です。変数引渡しを行い、アラートレベルにより通知先リストを設定させます。
More information: [Ops Guide](http://example.com) Notify:${notify_all}${notify_is_alert}${notify_is_alert_recovery}${notify_is_warning}${notify_is_warning_recovery}${notify_is_recovery}${notify_is_no_data}${notify_is_not_alert}${notify_is_not_alert_recovery}${notify_is_not_warning}${notify_is_not_warning_recovery}${notify_is_not_recovery}${notify_is_not_no_data}
作成例
ec2.tf に datadog_monitor の resource 定義をします。
message、escalation_message にテンプレートを設定(data.template_file.〜.rendered 部分)します。
例では2つの resource を定義し、message に個別の記述と、テンプレート記述設定をしています。
resource "datadog_monitor" "ec2_cpuutilization" { type = "query alert" name = "[TEST] EC2 CPU Utilization" query = "max(last_5m):max:aws.ec2.cpuutilization{name:test-instance-al2-0} by {host,name,region} > 99" message = "# [TEST] EC2 CPU Utilization\n${data.template_file.message.rendered}${data.template_file.notify.rendered}" escalation_message = "**Renotify**\n# [TEST] EC2 CPU Utilization\n${data.template_file.message.rendered}${data.template_file.notify.rendered}" ・・・ } resource "datadog_monitor" "ec2_status_check_failed" { type = "query alert" name = "[TEST] EC2 StatusCheckFailed" query = "min(last_15m):max:aws.ec2.status_check_failed{name:test-instance-al2-0} by {host,name,region} > 0" message = "# [TEST] EC2 StatusCheckFailed\n${data.template_file.message.rendered}${data.template_file.notify.rendered}" escalation_message = "**Renotify**\n# [hoge] EC2 StatusCheckFailed\n${data.template_file.message.rendered}${data.template_file.notify.rendered}" ・・・ }
作成結果
通知本文の一部を共通化し、一括更新を行うことができるようになりました。
懸念は Terraform の更新頻度が高いため、仕様変更により動作しなくなる可能性でしょうか。
Datadog側標準機能でテンプレート化、通知先グループの設定などを実装して欲しい所です。