CloudWatchのカスタムメトリクスにsidekiqやunicornのプロセス監視を追加する

はじめに
---
いま携わっているプロジェクトでは、EC2インスタンスのモニタリングにCloudWatchを使用しています。
今回、sidekiqやunicornなどのプロセスもCloudWatchで監視できるようにしたのでまとめます。

AWSでの事前準備
---
今回はaws cliを使ってCloudWatchにカスタムメトリクスとしてプロセス数を送信します。
IAMロールの作成や、EC2インスタンスへのポリシーのアタッチなどの事前準備については以下の記事が参考になります。
[Run Commandで複数のEC2インスタンスのカスタムメトリクスを一括設定 ｜ Developers.IO](https://dev.classmethod.jp/cloud/aws/amazon-linux-put-custom-metrics-with-run-command/)

プロセス監視のシェルスクリプト
---
SSMを使わないのであれば、以下スクリプトをサーバに置いてcron設定するだけでもOKです。

主にこちらの記事を参考にさせていただきました :pray: 
[CloudWatchでEC2上のプロセス監視 - 合同会社ジョートー](https://jyo-to.okinawa/20180725/1895/)

```sh
#!/bin/bash

NAMESPACE="Ec2Process"
UNIT="Count"
REGION=`curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone | sed -e 's/.$//'`
INSTANCE_ID=`curl -s http://169.254.169.254/latest/meta-data/instance-id`
DIMENSIONS="InstanceId=$INSTANCE_ID"
 
# 監視対象プロセスリスト
PROCESS_LIST=(sidekiq unicorn)
 
PUT_COMMAND="aws cloudwatch put-metric-data"
 
# 監視対象プロセス毎にプロセス数をカウントしてCloudWatchに格納する
for PROCESS in ${PROCESS_LIST[@]}; do
  COUNT=`ps aux | grep $PROCESS | grep -v grep | wc -l`
  echo $PROCESS:$COUNT
  $PUT_COMMAND --metric-name $PROCESS --namespace $NAMESPACE --dimensions $DIMENSIONS --value $COUNT --unit $UNIT --region $REGION
done
```

今回は、サーバにログインして作業するのが面倒なので、SSMを使ってcronを設定していきます。

AWS Systems Manager（SSM）を使ってcronを設定する
---

AWS Systems Manager > コマンドの実行 > AWS-RunShellScript を選択し、「コマンドのパラメータ」に以下を貼り付けます。

```sh
# ディレクトリ作成
mkdir -p /opt/cw-monitoring
 
# ユーザーがいなければ作成
if ! id cw-mon >/dev/null 2>&1; then
  useradd cw-mon
fi

# メモリ使用率カスタムメトリクス送信スクリプト作成
tee /opt/cw-monitoring/processCounter.sh << "EOF" > /dev/null
#!/bin/bash

NAMESPACE="Ec2Process"
UNIT="Count"
REGION=`curl -s http://169.254.169.254/latest/meta-data/placement/availability-zone | sed -e 's/.$//'`
INSTANCE_ID=`curl -s http://169.254.169.254/latest/meta-data/instance-id`
DIMENSIONS="InstanceId=$INSTANCE_ID"
 
# 監視対象プロセスリスト
PROCESS_LIST=(sidekiq unicorn)
 
PUT_COMMAND="aws cloudwatch put-metric-data"
 
# 監視対象プロセス毎にプロセス数をカウントしてCloudWatchに格納する
for PROCESS in ${PROCESS_LIST[@]}; do
  COUNT=`ps aux | grep $PROCESS | grep -v grep | wc -l`
  echo $PROCESS:$COUNT
  $PUT_COMMAND --metric-name $PROCESS --namespace $NAMESPACE --dimensions $DIMENSIONS --value $COUNT --unit $UNIT --region $REGION
done
EOF
 
# オーナー、グループ、パーミッション設定
chown -R cw-mon:cw-mon /opt/cw-monitoring
chmod 744 /opt/cw-monitoring/processCounter.sh
 
# cron設定
tee /var/spool/cron/cw-mon << EOF > /dev/null
*/1 * * * * /opt/cw-monitoring/processCounter.sh
EOF
```

上記スクリプトでは以下の操作を行っています。

- スクリプトを実行するためのユーザを作成する
- スクリプトを置くディレクトリを作成する
- スクリプトを作成
- cronを設定する

今後開始したいプロセスが増えても、`PROCESS_LIST`に追加していけばOKです :wink: 

「実行」をポチってCloudWatch > メトリクスを見に行くと、

カスタムメトリクスに「Ec2Process」が追加され、各インスタンスで値が取得されてることが確認できます :tada: 

![スクリーンショット_2018-10-01_16_26_02.png](https://qiita-image-store.s3.amazonaws.com/0/611/2efdc504-629d-5eda-b099-4a459bf7494f.png)

あとはしきい値を設定してAlermされるようにすれば死活監視できますね。

以上です :hugging: 

参考
---
- [Run Commandで複数のEC2インスタンスのカスタムメトリクスを一括設定 ｜ Developers.IO](https://dev.classmethod.jp/cloud/aws/amazon-linux-put-custom-metrics-with-run-command/)
- [CloudWatchでEC2上のプロセス監視 - 合同会社ジョートー](https://jyo-to.okinawa/20180725/1895/)
- [AWSで構築した環境にありがちなシェルスクリプトたち まとめ ｜ Developers.IO](https://dev.classmethod.jp/cloud/aws/aws-shellscript-summary/#process-monitoring)
- [いい加減覚えよう。 `command > /dev/null 2>&1`の意味 - Qiita](https://qiita.com/ritukiii/items/b3d91e97b71ecd41d4ea)
- [bash - Find out if user name exists - Super User](https://superuser.com/questions/336275/find-out-if-user-name-exists)
- [bash - Only mkdir if it does not exist - Stack Overflow](https://stackoverflow.com/questions/18622907/only-mkdir-if-it-does-not-exist)