AWS LambdaでAWSの障害をslackにメンション付きで通知する

担当しているシステムのエラーの通知や障害の通知まわりで、その問題点と解決策を整理したのでメモしておきます。

背景

エラー通知があふれ見逃す危険があった

担当しているシステムではRailsやJSでExceptionが発生したときや、AWSでなんらかのイベントが発生したときにはSlackのエラー用チャンネルにその内容を通知しています。
しかし、RailsやJSのExceptionはそこそこの頻度で発生しているため、1日に何回もSlackに通知がきてしまいます。
その結果 エラーの通知に慣れてしまう という事態が発生し、重要なエラー(AWSインスタンスが落ちるなど)への対処が遅れることがしばしばありました。

解決の方向性

緊急度の高いエラーにすぐに気付ける状態を目指す

緊急度の高いエラーにすぐに気付ける状態を目標として 緊急度の高いエラーにのみメンション @channelをつける という方向で対応することにしました。

「Slackには即対応が必要なエラーしかこない」という世界にするためにRailsのExceptionやJS Errorを全て解決するぜ!ということができたら格好いいのですが、実際は「解決する工数が大きいわりに発生頻度と重要度(緊急度)は低い」エラーというものも多く、実現は難しいと判断しました。

既存の構成

既存の通知の仕組みは以下のようになっていました。

CloudWatch Alarm + SNSでメール送信 + Email Integrationでslack通知

処理の流れは以下のようになっています。

  1. SlackのEndPointでSNSをSubscribeする。
  2. CloudWatch AlarmからSNSにPublishしメール送信
  3. Email Integrationでslackに通知

これだと背景に記載した通り他のエラー内容に埋もれてしまうという問題がありました。

今回の構成

CloudWatch Alarm + SNS + Lambda

  1. LambdaでSNSをSubscribeする。
  2. CloudWatch AlarmからSNSにPublish。
  3. 通知を受けたLambdaでSlackのweb hookを叩く。

CloudWatch AlarmはAWSリソースのメトリクスを起動条件にすることができます。起動することができるターゲットは以下の3つ

  • SNS(Simple Notification Service)
  • Auto Scalingアクション
  • EC2アクション

直接Slackに通知することはできないため、SNS経由でLambdaを起動して通知するようにします。

他の案

CloudWatch Events + Lambda

CloudWatch Eventsは直接AWS Lambdaを起動できるため便利ですが、今回の用途には適していません。
AWSリソースの状態変化(=AWSAPIコール)をイベントとしているため、CPU UtilizationやMemory UsageなどのMetricsを通知ないからです。