概要
AWS CloudWatchのアラームを利用して、とある既存アプリケーション(ECSコンテナ)で指定した閾値を超えた場合にアラートが出るようにしていました。今回、同じアラーム設定内容をセットで別の新規アプリを導入したところ、一方で閾値を超えると両方のアラートが飛んできてしまう現象に遭遇しました。
こちらの原因と解決法がわかったので紹介します。
前提
既存アプリで使っていたアラームの設定は以下の内容です。
管理コンソールから確認すると以下の通りです。
Cloudformationテンプレートは以下の内容で設定していました。
NginxLogAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmActions:
- !Ref SampleTopic
Namespace: 'Nginx'
MetricName: 'Error'
ComparisonOperator: GreaterThanOrEqualToThreshold
EvaluationPeriods: '1'
Period: 60
Statistic: Sum
Threshold: 1
TreatMissingData: notBreaching
NginxMetricFilter:
Type: AWS::Logs::MetricFilter
Properties:
LogGroupName: '/aws/ecs/docker'
FilterPattern: 'ERROR'
MetricTransformations:
-
MetricValue: '1'
MetricNamespace: 'Nginx'
MetricName: 'Error'
これは、/aws/ecs/docker
ロググループ内のERROR
という文字列を含むログイベントを検出し、それをNginx
名前空間のError
メトリクスとしてCloudWatchに送信する、という設定になります。
ERROR
をフィルターしていたのは、GunicornやuWSGIでエラーが起きる時に以下のようなエラーメッセージが表示されるためです。
[ERROR] Exception in worker process
こんな感じです。
上記のCloudwatchアラームの設定では、NginxLogAlarm
がこのError
メトリクスを監視し、60秒間に1つ以上のエラーが発生した場合にアラームをトリガーし、SampleTopic
に通知を送信する、という流れです。
同時に検知してしまう現象の原因
上記と同じことがしたかったので、新規アプリでも同じ構成と流れでアラームを設定しました。
ロググループだけ別の名前/aws/ecs/docker_sample
にして、他は同じです。
しかし、いざ、これで構築が完了した後、新規アプリでエラーを検知すると既存アプリ・新規アプリの両方とも検知してしまい、アラートが2回きてしまうという現象が発生。
なぜか?
答えは、メトリクスの名前設定にありました。
公式ドキュメントには以下のように記載があります。
メトリクスは名前、名前空間、0 以上のディメンションで一意に定義されます。
https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/cloudwatch_concepts.html
つまり、既存と同じ MetricNamespace
x MetricName
の組み合わせを使うと、一意の識別子として機能して互いに検知してしまうのです。
異なるロググループから同じMetricNamespace
とMetricName
を使用してメトリクスを送信する場合であっても、それらのメトリクスはCloudWatch内で同じメトリクスとして扱われる、という意味です。
上記の場合、/aws/ecs/docker
と/aws/ecs/docker_sample
という異なるロググループ名を持つ2つのNginxMetricFilter
がありますが、どちらもERROR
というフィルターパターンでNginx
名前空間のError
メトリクスにデータを送信します。これにより、どちらのロググループからのエラーも同じNginx
名前空間のError
メトリクスに集約されていたのです...
なるほど。どちらのロググループでERROR
が検出されても、それは同じNginx
のError
メトリクスに集約され、アラーム条件を満たしてしまうのでどちらでもアラートが上がる、ということなんですね。
確かに、それぞれのロググループのメトリクスフィルターを見ると、Alarms
のところに二つのアラームが並んでいました。これを見れば一目瞭然でしたね。
解決方法
ということで、新規アプリの方のMetricNamespace
を既存アプリのメトリクス空間名と重複しないものに設定して、再度構築。すると、上記の管理コンソールから確認しても、それぞれのロググループには一つのアラームしか存在しないようになったことを確認できました。
これでエラーが起きても、両方で検知されることは無くなりました。
めでたしめでたし。