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


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

[AWSでメモリやディスクの使用率とか監視する]
(https://qiita.com/zaburo/items/98388ef35aa2e7a477e0)

[CloudWatchのAlermをLambda通じてchatworkにPOSTする](https://qiita.com/zaru/items/bab992b9438f07740eb9)

大まかな流れ
**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のディスク使用率を監視する](https://michimani.net/post/aws-monitoring-disk-usage-of-ec2/)

<font color="Red">credential情報は、このときの作成完了画面ぽいとこでないと確認出来ないのでメモるかcsvファイルのDLを忘れずに</font>
※万が一忘れてしまった場合は、新規にアクセスキーを発行でもいけた気がするが定かではない
![ユーザ追加画面.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106608/38d25853-92e7-1c69-3442-28b6fe51a3a6.png)

##②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」が記載されている)

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

##④実行テスト
--verifyをつけるとCloudWatchへの送信はしないらしい。

```shell

./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エラー)](http://blue-bear.jp/kb/aws-perl%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%81%8C%E8%A6%8B%E5%BD%93%E3%81%9F%E3%82%89%E3%81%AA%E3%81%84cant-locate-xxx-pm%E3%82%A8%E3%83%A9%E3%83%BC/)

全部一気に出ず、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のメトリクスを選択すると、自動で下記画像のようになる。
![アラーム詳細.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106608/e1f3d1a0-e642-b53f-6338-2b9d087873bb.png)
ディスク使用率80%以上で通知ほしいときは0を80にするだけ。

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

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

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

#LambdaでChatworkへの通知ロジックを作成する
ここでかなりハマった
**①ロジックの作成**
**②トリガーの設定**
**③エイリアスの設定**

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

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

[CloudWatchのAlermをLambda通じてchatworkにPOSTする](https://qiita.com/zaru/items/bab992b9438f07740eb9)

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

```javascript: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を設定する。
![トリガー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106608/7c190b95-a3f2-e30c-3a14-87e6a1360870.png)
SNSトピックには、先程作成したSNSトピックを選択。
※デフォルトだと適当なSNSトピックが設定されているので注意

##③エイリアスの設定
正直ここはよく分かってない()
とにかくとてつもなくハマりまくった
バージョン$LATESTは指定出来ないとかなんとか

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

これで完了！

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

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

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

#参考

[AWSでメモリやディスクの使用率とか監視する]
(https://qiita.com/zaburo/items/98388ef35aa2e7a477e0)

[AWS CloudWatchでディスク容量チェック](http://labs.septeni.co.jp/entry/20141212/1418321528)

[CloudWatchのAlermをLambda通じてchatworkにPOSTする](https://qiita.com/zaru/items/bab992b9438f07740eb9)

[Amazon CloudWatchでEC2のディスク使用率を監視する](https://michimani.net/post/aws-monitoring-disk-usage-of-ec2/)

[[AWS] Perlモジュールが見当たらない(Can’t locate xxx.pmエラー)](http://blue-bear.jp/kb/aws-perl%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%81%8C%E8%A6%8B%E5%BD%93%E3%81%9F%E3%82%89%E3%81%AA%E3%81%84cant-locate-xxx-pm%E3%82%A8%E3%83%A9%E3%83%BC/)