Terraform で Datadog のモニターを管理する方法を試してみた

Terraform で Datadog のモニターを管理する方法を試してみた

Clock Icon2025.02.18

こんにちは。テクニカルサポートチームのShiinaです。

はじめに

Terraform は、クラウドや SaaS のリソースをコードで管理できる IaC(Infrastructure as Code)ツールです。
宣言的な構文でインフラを定義し、自動で作成・変更・削除できます。
本記事では、Terraform を使って Datadog のリソースを管理する方法を解説します。
Datadog API キーと APP キーの発行、Terraform の初期設定、サンプルコードを用いたリソース作成を紹介します。
さらに、既存リソースのインポートやカスタムイベントの送信方法についても説明します。
Terraform を活用して Datadog の設定を効率的に管理したい方は、ぜひ参考にしてください。

事前準備

Datadog API キーと APP キーの発行

Terraform を利用するには Datadog API キーと APP キーが必要となります。

  • Datadog API キー発行
    Organization Settings の API Keys を選択します。
    New API Key を選択し、キーを発行します。
    APIキー発行

  • Datadog APP キー発行
    Organization Settings の Application Keys を選択します。
    New Key を選択し、キーを発行します。
    Applicationキー発行

Terraform インストール

公式サイトを参考に Terraform をインストールします。
https://developer.hashicorp.com/terraform/tutorials/aws-get-started/install-cli

Terraform を使用して新規リソースを作成する方法

1.Datadog プロバイダーの構成

任意のディレクトリを作成します。

作成したディレクトリに移動し、以下の内容の main.tf ファイルを作成します。

main.tf
terraform {
  required_providers {
    datadog = {
      source = "DataDog/datadog"
    }
  }
}

# Configure the Datadog provider
provider "datadog" {
}

Datadog API キーと APP キーを環境変数にセットします。

export DD_API_KEY=xxxxxxxxx
export DD_APP_KEY=yyyyyyyyy

初期化とプロバイダーのプルを行います。

terraform init
出力結果
Initializing the backend...
Initializing provider plugins...
- Finding latest version of datadog/datadog...
- Installing datadog/datadog v3.54.0...
- Installed datadog/datadog v3.54.0 (signed by a HashiCorp partner, key ID FB70BE941301C3EA)
Partner and community providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:
https://www.terraform.io/docs/cli/plugins/signing.html
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

ディレクトリ内に任意の .tf ファイルを作成し、コードを記述していきます。

2.リソース反映

記述が完了したら、リソースの反映を行います。

terraform apply
出力結果
Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

datadog_monitor.cpumonitor: Creating...
datadog_monitor.log_monitor: Creating...
datadog_monitor.process_monitor: Creating...
datadog_monitor.liveprocess_monitor: Creating...
datadog_monitor.log_monitor: Creation complete after 1s [id=164867835]
datadog_monitor.cpumonitor: Creation complete after 1s [id=164867834]
datadog_downtime_schedule.cpumonitor_downtime: Creating...
datadog_monitor.process_monitor: Creation complete after 1s [id=164867836]
datadog_monitor.liveprocess_monitor: Creation complete after 1s [id=164867837]
datadog_downtime_schedule.cpumonitor_downtime: Creation complete after 1s [id=f00cba83-43aa-4b39-99d2-239e7f44293f]

Apply complete! Resources: 5 added, 0 changed, 0 destroyed.

サンプルコード

サンプルコードの確認方法

次の2つの手段があります。

Terraform ドキュメントを利用する
以下のドキュメントより、モニターの作成やインテグレーションの設定などのリファレンスを確認できます。
https://registry.terraform.io/providers/DataDog/datadog/latest/docs/guides/monitors

Datadog コンソールを利用する
Datadog コンソールで確認できます。
※2025年2月時点ではモニターの作成のみに対応しています。
Monitors より Monitors List を選択します。
monitor-menu

一覧より確認したいモニターを選択します。
歯車マークより Export Monitor を選択します。
エクスポート1

Terraform タブを選択します。
エクスポート2

メトリクスモニター

aws.ec2.cpuutilization メトリクスの閾値を監視するモニター

resource "datadog_monitor" "cpumonitor" {
  name                = "EC2 CPU Monitor"
  type                = "metric alert"
  message             = "CPU usage alert triggered. @your_notification@example.com"
  query               = "avg(last_15m):avg:aws.ec2.cpuutilization{env:prod} by {host} > 80"
  evaluation_delay    = 900
  new_group_delay     = 300
  require_full_window = false
  tags                = ["env:prod", "layer:backend"]
}

メトリクスモニター2

サービスチェックモニター

nginx プロセスを監視する process.up サービスチェックモニター

resource "datadog_monitor" "process_monitor" {
  name    = "Nginx Process Monitor"
  type    = "service check"
  message = "Nginx process alert triggered. @your_notification@example.com"
  query   = "\"process.up\".over(\"env:prod\",\"process:nginx\").by(\"host\").last(5).count_by_status()"
  monitor_thresholds {
    warning  = 2
    critical = 4
  }
  tags = ["env:prod", "layer:backend"]
}

サービスチェックモニター

ライブプロセスモニター

amazon-ssm-agent プロセスを監視するライブプロセスモニター

resource "datadog_monitor" "liveprocess_monitor" {
  name            = "Amazon SSM Agent Process Monitor"
  type            = "process alert"
  message         = "Amazon SSM Agent process is not running on some hosts. @your_notification@example.com"
  query           = "processes('amazon-ssm-agent').over('env:prod').rollup('count').last('5m') < 1"
  on_missing_data = "default"
  tags            = ["env:prod", "layer:backend"]
}

ログモニター

*failed* 文字列を含むエラーメッセージを監視するログモニター

resource "datadog_monitor" "log_monitor" {
  name                   = "Nginx Error Log Monitor"
  type                   = "log alert"
  groupby_simple_monitor = false
  include_tags           = false
  require_full_window    = false
  query                  = "logs(\"env:prod source:nginx @error.message:*failed*\").index(\"*\").rollup(\"count\").last(\"5m\") >= 1"
  message                = "Nginx Error Log Detected. @your_notification@example.com"
  tags                   = ["env:prod", "layer:backend"]
}

ログモニター

ダウンタイム(モニター ID 指定)

モニター ID 指定したダウンタイムを行う設定

resource "datadog_downtime_schedule" "cpumonitor_downtime" {
  scope = "*"

  monitor_identifier {
    monitor_id = datadog_monitor.cpumonitor.id
  }

  recurring_schedule {
    recurrence {
      duration = "1d" # 1日
      rrule    = "FREQ=WEEKLY;INTERVAL=1;BYDAY=SU,SA"
      start    = "2025-02-15T00:00:00"
    }
    timezone = "Asia/Tokyo"
  }

  display_timezone                 = "Asia/Tokyo"
  message                          = "Scheduled downtime for CPU monitor"
  mute_first_recovery_notification = false
  notify_end_states                = ["alert", "warn", "no data"]
  notify_end_types                 = ["canceled", "expired"]
}

ダウンタイムスケジュール(モニターid)

ダウンタイム(タグ指定)

モニターのタグを指定したダウンタイムを行う設定

resource "datadog_downtime_schedule" "prod_backend_downtime" {
  scope = "*"

  monitor_identifier {
    monitor_tags = ["env:prod", "layer:backend"]
  }

  recurring_schedule {
    recurrence {
      duration = "6h" # 6hours
      rrule    = "FREQ=DAILY;INTERVAL=1"
      start    = "2025-02-15T00:00:00"
    }
    timezone = "Asia/Tokyo"
  }

  display_timezone                 = "Asia/Tokyo"
  message                          = "Scheduled downtime for Production backend"
  mute_first_recovery_notification = false
  notify_end_states                = ["alert", "warn", "no data"]
  notify_end_types                 = ["canceled", "expired"]
}

ダウンタイムスケジュール(モニタータグ)

既存リソースをインポートする方法

1.terraformer インストール

terraformer のインストールを行います。

export PROVIDER=all
curl -LO https://github.com/GoogleCloudPlatform/terraformer/releases/download/$(curl -s https://api.github.com/repos/GoogleCloudPlatform/terraformer/releases/latest | grep tag_name | cut -d '"' -f 4)/terraformer-${PROVIDER}-linux-amd64
chmod +x terraformer-${PROVIDER}-linux-amd64
sudo mv terraformer-${PROVIDER}-linux-amd64 /usr/local/bin/terraformer

2.Datadog プロバイダーの構成

任意のディレクトリを作成します。

作成したディレクトリ移動し、以下の内容の main.tf ファイルを作成します。

main.tf
terraform {
  required_providers {
    datadog = {
      source = "DataDog/datadog"
    }
  }
}

# Configure the Datadog provider
provider "datadog" {
}

Datadog API キーと APP キー、Datadog サイト URL を環境変数にセットします。

export DD_API_KEY=xxxxxxxxx
export DD_APP_KEY=yyyyyyyyy
export DD_SITE=https://api.datadoghq.com

初期化とプロバイダーのプルを行います。

terraform init
出力結果
Initializing the backend...
Initializing provider plugins...
- Finding latest version of datadog/datadog...
- Installing datadog/datadog v3.54.0...
- Installed datadog/datadog v3.54.0 (signed by a HashiCorp partner, key ID FB70BE941301C3EA)
Partner and community providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:
https://www.terraform.io/docs/cli/plugins/signing.html
Terraform has created a lock file .terraform.lock.hcl to record the provider
selections it made above. Include this file in your version control repository
so that Terraform can guarantee to make the same selections by default when
you run "terraform init" in the future.

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

3.インポート

インポートコマンドを実行します。

terraformer import datadog --resources=* --api-key $DD_API_KEY --app-key $DD_APP_KEY --api-url $DD_SITE

resource 引数でリソースを指定してインポートすることも可能です。

  • モニターリソースのみインポートする例
terraformer import datadog --resources=monitor --api-key $DD_API_KEY --app-key $DD_APP_KEY --api-url $DD_SITE
出力結果
2025/02/14 08:59:10 Attempting an import of ALL resources in datadog
2025/02/14 08:59:11 datadog importing... dashboard
2025/02/14 08:59:12 datadog done importing dashboard
2025/02/14 08:59:12 datadog importing... dashboard_json
2025/02/14 08:59:12 datadog done importing dashboard_json
2025/02/14 08:59:12 datadog importing... dashboard_list
2025/02/14 08:59:12 datadog done importing dashboard_list
2025/02/14 08:59:12 datadog importing... downtime
2025/02/14 08:59:13 datadog done importing downtime
2025/02/14 08:59:13 datadog importing... integration_aws
2025/02/14 08:59:13 datadog done importing integration_aws
2025/02/14 08:59:13 datadog importing... integration_aws_lambda_arn
2025/02/14 08:59:13 datadog done importing integration_aws_lambda_arn
2025/02/14 08:59:13 datadog importing... integration_aws_log_collection
2025/02/14 08:59:13 datadog done importing integration_aws_log_collection
2025/02/14 08:59:13 datadog importing... integration_azure
2025/02/14 08:59:13 datadog error initializing resources in service integration_azure, err: 400 Bad Request
2025/02/14 08:59:13 datadog importing... integration_gcp
2025/02/14 08:59:14 datadog error initializing resources in service integration_gcp, err: 400 Bad Request
2025/02/14 08:59:14 datadog importing... integration_pagerduty
2025/02/14 08:59:14 datadog error initializing resources in service integration_pagerduty, err: API error 404 Not Found: {"errors":["pagerduty not found"]}
2025/02/14 08:59:14 datadog importing... integration_pagerduty_service_object
2025/02/14 08:59:14 datadog error initializing resources in service integration_pagerduty_service_object, err: API error 404 Not Found: {"errors":["pagerduty not found"]}
2025/02/14 08:59:14 datadog importing... integration_slack_channel
2025/02/14 08:59:14 Filter(account_name or resource id) is required to import datadog_integration_slack_channel resource
(中略)

4.生成ファイルの確認

ディレクトリ配下に既存リソースから生成された tf.ファイルが出力されます。

出力ファイル例
├── generated
│   └── datadog
│       ├── dashboard
│       │   ├── provider.tf
│       │   ├── terraform.tfstate
│       │   └── variables.tf
│       ├── dashboard_json
│       │   ├── provider.tf
│       │   └── terraform.tfstate
│       ├── dashboard_list
│       │   ├── provider.tf
│       │   ├── terraform.tfstate
│       │   └── variables.tf
│       ├── downtime
│       │   ├── provider.tf
│       │   ├── terraform.tfstate
│       │   └── variables.tf
│       ├── integration_aws
│       │   ├── integration_aws.tf
│       │   ├── outputs.tf
│       │   ├── provider.tf
│       │   └── terraform.tfstate
│       ├── integration_aws_lambda_arn
│       │   ├── provider.tf
│       │   ├── terraform.tfstate
│       │   └── variables.tf
│       ├── integration_aws_log_collection
│       │   ├── provider.tf
│       │   ├── terraform.tfstate
│       │   └── variables.tf
│       ├── integration_slack_channel
│       │   ├── provider.tf
│       │   └── terraform.tfstate
│       ├── logs_archive
│       │   ├── logs_archive.tf
│       │   ├── outputs.tf
│       │   ├── provider.tf
│       │   ├── terraform.tfstate
│       │   └── variables.tf
│       ├── logs_archive_order
│       │   ├── logs_archive_order.tf
│       │   ├── outputs.tf
│       │   ├── provider.tf
│       │   ├── terraform.tfstate
│       │   └── variables.tf
│       ├── logs_custom_pipeline
│       │   ├── logs_custom_pipeline.tf
│       │   ├── outputs.tf
│       │   ├── provider.tf
│       │   └── terraform.tfstate
│       ├── logs_index
│       │   ├── logs_index.tf
│       │   ├── outputs.tf
│       │   ├── provider.tf
│       │   └── terraform.tfstate
│       ├── logs_index_order
│       │   ├── logs_index_order.tf
│       │   ├── outputs.tf
│       │   ├── provider.tf
│       │   ├── terraform.tfstate
│       │   └── variables.tf
│       ├── logs_integration_pipeline
│       │   ├── logs_integration_pipeline.tf
│       │   ├── outputs.tf
│       │   ├── provider.tf
│       │   └── terraform.tfstate
│       ├── logs_metric
│       │   ├── provider.tf
│       │   └── terraform.tfstate
│       ├── logs_pipeline_order
│       │   ├── logs_pipeline_order.tf
│       │   ├── outputs.tf
│       │   ├── provider.tf
│       │   ├── terraform.tfstate
│       │   └── variables.tf
│       ├── metric_metadata
│       │   ├── provider.tf
│       │   └── terraform.tfstate
│       ├── monitor
│       │   ├── monitor.tf
│       │   ├── outputs.tf
│       │   ├── provider.tf
│       │   ├── terraform.tfstate
│       │   └── variables.tf
│       ├── role
│       │   ├── outputs.tf
│       │   ├── provider.tf
│       │   ├── role.tf
│       │   └── terraform.tfstate
│       ├── service_level_objective
│       │   ├── provider.tf
│       │   ├── terraform.tfstate
│       │   └── variables.tf
│       ├── synthetics_global_variable
│       │   ├── provider.tf
│       │   ├── terraform.tfstate
│       │   └── variables.tf
│       ├── synthetics_private_location
│       │   ├── outputs.tf
│       │   ├── provider.tf
│       │   ├── synthetics_private_location.tf
│       │   └── terraform.tfstate
│       ├── synthetics_test
│       │   ├── outputs.tf
│       │   ├── provider.tf
│       │   ├── synthetics_test.tf
│       │   ├── terraform.tfstate
│       │   └── variables.tf
│       └── user
│           ├── outputs.tf
│           ├── provider.tf
│           ├── terraform.tfstate
│           ├── user.tf
│           └── variables.tf
└── main.tf

カスタムイベントを送信する

Dogwrap コマンドラインツールを使用すると、任意のコマンドを呼び出し、その結果をイベントとして送信できます。
そのため、 terraform apply コマンドの実行イベント自体を Datadog で管理することができます。

1.Datadog Python ライブラリのインストール

仮想環境を有効化してパッケージのインストールを行います。

sudo apt install python3-pip python3.12-venv
python3 -m venv myenv
source myenv/bin/activate
pip install datadog

2.イベント送信

Datadog API キーを環境変数にセットします。

export DD_API_KEY=xxxxxxxxx

Dogwrap コマンドラインツールを使用して terraform apply 実行イベントをカスタムイベントとして送信します。

dogwrap -n "terraform apply" -k $DD_API_KEY --submit_mode all --tags="source:terraform" "terraform apply"

3.イベント確認

Service Mgmt の Event Explorer を選択します。
eventexploer-menu

クエリフィールドにsource:terraform と入力し、イベントをフィルタします。
event explorer フィルター

該当のイベントを選択します。
コマンド、終了コード、標準出力がイベントとして記録されていることが確認できます。
Events-Explorer-Datadog-02-18-2025_06_04_PM

まとめ

Terraform を使用すると、Datadog の設定管理を効率化できます。
サンプルコードやインポート機能を活用することで、複雑な監視設定も数行のコードで実現が可能になります。
設定の自動化とバージョン管理を実現しつつ、手作業での設定ミスも減らせるため、運用品質の向上が期待できます。

本記事が誰かのお役に立てれば幸いです。

参考

https://docs.datadoghq.com/ja/integrations/terraform/
https://docs.datadoghq.com/ja/containers/guide/how-to-import-datadog-resources-into-terraform/
https://registry.terraform.io/providers/DataDog/datadog/latest/docs
https://github.com/GoogleCloudPlatform/terraformer/blob/master/docs/datadog.md

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.