JINS Advent calendar 10日目もITデジタル部の大間が担当します。
何の話?
8日目のアドベントカレンダーで@Takuma_Satoからもありましたが、Observabilityの観点でモニタリングやアラートを仕込んで管理することが重要になっており、その目的で直近JINSではDatadogを導入しサービス監視を始めました!
導入するにあたり、もちろん元々は別のツールを使って監視をしておりそこからDatadogに移行する必要があり、その中で取り組んだことのお話です。
やってきたこと
STEP1
元々のツールの監視設定をDatadogに持ってくるにあたり、Datadog上で対象の監視設定のMonitorを作成する必要がありました。
はじめのうちはGUIでMonitorポチポチ作っていたのですが....とてもしんどい...
(こういうのをひたすら作り続ける....)
例えば、ログ監視の設定であれば、一つログ監視のMonitorを作って、それをcloneして対象インスタンスや条件を変えてを繰り返して対象のMonitorを数十と作成してました。
そんな中で課題として出てきたのは
- まず、ポチポチGUIから設定する作業がなかなかに手間がかかる
- GUIからの作成なのでレビューがやりづらく、設定ミスが発生しうる
- 実際いくつか後々気づいた設定ミスも....
そんな中で、Datadog ProviderがTerraformにあるということを知り、「あれ、これ使えるのでは」となりました。
元々、JINSではIaCツールとしてterraformを使い始めていたので、Terraformは好都合でした。
Monitoring as Codeやってみようというやつですね!
STEP2
そんなわけでterraformでMonitorを作り始めてみました。
terraform {
required_version = "1.2.4"
required_providers {
datadog = {
source = "datadog/datadog"
version = "3.25.0"
}
}
}
locals {
alert_notify_join = join(" ", var.alert_notify )
}
data "template_file" "message" {
template = file("${path.module}/LOG.tmpl")
vars = {
critical = "${var.critical}"
alert_notify = "${local.alert_notify_join}"
error_message = "${var.error_message}"
}
}
resource "datadog_monitor" "log_monitor" {
enable_logs_sample = "false"
escalation_message = ""
evaluation_delay = "0"
groupby_simple_monitor = "false"
include_tags = "false"
message = data.template_file.message.rendered
monitor_thresholds {
critical = "${var.critical}"
}
name = "{{#is_alert}}[Alert]{{/is_alert}}${var.error_message}"
new_group_delay = "60"
no_data_timeframe = "0"
notify_audit = "false"
notify_by = ["*"]
notify_no_data = "false"
priority = "0"
query = "logs(\"log conditions\").index(\"*\").rollup(\"count\").by(\"host\").last(\"5m\") >= 1"
renotify_interval = "5"
renotify_occurrences = "0"
renotify_statuses = ["alert"]
require_full_window = "false"
tags = "${var.tags}"
timeout_h = "0"
type = "log alert"
}
■本文
検知日時: {{local_time 'last_triggered_at' 'Asia/Tokyo'}}
ホスト名: {{log.tags.name}}
メッセージ: ${error_message}
■イベントログ
種類: {{log.status}}
日時: {{local_time 'last_triggered_at' 'Asia/Tokyo'}}
ソース:{{log.service}}
説明:
{{log.message}}
通知先:
{{#is_alert}}
${alert_notify}
{{/is_alert}}
個人的工夫ポイントとしては、templateを使って改行も含めてメッセージをいい感じにするあたりです!
datadog monitor
リソースのmessage
に直接渡すことももちろんできるのですが、1行の中に改行コードも混ぜながら記述しないといけなく、やはりコードが見にくくなるな...と。
アラート発報の際にはAlertかWarningかによって通知先を分けたり、通知文言を変えたりもして結構メッセージが条件分岐含めてメッセージ内容が長くなりがちなので、ここをtemplateにした&通知先や文言も変数で外だしはある程度きれいな形にできたかなと考えています。
これでMonitoring as Codeはでき、GUIでポチポチしなくてよいし、コードレビューで品質も保ちやすくなりました!
一方でもちろんファイル分割の仕方次第ではありますが、main.tf
の中でずらずらとたくさんリソースを並べてしまうとコードも長くなってしまいがちです。
そこでモジュール化です!
STEP3
STEP2で作成していたtfファイルをモジュールとして読み込む形にしました。
#--------------------------
# LOG監視用のmonitor
#--------------------------
module "log_monitor" {
source = "git::ssh://xxxx.git//LOG?ref=v1.0"
stage = local.stage
tags = ["AWS", "LOG", "TF_V1"]
log_source = "xxxx.log"
log_condition = "filename:xxxx.log \\\"ERROR\\""
error_message = "xxxx.logにERRORメッセージが出力されました"
alert_notify = local.alert_notify
}
モジュール自体もリポジトリでバージョン管理し、gitからsourceを読み込む形にしています。
また、sourceを読み込む際もgitのタグを指定し、さらにdatadogのタグにもTF_v1
のように使用しているモジュールのバージョンを指定して、デグレないような仕組みも工夫してあります。
こういったモジュールをリソース監視用、ログ監視用、プロセス監視用など複数用意しておき、必要な監視が出てきた際にはそのモジュールを呼んでMonitorを作成する方式としました。
まとめ
GUIからぽちぽちしていた際と比べると、Terraformによるコード化、さらにそれらのモジュール化によって手間の削減や品質向上が少なからず進んだかしらと考えています(きっと)!
少なくともコード化してリポジトリ管理されたことで、作成時あるいは変更時にプルリクでレビューができるようになり、「実装したんだけどなんか間違ってね?」なMonitorが減ったことは間違い無いです。
機会があればどこかで書きますが、DatadogはAgentの導入や設定の際のAnsibleの活用も少しずつ進めており、色々とコード化の仕組みを進めております。
現在はこの辺の仕組みはごく一部のインフラ寄りのメンバだけでやっていますが、コード化されることでもっとアプリ寄りなメンバも自分たちでMonitorの設定ができるようになり自分が楽にDatadogの活用がより進めばよいなーと思っています。
明日は初日にNWな話を書いてくれた@knt-okadaが、今度はCloudな話をしてくれるのでお楽しみに〜