EC2のディスク使用率のアラートをChatworkに飛ばす


ざっくりと下記参考2記事を組み合わせた感じだが、いろいろハマりポイントあったのでまとめ

AWSでメモリやディスクの使用率とか監視する

CloudWatchのAlermをLambda通じてchatworkにPOSTする

大まかな流れ
EC2にCloudWatchへの通知用モジュールを入れる
CloudWatchでアラーム設定をする
LambdaでChatworkへの通知ロジックを作成する
※LambdaのランタイムはNode.js 8.10

使うAWSサービスは以下
・EC2
・CloudWatch
・Amazon SNS
・Lambda

EC2にCloudWatchへの通知用モジュールを入れる

EC2の監視は、CloudWatchにデフォルトでCPUやメモリのメトリクスがあるものの、ディスク使用率に関しては無いらしい。
そのためEC2からCloudWatchに対し現在の使用量を申告するための設定が必要。

流れとしては
①(「プログラムによるアクセス」が有効になっているIAMアカウントが無い場合は)IAMアカウント作成
②CloudWatchへの通知用モジュール(←AWSが用意してくれている)をEC2にDL
③credential情報の設定
④実行テスト(必要があればperlモジュールのインストール)
⑤cronの設定

①IAMアカウント作成

「プログラムによるアクセス」が有効になっているIAMアカウントが無い場合は省略可。
このへんのサイトを参考にしつつ作成。
(正直どの権限がどうとかよくわかってないので言われるがままに…)
Amazon CloudWatchでEC2のディスク使用率を監視する

credential情報は、このときの作成完了画面ぽいとこでないと確認出来ないのでメモるかcsvファイルのDLを忘れずに
※万が一忘れてしまった場合は、新規にアクセスキーを発行でもいけた気がするが定かではない

②CloudWatchへの通知用モジュールをEC2にDL

curlでDLして解凍するだけ

#CloudWatchへの通知用モジュールをDL・解凍
curl https://aws-cloudwatch.s3.amazonaws.com/downloads/CloudWatchMonitoringScripts-1.2.2.zip -O
unzip CloudWatchMonitoringScripts-1.2.2.zip

③credential情報の設定

DLしたファイル内にcredential情報を記載する用のテンプレート(awscreds.template)が存在するので、それをコピー or 新規でawscreds.confを作成する。

# 解凍したディレクトリに移動し、credential情報を書き換える
cd aws-scripts-mon
vim awscreds.conf

awscreds.confの中身は、①で控えたIAMアカウントの「アクセスキーID」と「シークセットアクセスキー」を下記のように設定。(credentials.csvをDLしていれば、「Access key ID」と「Secret access key」が記載されている)

awscreds.conf
AWSAccessKeyId=[Access key ID]
AWSSecretKey=[Secret access key]

④実行テスト

--verifyをつけるとCloudWatchへの送信はしないらしい。


./mon-put-instance-data.pl --mem-util --swap-util --disk-space-util --disk-path=/ --verify

今回いくつかのサーバに適用したのだが、そのうちの数台でガンガンエラー出たので、場合によってはperlモジュールのインストールが必要。(エラー出なかったサーバは元々入ってたのか、何かをインストールした際に入ったのかは不明)

出たエラー達
Can’t locate Sys/Syslog.pm in @INC (@INC contains: …
Can’t locate URI/Escape.pm in @INC (@INC contains: …
Can’t locate DateTime.pm in @INC (@INC contains: …
Can’t locate Compress/Zlib.pm in @INC (@INC contains: …
Can’t locate LWP.pm in @INC (@INC contains: …

このあたりを参考にしつつ
[AWS] Perlモジュールが見当たらない(Can’t locate xxx.pmエラー)

全部一気に出ず、1個1個潰していった結果、おそらく全部で下記のモジュールが必要

yum install -y perl-Sys-Syslog perl-CGI perl-DateTime-TimeZone perl-URI perl-Compress-Zlib perl-LWP-Protocol-https

perlの勉強もいつかしよういつか

⑤cronの設定

あくまでもCloudWatchへの自己申告なので自動通知にしないとね、という事みたい

*/5 * * * * /[モジュールをインストールしたディレクトリのパス]/aws-scripts-mon/mon-put-instance-data.pl --disk-space-util --disk-path=/ --from-cron

これで設定したサーバのディスク使用率をCloudWatchから見れるようになったはず

CloudWatchでアラーム設定をする

この後出てくるChatwork APIを叩くLambdaのロジックは、アラームを検知したSNSのイベントをトリガーに動作するのだが
CloudWatchのイベントをLambda側で直でトリガーに出来ないのかは不明。
今回はChatworkの通知だけじゃなくメール送信もしたので、LambdaのトリガーはSNSを経由したものになっている。

流れ
①SNSの設定をする
②監視のアラーム設定をする

①SNSの設定

Amazon SNSにて

トピックを作成

トピック > トピックの作成
トピック名を入れるだけ
一瞬で終わる

サブスクリプションを作成

サブスクリプション > サブスクリプションの作成
トピックARN:さっき作成したトピックのARNを選択
プロトコル:Eメールを選択
エンドポイント:通知先のEメールを設定

AWSからエンドポイントに設定したメアドに確認メールが飛ぶので、
メール内の「Confirm subscription」リンクを踏んで確認完了したらここの設定は終わり。

※もしかしたらメール通知しない場合にはサブスクリプションいらないかもしれない

②アラームの設定

CloudWatchにて

アラーム > アラームの作成

メトリクスの選択

EC2から無事に通知が届いている場合には、
 カスタム名前空間 > Linuxシステム > Filesystem, InstanceId, MountPath
に対象のメトリクスがあるので選択する。(メトリクス名は「DiskSpaceUtilization」)

アラーム詳細

DiskSpaceUtilizationのメトリクスを選択すると、自動で下記画像のようになる。

ディスク使用率80%以上で通知ほしいときは0を80にするだけ。

名前は対象のサーバが分かるものにしておいた方が良さげ。(今回の場合は、後ほどメール本文にもこの名前を付与している)
なおここで設定した名前は後から変更出来なさそう。

アクション

通知の送信先に、先程設定したSNSトピックを選択するだけ。

ここまですると、SNSのサブスクリプションにメール設定している場合にはメールが飛んでくるようになる。

LambdaでChatworkへの通知ロジックを作成する

ここでかなりハマった
①ロジックの作成
②トリガーの設定
③エイリアスの設定

①ロジックの作成

通知するだけのロジックなので、わざわざzipが必要な環境用意したくない!
Node力は雑魚だけど自力でいけるやろと思ってあがいてみた

が、結局クソ雑魚すぎて諦め
ドンピシャなサイト見つけてほぼ丸パクリ

CloudWatchのAlermをLambda通じてchatworkにPOSTする

「一から作成」でランタイムはNode.js 8.10

index.js
var https = require('https');
var querystring = require('querystring');

exports.handler = function(event, context) {

  // 本文の組み立て
  // SNSからのevent引数からAlarmName(CloudWatchのアラーム詳細で設定した「名前」)を抜き出して付与している
  var post_message = '';
  if(event.Records){
      var message = JSON.parse(event.Records[0].Sns.Message);  
      post_message = "ディスク容量警報発生!\n" + message.AlarmName + "\n";
  }else{
      return;
  }
  var postData = querystring.stringify({
      body:post_message
  });

  // リクエストの設定情報
  var options = {
      host: 'api.chatwork.com',
      port: 443,
      path: '/v2/rooms/xxxxxxxx/messages', // xxxxxxxxに通知したいルームIDを設定
      method: 'POST',
      headers: {
          'Content-Type': 'application/x-www-form-urlencoded',
          'Content-Length': postData.length,
          'X-ChatWorkToken': 'xxxxxxxxxxxxx' // Chatworkのアクセストークンを設定
      }
  };

  // 通信!
  var req = https.request(options, function (res) {
    res.on('data', function (d) {
      process.stdout.write(d);
    });
    res.on('end', function () {
      context.done();
    });
  });

  req.on('error', function (err) {
    console.log(err);
  });

  req.write(postData);
  req.end();

};

なおconsole.logに出したものはCloudWatchでも確認できるのだが
テスト実行したらLambdaの画面上にも出るしとても便利

②トリガーの設定

トリガーにSNSを設定する。

SNSトピックには、先程作成したSNSトピックを選択。
※デフォルトだと適当なSNSトピックが設定されているので注意

③エイリアスの設定

正直ここはよく分かってない()
とにかくとてつもなくハマりまくった
バージョン$LATESTは指定出来ないとかなんとか

エイリアスの作成で、バージョン$LATESTを指定したエイリアスを作成する。

これで完了!

終わりに

これでディスク使用率が、CloudWatchのアラーム詳細に設定したしきい値を超えたらChatworkに通知が飛ぶようになる。

このままだとしきい値を下回った場合の通知は来ないが、アラーム詳細の下の方にあるアクションで追加設定も出来るっぽい。

というか以前触ったときよりLambdaの画面が変わりすぎてて驚いた。
また何か触るときに変貌してそうで怖い。

参考

AWSでメモリやディスクの使用率とか監視する

AWS CloudWatchでディスク容量チェック

CloudWatchのAlermをLambda通じてchatworkにPOSTする

Amazon CloudWatchでEC2のディスク使用率を監視する

[AWS] Perlモジュールが見当たらない(Can’t locate xxx.pmエラー)