← グループ一覧へ戻る
技術解説

イベント駆動で作る障害検知 ─ 標準メトリクスに出ない失敗を監視する

  • AWS
  • EventBridge
  • CloudWatch
  • 監視
  • Terraform

CPU使用率やリクエスト数のような「量」はCloudWatchの標準メトリクスで監視できる。 しかし運用で本当に知りたい「ECSタスクが異常停止した」「デプロイが失敗した」という出来事は、標準メトリクスには現れない。 本稿では、AWSの3サービスを直列に束ねてイベントをメトリクス化し、通常のアラーム運用に乗せる構成パターンを解説する。

ページ構成

  1. 課題: 「量」は見えるが「出来事」が見えない
  2. 構成: イベント → ログ → メトリクスのパイプライン
  3. 設計判断: なぜLambdaを使わないのか
  4. 監視対象を宣言的に増やす
  5. まとめ

1. 課題: 「量」は見えるが「出来事」が見えない

知りたいこと標準メトリクスで分かるか
ECSサービスのCPU使用率分かる
ALBの5xx応答数分かる
ECSタスクがコンテナ異常で停止した分からない(イベントとしてのみ発生)
CodeDeployのデプロイが失敗した分からない(イベントとしてのみ発生)
RDSのフェイルオーバーが発生した分からない(イベントとしてのみ発生)

下3つはAWS内部でイベントとして発生している。EventBridgeにはこれらのイベントが流れているが、 イベントは「その瞬間に流れて消える」ものであり、そのままではアラームの対象にならない。 「過去5分間に何回発生したか」というに変換して初めて、閾値監視ができる。

2. 構成: イベント → ログ → メトリクスのパイプライン

3つのサービスの役割分担は明確である。

サービス役割得られるもの
EventBridge Ruleイベントパターンで「監視したい出来事」だけを捕捉フィルタリング
CloudWatch Logs捕捉したイベント本文をそのまま記録調査用の一次情報
Metric Filterログの発生件数をカスタムメトリクスに変換アラーム可能な「数」

この構成の利点は、メトリクス化と同時に調査用のログが残ることにある。 アラームが鳴った時、メトリクスは「何回起きたか」しか教えてくれないが、 CloudWatch Logsにはイベント本文(どのクラスタで、どんな理由で停止したか)がJSONで残っているため、そのまま原因調査に入れる。

3. 設計判断: なぜLambdaを使わないのか

イベントをメトリクス化する方法としては、EventBridgeからLambdaを起動してPutMetricDataを呼ぶ構成も考えられる。 あえてLambdaを使わない理由は次の通り。

観点Lambda方式Logs + Metric Filter方式
管理対象関数コード・ランタイム更新・エラーハンドリング宣言的な設定のみ
障害点Lambda自体の失敗(監視の監視が必要になる)マネージド機能のみで完結
一次情報自前でログ出力を実装イベント本文が自動で残る
コスト呼び出し課金 + ログログ保存のみ

監視基盤は「壊れにくいこと」が最優先である。コードを持たず、AWSのマネージド機能の直列接続だけで構成すれば、 監視基盤そのものの運用負荷をほぼゼロにできる。

4. 監視対象を宣言的に増やす

この構成をTerraformモジュールにする際は、「イベントパターン + メトリクス名 + ディメンション」の組をmapで受け取る形にすると、 監視対象の追加が宣言1つで済む。

# 概念例(汎用化した書き方)
monitoring_events = {
  ecs_task_failed = {
    event_pattern = {
      source      = ["aws.ecs"]
      detail-type = ["ECS Task State Change"]
      detail = {
        lastStatus    = ["STOPPED"]
        stoppedReason = [{ "prefix" = "Essential container" }]
      }
    }
    metric_name = "ECSTaskFailed"
    dimensions  = { ClusterName = "$.detail.clusterArn" }
  }
  deploy_failed = {
    event_pattern = {
      source      = ["aws.codedeploy"]
      detail-type = ["CodeDeploy Deployment State-change Notification"]
      detail      = { state = ["FAILURE"] }
    }
    metric_name = "CodeDeployFailed"
    dimensions  = { ApplicationName = "$.detail.application" }
  }
}

ポイントは2つ。

  • イベントパターンはAWSが公式に定義している。「ECS Task State Change」等のイベント構造は各サービスのドキュメントに公開されており、stoppedReasonのprefix一致で「コンテナ起因の停止だけ」を絞り込むような精密なフィルタが書ける
  • ディメンションはJSONPathでイベント本文から抽出する。クラスタ名やアプリケーション名をディメンションにしておけば、1つの仕組みで複数サービスを区別して監視できる

5. まとめ

設計判断内容
イベントは数に変換して監視するEventBridge → Logs → Metric Filterの直列3サービスで実現
コードを持たないLambdaを使わず宣言的設定のみ。監視基盤自体の運用負荷を排除
一次情報を捨てないメトリクスと同時にイベント本文がログに残り、調査に直結
監視対象はmapで一括管理イベントパターンの追加 = 監視対象の追加

「CPUは正常なのにサービスが動いていない」という状況の多くは、標準メトリクスの外側で起きた出来事が原因である。 イベントをメトリクスに変換する小さなパイプラインを1つ持っておくと、監視の空白地帯を宣言1つずつ埋めていける。