CPU使用率やリクエスト数のような「量」はCloudWatchの標準メトリクスで監視できる。 しかし運用で本当に知りたい「ECSタスクが異常停止した」「デプロイが失敗した」という出来事は、標準メトリクスには現れない。 本稿では、AWSの3サービスを直列に束ねてイベントをメトリクス化し、通常のアラーム運用に乗せる構成パターンを解説する。
ページ構成
- 課題: 「量」は見えるが「出来事」が見えない
- 構成: イベント → ログ → メトリクスのパイプライン
- 設計判断: なぜLambdaを使わないのか
- 監視対象を宣言的に増やす
- まとめ
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つずつ埋めていける。