MNTSQ Techブログ

リーガルテック・カンパニー「MNTSQ(モンテスキュー)」のTechブログです。

ECSのオートスケールイベントをDatadog経由でSlackに通知してみる

MNTSQ Tech Blog TOP > 記事一覧 > ECSのオートスケールイベントをDatadog経由でSlackに通知してみる

はじめに

ECSのオートスケールは、一度設定してしまえば非常に便利ですが、人の手を離れて安定運用に乗せるまでには様々な技術的なハードルがあります。安定運用に入るまでは、現在の設定は妥当なのかを判断するため、オートスケールが発生したことを何らかの方法で人間が把握し、日々改善を重ねていくことが必要不可欠です。そこで今回は、ECSのオートスケールイベントをEventBridgeで拾い、Datadogに連携してSlack通知する仕組みを実装してみます。

構成

全体の構成は以下の通りです。ECSクラスタやサービスを限定せずに、オートスケールイベントが発生した時に通知を行うような汎用的な仕組みを作っていきます。

  1. オートスケールのイベントをEventBridgeで拾う
  2. Datadog Event Management APIからDatadogに連携する
  3. Datadog Event Monitorにてアラートの設定を行う
  4. Slackにメッセージを送信する

実装してみる

EventBridge

EventBridge API destinationsの設定

EventBridgeでは、API destinations(API送信先)を設定することによって、AWS内のイベントを任意のAPIに連携することができます。 以下のサンプルコードにて、API destinationsおよび必要なIAMリソースを作成します。DATADOG_API_KEYはあらかじめSecrets Managerに登録されているものとしています。

サンプルコード

# IAM
data "aws_iam_policy_document" "eventbridge_sts" {
  statement {
    effect  = "Allow"
    actions = ["sts:AssumeRole"]

    principals {
      type        = "Service"
      identifiers = ["events.amazonaws.com"]
    }
  }
}

data "aws_iam_policy_document" "eventbridge_datadog" {
  statement {
    effect    = "Allow"
    actions   = ["events:InvokeApiDestination"]
    resources = [aws_cloudwatch_event_api_destination.datadog.arn]
  }

  statement {
    effect = "Allow"

    actions = [
      "secretsmanager:DescribeSecret",
      "secretsmanager:GetSecretValue",
    ]

    resources = ["arn:aws:secretsmanager:*:*:secret:events!connection/<DATADOG_API_KEYのシークレット名>/*"]
  }
}

resource "aws_iam_role" "eventbridge_datadog" {
  name               = "eventbridge_datadog_role"
  assume_role_policy = data.aws_iam_policy_document.eventbridge_sts.json
}

resource "aws_iam_role_policy" "eventbridge_datadog" {
  name   = aws_iam_role.eventbridge_datadog.name
  role   = aws_iam_role.eventbridge_datadog.id
  policy = data.aws_iam_policy_document.eventbridge_datadog.json
}

# あらかじめSecretsManagerにDATADOG_API_KEYを登録しておくこと
data "aws_secretsmanager_secret_version" "datadog_api_key" {
  secret_id = "<DATADOG_API_KEYのシークレット名>"
}

# Connection
resource "aws_cloudwatch_event_connection" "datadog" {
  name = "datadog-event-api"

  authorization_type = "API_KEY"
  auth_parameters {
    api_key {
      key   = "DD-API-KEY"
      value = data.aws_secretsmanager_secret_version.datadog_api_key.secret_string
    }
  }
}

resource "aws_cloudwatch_event_api_destination" "datadog" {
  name                             = "datadog-event-api"
  connection_arn                   = aws_cloudwatch_event_connection.datadog.arn
  invocation_endpoint              = "https://api.datadoghq.com/api/v1/events"
  http_method                      = "POST"
  invocation_rate_limit_per_second = 10
}

EventBridgeのマネジメントコンソール左側のツリーから「API送信先」および「接続」を確認し、"datadog-event-api"のリソースが作成されていたらOKです。

オートスケールイベントを拾うためのEventルールを作成する

ECSのオートスケールイベントは、一例としては以下のように、"aws.ecs"の"UpdateService"イベントを呼び元の"userIdentity"で絞ることによって判別することができます。"aws.application-autoscaling"のイベントもありますが、こちらで設定してもスケールの最大値に達した時しかトリガされないようです。ただでさえ動作確認が大変なところなので、気をつけましょう。

{
  "detail-type": ["AWS API Call via CloudTrail"],
  "source": ["aws.ecs"],
  "detail": {
    "userIdentity": {
      "invokedBy": ["ecs.application-autoscaling.amazonaws.com"]
    },
    "eventSource": ["ecs.amazonaws.com"],
    "eventName": ["UpdateService"]
  }
}
※今回やってはいけないイベントパターンの設定(スケール最大値に達した時しか発生しない)
{
  "source": ["aws.application-autoscaling"]
  "detail-type": ["Application Auto Scaling Scaling Activity State Change"]
}

ターゲットには、先ほど作成したAPI destinationsを指定します。 また、拾ったイベントのjsonAPIのリクエストボディによしなに整形するため、入力トランスフォーマを以下のように設定します。 入力パスで使用したい変数をバインドし、入力テンプレートでリクエストボディを作成しています。

※ 入力パス
{
  "newDesiredCount": "$.detail.requestParameters.desiredCount",
  "service": "$.detail.requestParameters.service"
}
※ 入力テンプレート
{
  "title": "ECS Cluster Auto Scaling",
  "source_type_name": "amazon ecs",
  "alert_type": "info",
  "text": "%%%`<service>` is auto scaled.\n New desiredCount: <newDesiredCount> %%%",
  "tags": [
    "environment:development",
    "source:amazon_ecs",
    "aws_account:************",
    "new_desired_count:<newDesiredCount>",
    "ecs_service_name:<service>"
  ]
}

これらの設定のサンプルコードです。

サンプルコード

# ECSサービスのオートスケールを検知して通知するイベント
resource "aws_cloudwatch_event_rule" "ecs_service_autoscale" {
  name = "ecs-service-autoscale"

  event_pattern = jsonencode({
    detail-type = ["AWS API Call via CloudTrail"]
    source      = ["aws.ecs"]
    detail = {
      userIdentity = {
        invokedBy = ["ecs.application-autoscaling.amazonaws.com"]
      }
      eventSource = ["ecs.amazonaws.com"],
      eventName   = ["UpdateService"]
    }
  })
}

# API destinationsをターゲットに設定
resource "aws_cloudwatch_event_target" "ecs_service_autoscale" {
  rule     = aws_cloudwatch_event_rule.ecs_service_autoscale.name
  arn      = aws_cloudwatch_event_api_destination.datadog.arn
  role_arn = aws_iam_role.eventbridge_datadog.arn

  input_transformer {
    input_paths = {
      newDesiredCount = "$.detail.requestParameters.desiredCount",
      service         = "$.detail.requestParameters.service"
    }

    # jsonencodeが特殊文字をエスケープしてしまうので、ヒアドキュメントを使用する
    input_template = <<EOF
    {
      "title": "ECS Service Auto Scaling",
      "source_type_name": "amazon ecs",
      "alert_type": "info",
      "text": "%%%`<service>` is auto scaled.\n New desiredCount: <newDesiredCount> %%%",
      "tags": [
        "environment:development",
        "source:amazon_ecs",
        "aws_account:**********",
        "event_name:ecs_service_autoscaled",
        "new_desired_count:<newDesiredCount>",
        "ecs_service_name:<service>"
      ]
    }
    EOF
  }
}

Eventルールが作成されたら、何らかの方法でECSサービスをオートスケールさせてみましょう。DatadogのEvent Explorerhttps://.datadoghq.com/event/explorer)にて以下のようなイベントが飛んできていることを確認します。"event_name:ecs_service_autoscaled "でクエリをすれば出てくるはずです。

※ イベントがDatadogに飛んでこない時

イベントが飛ばない時は以下を行いましょう

  • EventルールのターゲットにCloudWatchを設定
    コンソールからEventルールを選択し、「ターゲット」のタブから「編集」でCloudWatchロググループを追加します。追加の権限などは不要なはずです。イベントが正しく拾えていれば、設定したロググループにログストリームが生成されているはずです。また、ロググループからイベントの詳細を確認できるので、入力テンプレートの情報を充実させたい場合などにもこちらを参照します。

  • EventルールのAPI destinationsのターゲットにDLQを設定する
    コンソールからEventルールを選択し、「ターゲット」のタブから「編集」-> 「ターゲットを選択」のページに移動します。ターゲットは複数設定できますが、API destinationsのものを選び、「追加設定」から以下のようにDLQを設定します。DatadogのAPIを読んだ時にエラーが返ってきていた場合は、設定したキューを確認することでレスポンスを確認できます。

Datadog

Slack連携の設定

Slack通知を行うためには、あらかじめDatadogとSlack側で簡単な設定が必要です。本記事では設定方法の説明は割愛するので、公式ドキュメントを参考に設定を行ってください。

docs.datadoghq.com

Event Monitorの設定

Datadogコンソールの左側のツリーから「Monitors」を選択し、遷移後画面の左上にある「+New Monitor」をクリックします。(もしくはブラウザにhttps://.datadoghq.com/monitors/createを入力)作成画面では「Event」を選択します。

1. Define the search queryを以下のように設定します

  • クエリの欄に"event_name:ecs_service_autoscaled "を入力 "ecs_service_autoscaled"は入力テンプレートで独自定義したものなので、これで目的のイベントのみを拾います

  • by句に"new_desired_count"と"ecs_service_name"を入力
    サービス, スケールイベントごとに通知が飛ぶようにマルチモニター化します。また、ここでby句に指定したTagsのみが通知メッセージに埋め込み可能になります。

2. Set alert conditionsを以下のように設定します

  • Trigger when the evaluated value is "above or equal to"に設定
    イベント発生を検知したいので データ点1以上でWarnアラートを飛ばせるように設定します

  • Alert thresholdを適当な大きな値に設定
    オートスケールイベントの通知はWarnレベルで行いたいので、Alertレベルの通知は行わないように、適当に大きな値にします。(本当はInfoレベルにしたいですが、2025/06現在ではDatadogの仕様上不可能と回答をサポートの方にいただきました)

  • Warning thresholdを1に設定 イベントが起きる毎に通知を行いたいので、1に設定します

3. Configure notifications & automationsをお好みで設定します
以下は設定例です。{{ }}で囲んである部分には、「EventのTagsに設定されている」かつ「by句で指定している」値のみ埋め込めます。通知をリッチにしたい場合は、 AWSのEventルール側で入力テンプレートの"tags"を充実させ、DatadogのEvent Monitor側のby句でも使用したいTagsを指定しましょう。また、メッセージ全体を{{#is_warning}}{{/is_warning}}で囲えば、Warn状態からのリカバリ時の通知が飛ばなくなります。

以上で、オートスケールイベントが起きた時に、以下のようにSlackに通知が飛ぶようになりました。

おわりに

とりあえずEventBridge -> Datadog -> Slackの通知ができそうだということで仕組みを作成してみましたが、思ったよりも通知がゴチャついてしまったなという印象があります。(通知タイトルに "on ecs_service_name:~"ってついてしまうなど)もしかしたら、以前紹介したAmazon Q Developer in chat applications(旧: AWS Chatbot)を使用した仕組みの方が、スマートに通知できたような気もしています。とはいえオートスケールイベントを通知するという目的は達成しており、監視・モニタリング系の管理をDatadogに集約することには運用上のメリットもあるので、そことの兼ね合いでもあると思います。ここら辺は今後のDatadogのアップデートにも期待ですね。

MNTSQ株式会社 SRE 西室