Amazon Monitronの監視+Slack通知をマネージドサービスだけで実現してみた

2023.10.30

こんにちは。CX事業本部Delivery部のakkyです。

弊社ではオフィスにAmazon Monitron(以下Monitron)を設置して実験をしているのですが、常時きちんと稼働できているかどうか監視する仕組みが欲しくなりました。

Monitronはゲートウェイとセンサー間が無線なので、何らかのトラブルで通信ができなくなることも考えられますし、不意にゲートウェイの電源を抜かれてしまうかもしれません。また、インターネット回線にトラブルがあってもAWSへ通信出来なくなってしまいます。

そこで今回は、Monitronを監視する構成を考えてみましたのでご紹介します。Lambdaすら使う必要なく、完全にマネージドサービスだけで実現できました。

構成の検討

MonitronではデータをKinesis Data Streamsでエクスポートできます。これに関しては以前ご紹介しました。

Kinesis Data Streamにデータが来たら、これを何とかしてCloudwatch Metricsに入れてAlarmを作ってSlackに投げればよいと思い、次のような構成を最初に考えました。

これで一旦は動いたのですが、Lambdaが2つあるのと、Slackに表示される形式を整えるのが面倒だという問題がありました。ちょっとイケてないですね。

そんな話を社内でしたところAWS Chatbotを使うとアラームの内容がキレイに表示されて良いという話を聞き、またKinesis Data StreamsからCloudwatch logsへの転送がEventbridge Pipesで可能だということがわかり、最終的にはこのような構成になりました。

Lambdaレス!コードを1行も書かず、すべてAWSのマネージドサービスだけで監視を実現できるようになりました。 Monitronもマネージドサービスなのでぴったりですね。

構成の詳細

上記構成のサービスはそれぞれ次のような処理を行います。

  1. Kinesis Data Streams(KDS)
    • Monitronからデータを送る
  2. EventBridge Pipes
    • KDSからデータを取得・加工してCloudwatch Logsへ送信
  3. Cloudwatch logs→Metrics→Alarm
    • ログデータの保存・メトリクスの抽出・アラームの発報
  4. SNS
    • アラームを配信
  5. Chatbot
    • Slackへ投稿

監視する項目としては次の項目にします。

  1. ゲートウェイの接続
  2. ゲートウェイの切断
  3. センサーデータが1時間間隔で送信されているか

MonitronとKinesis Data Streamsの設定

上記ブログ記事をご覧ください

EventBridge Pipes

Amazon EventBridgeからパイプを開き、パイプの作成をクリックします。

ソースの設定

ソースをKinesisに設定し、ストリーム名にMonitronからデータが送信されているKDSを選択します。残りはデフォルトにしました。

フィルタリングと強化は使いません。

ターゲットの設定

ターゲットサービスにCloudwatchログを設定し、ロググループに名前を付けます。既存の好きなロググループに出すことはできず、/aws/events以下の名前空間のものに限るようです。今回は/aws/events/MonitronStreamという名前を付けました。

次にターゲット入力トランスフォーマーを設定します。KDSを使うと、ペイロードがBASE64エンコードされるので、この機能を使って平文に戻します。送信時刻も付与することにしました。

サンプルイベント/イベントペイロードからKinesisストリーム→サンプルイベント1を選び、dataとapproximateArrivalTimestampをクリックすると手軽に作れます。

{
  "data": <$.data>,
  "approximateArrivalTimestamp": <$.approximateArrivalTimestamp>
}

Cloudwatchの設定

EventBridgeによってMonitronのイベントデータがCloudwatch Logsに送信されるようになりました。Cloudwatchでは、(1)Logsからメトリクスフィルターを使用してMetricsに変換する (2)Metricsを参照してAlarmを作る の2つの作業を行います

メトリクスフィルターの設定

Cloudwatchを開きロググループから/aws/events/MonitronStreamを開きます。メトリクスフィルターのタブから「メトリクスフィルターを作成」をクリックします。

まずはゲートウェイの接続イベントを取りたいので、フィルターパターンは次のようにします

{ $.data.eventType = "gatewayConnected"}

Eventbridge PipeでKDSのBASE64をデコードしてdataプロパティの中に入れているため、$.data.XXXXXにMonitronのペイロードが入っている点に注意してください。

フィルター名は「GatewayConnected」として、メトリクス名前空間は「MonitronGateway」メトリクス名は「Connected」メトリクス値は「1」として作成します。

これ以外にも切断イベントを以下のようなフィルタで作り、フィルター名は「GatewayDisonnected」として、メトリクス名前空間は「MonitronGateway」メトリクス名は「Discnnected」メトリクス値は「0」として作成しました。接続と切断でメトリクス名を分けたのは、ゲートウェイが極短時間で切断・接続した場合、メトリクスで区別できなくなるためです。

{ $.data.eventType = "gatewayDisconnected"}

次に、データが一定間隔で送信されているかを確認するために、データ測定結果も記録することにします。 フィルター条件は次のようにします。それぞれのプロパティは実際に使っているものに変えてください。

{ $.data.eventType = "measurement" && $.data.eventPayload.siteName = "Site 1" && $.data.eventPayload.assetName = "扇風機" && $.data.eventPayload.positionName = "モーター"}

フィルター名は「Site1FanMotor」として、メトリクス名前空間は新たに「Site1FanMotor」を作成、メトリクス名は「TotalVibrationRMS」メトリクス値は$.data.eventPayload.features.acceleration.band10To1000Hz.totalVibration.rmsとして作成しました。これはアプリで使われる加速度の値です。

他にも$.data.eventPayload.features.temperatureに入っている温度なども記録しました。

ここまで設定できると、メトリクスにデータが記録できるようになっているはずです。

SNSトピックの作成

今回はEメールサブスクリプションを先に作成したため、Cloudwatch AlarmのコンソールからSNSも同時に作成しましたが、Chatbot単体で使う場合は事前にSNSトピックを作成しておいてください。

アラームの設定

アラーム→すべてのアラームからアラームの作成を行います。

まず、切断アラームを作成します。メトリクス名は「Disconnected」とし、統計:最小、期間:1分にします。しきい値は静的の「より低い」で「1」とします。 トリガーは「アラーム」を選び、SNSトピックを新規作成するか、既存のものを選択してください。アラーム名は「GatewayDisconnected」にしました。 欠落データは「正常」とすると、切断イベントが発生した時間以外はアラーム一覧で正常とマークされますが、これは接続の実態を反映していないのでお好みで設定してください。

接続アラームは切断アラームを少し変更し、統計:最大、トリガーを「OK」としました。

最後にデータ取得アラームを作成します。 Monitronは、正常であれば60分間隔でデータが取得されるので、直近60分に測定データがない場合を異常としてアラームしてみました。

こちらは上記2つのアラームとは異なり、メトリクス名を「TotalVibrationRMS」とし、統計:サンプル数、期間はカスタムを選択し、4200秒とします。 これで70分間のデータポイント数が得られます。Monitronの測定間隔の60分ではなく70分としたのは、測定間隔の誤差を考慮したためです。測定間隔の誤差は実績で1分程度なので、もう少し許容間隔は減らしてもいいかもしれません。 しきい値は静的の「より低い」で「1」とし、トリガーは「アラーム」としました。

Chatbotの設定

Slackを認証して連携し、新しいチャネルを作成します。

Chatbotを使うとSlackからAWSリソースの一覧を表示したり、操作したりできますが、今回は通知だけをさせて捜査は何もさせたくないので、チャネルガードレールポリシーにAWSDenyAllを設定します。

チャネルロールはガードレールポリシーに制限されるので、この設定で何もできなくなりますが、気になる場合はIAMポリシーも以下のように変更し、すべての権限を削除しておきます。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Statement1",
            "Effect": "Deny",
            "Action": [
                "*"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

動作確認

以上の設定でMonitronに関する通知がSlackへ送信されるようになりました。試しにMonitronゲートウェイの電源をしばらく切ると、以下のような通知が確認できました!

ただし、実際に動作させてみると、接続と切断のアラームが評価されるタイミングが異なるため、ゲートウェイが極短期間で切断→復帰すると、Slackに投稿される順番が逆転することがありました。このため、接続されているということをきちんと監視したい場合には、KDSからゲートウェイ関連のメッセージを直接投Slackへ投稿する必要があるかもしれません。今回は簡易的な監視のため、順番の逆転は一旦許容しました。

まとめ

Monitronの監視をマネージドサービスなしで実現することができました。これでインターネット接続が不安定だったり、通信が不安定なセンサーを簡単に監視することができますね。

Eventbridgeは初めて使ったのですが、Lambdaをわざわざ書かなくてもよいので業務でも活用できそうです。

ただ、今回は5つのサービス(Cloudwatchの中にもたくさんありますが)を使いましたが、試しながら設定するためにマネジメントコンソールから作業したところ、想像以上に手順が多かったので、今後はCloudformationかCDKでデプロイするほうがよさそうです。IaCのありがたさを思い出しました。