CUEBiC TEC BLOG

キュービックTECチームの技術ネタを投稿しております。

モニタリング運用をDatadogへ集約しました

概要

こんにちは、キュービックでSREをやっているYuhta28です。キュービック内のテック技術について発信します。
キュービックでは監視をMackerel、ログ集約をOpenSearchを活用して運用していました。
OpenSearchを使ったログ集約はこちらの記事を御覧ください。

cuebic.hatenablog.com

今後更にRUMやSLOなどサービス運用改善に向けて攻めの監視を行い、モニタリングからオブザーバビリティにシフトしたいと考えDatadogを導入しモニタリング運用を集約化しました。

オブザーバビリティとは

日本語では可観測性と訳されることが多いです。従来のモニタリング(=監視)では何が起きているかを見続けて事前に定義した指標やログに異常を検出したら対応することを目的としています。
対してオブザーバビリティは予期せぬことが起きたときになぜそれが起きたのかを把握することを目的としています。1

導入

Mackerelでは監視設定をコンソール画面から各種メトリクスのしきい値を設定していました。値が違うだけで監視方法は同じでしたので効率化できないかと考えたところ、DatadogはTerraformで設定できることがわかりました。これならTerraformでIaC化できますし、リポジトリ管理できるのでCI/CD基盤も構築も可能と良いこと尽くめでしたので、Terraform☓Datadog☓GitHub Actionsを使ったモニタリング設計を構築しました。

registry.terraform.io

サンプルコード

# Datadogモジュールのセットアップ
provider "datadog" {
  api_key = var.datadog_api_key
  app_key = var.datadog_app_key
}

terraform {
  required_providers {
    datadog = {
      source  = "DataDog/datadog"
      version = ">= 3.1.2"
    }
  }
  required_version = ">= 0.12.31"
}

# ホスト死活監視
resource "datadog_monitor" "media_alive_monitoring" {
  name                = "{{host.name}} is down!"
  type                = "service check"
  query               = <<-EOT
    "datadog.agent.up".over("*").by("host").last(2).count_by_status()
  EOT
  notify_no_data      = true
  new_group_delay     = 60
  no_data_timeframe   = 2
  require_full_window = false

  # 通知メッセージ
  message = <<-EOT
      {{#is_alert}} ${var.critical_notify_slackchannel}  
      <!here>
      {{host.name}} is down!!
      {{/is_alert}}
      
      {{#is_alert_recovery}} ${var.critical_notify_slackchannel}  
      {{host.name}} is recovery
      {{/is_alert_recovery}}
  EOT

  monitor_thresholds {
    critical = "1"
    ok       = "1"
    warning  = "1"
  }
  tags = ["services:media"]
}

上記はDatadogエージェントを入れたサーバーホストが正しく稼働されているかを確認する死活監視の設定です。過去2分間でサーバーからの反応がなければ緊急通知用のSlackチャンネルに通知を飛ばすようにしています。通知メッセージ部分はDatadogが提供している変数テンプレートがあり、{{host.name}}でEC2のホスト名、{{#is_alert}}{{/is_alert}}でくくるとcritical時のみに中のメッセージを発信できるなどの条件つけがTerraformファイル内に記載できます。

Datadogモニター画面

ログ集約

OpenSearchのときはFluentdを利用してサーバー内のログを集約していました。
Datadogに対応したFluentdプラグイン2がありましたので、設定ファイルにプラグイン設定を追加することで簡単にDatadogへログを集約できました。

# td-agent.conf
  <store>
    @type datadog
    @id nginx-access
    api_key XXXXXXXXXXXXXXXXXXX

    include_tag_key true
    tag_key @log_name

    dd_source 'nginx'
    service   'access-log'
  </store>

Fluentdの設定ファイルにDatadogのAPIキーを記述し、ログのカテゴライズ先を設定すれば集約できます。

Datadogログ画面

SLO導入

今回Datadogへの移行を目的とした一つにSLOの策定があります。Mackerelでもできなくはないですが、Datadogにはマネージドに提供してくれるSLOモニター機能がありましたのでこちらを利用しました。これもTerraformで設定でき以下がSLOモニター作成及びアラート発報ソースコードになります。

SLOコード

# HTTPレスポンスステータスコードの割合を基にSLOを作成
resource "datadog_service_level_objective" "http_response_ok" {
  name        = "HTTP Response Status OK"
  description = "User Agentからのレスポンスに2xx/3xxを返す確率"
  type        = "metric"
  query {
    numerator   = "sum:Agent.Connection.Count.2xx_3xx{domain:*} by {domain}"
    denominator = "sum:Agent.Connection.count{domain:*} by {domain}"
  }

  # 過去7日間のSLOバジェットを作成
  thresholds {
    target    = 99.9
    timeframe = "7d"
    warning   = 99.99
  }
  # 過去30日間のSLOバジェットを作成
  thresholds {
    target    = 99.9
    timeframe = "30d"
    warning   = 99.99
  }
  # 過去90日間のSLOバジェットを作成
  thresholds {
    target    = 99.9
    timeframe = "90d"
    warning   = 99.99
  }

  tags = [
    "services:media"
  ]
}

# SLOバジェットが尽きたらAlertを発報
resource "datadog_monitor" "slo_http_response_ok_monitoring" {
  name = "{{domain.name}} SLO Error Budget consumed"
  type = "slo alert"
  #7日間のエラーバジェットをモニタリング
  query               = "error_budget(\"${datadog_service_level_objective.http_response_ok.id}\").over(\"7d\") > 100"
  notify_no_data      = false
  new_group_delay     = 0
  no_data_timeframe   = 0
  require_full_window = false

  # 通知メッセージ
  message = <<-EOT
      {{#is_alert}} ${var.critical_notify_slackchannel}  
      <!here>
      {{domain.name}} SLO error budget is empty!
      {{/is_alert}}


      {{#is_warning}} ${var.warning_notify_slackchannel}  
      {{domain.name}} SLO error budget is consumed 90%.
      {{/is_warning}}
  EOT

  monitor_thresholds {
    critical = "100"
    warning  = "90"
  }
  tags = [
    "services:media"
  ]
}

SLOの指標は企業によって様々で弊社でもまだ確立したものがありませんが、暫定的にUser Agentからのレスポンスタイムが正常であることを返す確率を基にSLOを作成しました。query部分を見るとわかりますが、ドメイン単位でのグルーピングができますのでこれ一つで弊社の全メディアの個別のSLOが作成できました。

課題

ただ問題がありまして通知メッセージに含まれている{{domain.name}}ドメイン名を変数にしてメッセージ内にどのメディアのエラーバジェットが減っているかわかるようにしたかったのですが、domainを変数として認識せずメッセージ内にメディアのドメイン名が表示されませんでした。

Slackへの通知メッセージに{{domain.name}}部分が記載されていない

Datadogのドキュメント3も参照しましたが、SLOモニターで設定した値を変数化する方法は今の所ないようです。現状はドメイン名をメッセージ内に出すのは諦めてアラートが上がったらダッシュボードから直接確認するようにしています。

よかったこと

Terraformを用いたDatadogへモニタリング運用を移行したことで良かった点です。

  • IaCによる統一されたモニタリング設定
  • GitHub ActionsによるCI/CD基盤の実装
  • SLOの設定

上2つはDatadogというよりもTerraformによる恩恵になりますが、モニタリング設定をコード化してCI/CD基盤を実装できたのは属人性を減らせる大きな一歩になりました。3つ目のSLOはまだ設定しただけこれからどのような効果を産むかはわかりませんが、徐々にカスタマイズしてビジネス側への分析提案できるようにしていきたいと思います。

所感

Datadogへのモニタリング運用移行について紹介しました。Datadogはただ監視するためだけのツールではなく、ビジネス分析や将来的なインパクト予測にも応用がききそうでしたので、初期構築から実装することができてよかったと思います。副次的な効果ですがDatadogに集約したことでMackereのl利用料とOpenSearchのコストの合計値よりも安くなったことも嬉しいオマケでした。
後は改良を進めてモニタリングからオブザービリティへ進化させるようにしていこうと思います。

参考文献

licensecounter.jp

aws.amazon.com