AWS CloudWatchでEC2を監視する (プロセス死活監視、ディスク使用率、iノード使用率を監視してアラートメールを送信する)

はじめに
===

AWS CloudWatchでEC2インスタンスを監視する方法について記します。

EC2インスタンスの各種情報をCloudWatchカスタムメトリックスへ追加する事で、CloudWatchからEC2インスタンスの各種情報を監視出来ます。

　・EC2インスタンス上で稼動するプロセス数 (例えばnginxのプロセス数)
　・EC2インスタンスのディスク使用率
　・EC2インスタンスのiノード使用率

まず、EC2インスタンスのプロセス数、ディスク使用率、iノード使用率をCloudWatchカスタムメトリックスへ追加するサンプルスクリプトについて記します。

スクリプトはGitHubにも保存しましたので、よろしければご利用下さい。
https://github.com/na0AaooQ/aws-cloudwatch-put-ec2-metric

最後に、CloudWatchでEC2インスタンスのnginxプロセスが停止した場合に、アラートメールを送信する設定例について記します。

環境
===

EC2インスタンス(Amazon Linux)は以下で作成したものを使用しました。

http://qiita.com/na0AaooQ/items/1fedb1d0136cd78c6aa1

EC2インスタンスの指定したプロセス数をCloudWatchへ追加するスクリプト
===

### (1) EC2インスタンスの指定したプロセス数をCloudWatchへ追加するスクリプトを作成します。

この例では、nginxのプロセス数をCloudWatchへ追加します。

```
[ec2-user@cloudwatch-example-server ~]$ uname -a
Linux cloudwatch-example-server 4.4.19-29.55.amzn1.x86_64 #1 SMP Mon Aug 29 23:29:40 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux
[ec2-user@cloudwatch-example-server ~]$

[ec2-user@cloudwatch-example-server ~]$ vi /home/ec2-user/cloudwatch_put_process.sh
```

```bash:/home/ec2-user/cloudwatch_put_process.sh
#!/bin/bash

## スクリプトの実行方法の表示する
function print_usage() {
    echo "Usage: $0 [ProcessName]"
    echo "       $0 [--help]"
    echo "       $0 [--debug] [ProcessName]"

    return 0
}

## 入力されたパラメータをチェックする
function check_parameter() {

    if [ $# -ge 1 ] && [ $# -le 2 ] ; then
        ## パラメータとして --help を指定した場合、スクリプトの実行方法を表示する
        if [ $1 == "--help" ] ; then
            print_usage
            exit

        ## パラメータとして --debug を指定した場合、実行するawsコマンド自体も表示する
        elif [ $# -eq 2 ] && [ $1 == "--debug" ] ; then
            debug_flg="on"
            process_name="$2"

        elif [ $# -eq 1 ] && [ $1 == "--debug" ] ; then
            print_usage
            exit

        elif [ $# -eq 1 ] ; then
            process_name="$1"
        fi

    else
        print_usage
        exit
    fi

    return 0
}

## AWS CLI設定
readonly AWS_CLI="/usr/bin/aws"
readonly AWS_CLI_REGION="ap-northeast-1"

## デバッグフラグ
debug_flg="off"

## パラメータ初期化
process_name=""

check_parameter $@

## CloudWatchに追加するメトリックス名や単位の設定
metric_name="${process_name}"
name_space="AmazonLinux/ProcessCount/${metric_name}"
unit="Count"

## プロセス数を取得する
process_count=`ps awux | grep -v grep | grep -v "$0" | grep -w "${process_name}" | wc -l`

## AWS CloudWatchのカスタムメトリックスにプロセス数を追加する
if [ ${debug_flg} == "on" ] ; then
    set -x
fi

${AWS_CLI} cloudwatch --region ${AWS_CLI_REGION} put-metric-data --metric-name `hostname -s`/${metric_name} --namespace ${name_space} --value ${process_count} --unit ${unit}
```

```
[ec2-user@cloudwatch-example-server ~]$ chmod 755 /home/ec2-user/cloudwatch_put_process.sh
```

### (2) スクリプトを実行し、EC2インスタンスのnginxプロセス数をCloudWatchへ追加します。

```
[ec2-user@cloudwatch-example-server ~]$ ps awux | grep -v grep | grep nginx
root      2610  0.0  0.1 109236  1960 ?        Ss   18:19   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx     2611  0.0  0.6 109676  6684 ?        S    18:19   0:00 nginx: worker process
[ec2-user@cloudwatch-example-server ~]$
```

```
[ec2-user@cloudwatch-example-server ~]$ /home/ec2-user/cloudwatch_put_process.sh --debug nginx
++ hostname -s
+ /usr/bin/aws cloudwatch --region ap-northeast-1 put-metric-data --metric-name cloudwatch-example-server/nginx --namespace AmazonLinux/ProcessCount/nginx --value 2 --unit Count
[ec2-user@cloudwatch-example-server ~]$
```

EC2インスタンスの指定したパーティションのディスク使用率をCloudWatchへ追加するスクリプト
===

### (3) EC2インスタンスの指定したパーティションのディスク使用率をCloudWatchへ追加するスクリプトを作成します。

```
[ec2-user@cloudwatch-example-server ~]$ vi /home/ec2-user/cloudwatch_put_disk_use.sh
```

```bash:/home/ec2-user/cloudwatch_put_disk_use.sh
#!/bin/bash

## スクリプトの実行方法の表示する
function print_usage() {
    echo "Usage: $0 [DiskPartitionName]"
    echo "       $0 [--help]"
    echo "       $0 [--debug] [DiskPartitionName]"

    return 0
}

## 入力されたパラメータをチェックする
function check_parameter() {

    if [ $# -ge 1 ] && [ $# -le 2 ] ; then
        ## パラメータとして --help を指定した場合、スクリプトの実行方法を表示する
        if [ $1 == "--help" ] ; then
            print_usage
            exit

        ## パラメータとして --debug を指定した場合、実行するawsコマンド自体も表示する
        elif [ $# -eq 2 ] && [ $1 == "--debug" ] ; then
            debug_flg="on"
            disk_name="$2"

        elif [ $# -eq 1 ] && [ $1 == "--debug" ] ; then
            print_usage
            exit

        elif [ $# -eq 1 ] ; then
            disk_name="$1"
        fi

    else
        print_usage
        exit
    fi

    return 0
}

## AWS CLI設定
readonly AWS_CLI="/usr/bin/aws"
readonly AWS_CLI_REGION="ap-northeast-1"

## デバッグフラグ
debug_flg="off"

## パラメータ初期化
disk_name=""

check_parameter $@

## CloudWatchに追加するメトリックス名や単位の設定
metric_name="${disk_name}"
name_space="AmazonLinux/DiskUse/_${metric_name}"
unit="Percent"

## パーティションのディスク使用率を取得する
disk_use=`df -Phl | grep -v "Filesystem" | grep -w "${disk_name}" | awk 'BEGIN{FS=" "}{print $5}' | sed -s 's/%//g'`

## AWS CloudWatchのカスタムメトリックスにディスク使用率を追加する
if [ ${debug_flg} == "on" ] ; then
    set -x
fi

${AWS_CLI} cloudwatch --region ${AWS_CLI_REGION} put-metric-data --metric-name `hostname -s`/DiskUse_${metric_name} --namespace ${name_space} --value ${disk_use} --unit ${unit}
```

```
[ec2-user@cloudwatch-example-server ~]$ chmod 755 /home/ec2-user/cloudwatch_put_disk_use.sh
```

### (4) スクリプトを実行し、EC2インスタンスの指定したパーティションのディスク使用率をCloudWatchへ追加します。

```
[ec2-user@cloudwatch-example-server ~]$ df -Plh
Filesystem      Size  Used Avail Use% Mounted on
/dev/xvda1      7.8G  1.3G  6.5G  17% /
devtmpfs        488M   56K  488M   1% /dev
tmpfs           498M     0  498M   0% /dev/shm
[ec2-user@cloudwatch-example-server ~]$
```

```
[ec2-user@cloudwatch-example-server ~]$ /home/ec2-user/cloudwatch_put_disk_use.sh --debug /
++ hostname -s
+ /usr/bin/aws cloudwatch --region ap-northeast-1 put-metric-data --metric-name cloudwatch-example-server/DiskUse_/ --namespace AmazonLinux/DiskUse/_/ --value 17 --unit Percent
[ec2-user@cloudwatch-example-server ~]$
```

EC2インスタンスの指定したパーティションのiノード使用率をCloudWatchへ追加するスクリプト
===

### (5) EC2インスタンスの指定したパーティションのiノード使用率をCloudWatchへ追加するスクリプトを作成します。

```
[ec2-user@cloudwatch-example-server ~]$ vi /home/ec2-user/cloudwatch_put_disk_inode_use.sh
```

```bash:/home/ec2-user/cloudwatch_put_disk_inode_use.sh
#!/bin/bash

## スクリプトの実行方法の表示する
function print_usage() {
    echo "Usage: $0 [DiskPartitionName]"
    echo "       $0 [--help]"
    echo "       $0 [--debug] [DiskPartitionName]"

    return 0
}

## 入力されたパラメータをチェックする
function check_parameter() {

    if [ $# -ge 1 ] && [ $# -le 2 ] ; then
        ## パラメータとして --help を指定した場合、スクリプトの実行方法を表示する
        if [ $1 == "--help" ] ; then
            print_usage
            exit

        ## パラメータとして --debug を指定した場合、実行するawsコマンド自体も表示する
        elif [ $# -eq 2 ] && [ $1 == "--debug" ] ; then
            debug_flg="on"
            disk_name="$2"

        elif [ $# -eq 1 ] && [ $1 == "--debug" ] ; then
            print_usage
            exit

        elif [ $# -eq 1 ] ; then
            disk_name="$1"
        fi

    else
        print_usage
        exit
    fi

    return 0
}

## AWS CLI設定
readonly AWS_CLI="/usr/bin/aws"
readonly AWS_CLI_REGION="ap-northeast-1"

## デバッグフラグ
debug_flg="off"

## パラメータ初期化
disk_name=""

check_parameter $@

## CloudWatchに追加するメトリックス名や単位の設定
metric_name="${disk_name}"
name_space="AmazonLinux/DiskInodeUse/_${metric_name}"
unit="Percent"

## パーティションのiノード使用率を取得する
disk_inode_use=`df -Pil | grep -v "Filesystem" | grep -w "${disk_name}" | awk 'BEGIN{FS=" "}{print $5}' | sed -s 's/%//g'`

## AWS CloudWatchのカスタムメトリックスにiノード使用率を追加する
if [ ${debug_flg} == "on" ] ; then
    set -x
fi

${AWS_CLI} cloudwatch --region ${AWS_CLI_REGION} put-metric-data --metric-name `hostname -s`/DiskInodeUse_${metric_name} --namespace ${name_space} --value ${disk_inode_use} --unit ${unit}
```

```
[ec2-user@cloudwatch-example-server ~]$ chmod 755 /home/ec2-user/cloudwatch_put_disk_inode_use.sh
```

### (6) スクリプトを実行し、EC2インスタンスの指定したパーティションのiノード使用率をCloudWatchへ追加します。

```
[ec2-user@cloudwatch-example-server ~]$ df -Phi
Filesystem     Inodes IUsed IFree IUse% Mounted on
/dev/xvda1       512K   37K  476K    8% /
devtmpfs         122K   428  122K    1% /dev
tmpfs            125K     1  125K    1% /dev/shm
[ec2-user@cloudwatch-example-server ~]$
```

```
[ec2-user@cloudwatch-example-server ~]$ /home/ec2-user/cloudwatch_put_disk_inode_use.sh --debug /
++ hostname -s
+ /usr/bin/aws cloudwatch --region ap-northeast-1 put-metric-data --metric-name cloudwatch-example-server/DiskInodeUse_/ --namespace AmazonLinux/DiskInodeUse/_/ --value 8 --unit Percent
[ec2-user@cloudwatch-example-server ~]$
```


cronによりEC2インスタンスのnginxプロセス数、ディスク使用率、iノード使用率をCloudWatchへ定期的に追加する
===

### (7) crontabにnginxプロセス数、ディスク使用率、iノード使用率をCloudWatchへ追加するスクリプトを登録します。

crontabコマンドで以下のようなcronを登録すると、5分おきにCloudWatchへEC2インスタンスのnginxプロセス数、ディスク使用率、iノード使用率を追加する事が可能です。

```
[ec2-user@cloudwatch-example-server ~]$ crontab -e
MAILTO=********@example.com

##### EC2インスタンスのロードアベレージをCloudWatchに記録する
*/5 * * * * /home/ec2-user/cloudwatch_put_loadaverage.sh

##### EC2インスタンスのnginxプロセス数をCloudWatchに記録する
*/5 * * * * /home/ec2-user/cloudwatch_put_process.sh nginx

##### EC2インスタンスの / のディスク使用率をCloudWatchに記録する
*/5 * * * * /home/ec2-user/cloudwatch_put_disk_use.sh /

##### EC2インスタンスの / のiノード使用率をCloudWatchに記録する
*/5 * * * * /home/ec2-user/cloudwatch_put_disk_inode_use.sh /
```


CloudWatchでnginxプロセスが停止した場合にアラートメールを送信する設定
===

### (8) CloudWatchでngxinプロセスが停止した場合、アラートメールを送信するよう設定します。

以下のように設定すると、CloudWatchメトリックスに追加しているnginxプロセス数が監視閾値を下回った場合、アラートメールを送信する事が出来ます。これにより、EC2インスタンスのnginxの停止を監視出来ます。

AWSマネジメントコンソールの「CloudWatch」->「メトリックス」->「AmazonLinux/ProcessCount/nginx」->「cloudwatch-example-server/nginx」の「アラームの作成」をクリックします。

![WS000049.JPG](https://qiita-image-store.s3.amazonaws.com/0/63647/67e34dc1-11c9-0765-f2d6-3c8f607984f9.jpeg)

「アラームの作成」画面が表示されます。各項目に以下のように入力します。

以下の例では、EC2インスタンスのnginxプロセス数が1未満になった場合、アラートメールを送信します。
入力が終わったら「アラームの作成」をクリックします。

　名前: Monitoring-ProcessCount-nginx-cloudwatch-example-server
　説明: Monitoring-ProcessCount-nginx-cloudwatch-example-server
　次の時: Monitoring-ProcessCount-nginx-cloudwatch-example-server が : < 1 を 1 回連続した場合


「アラームの作成」画面で「+ 通知」をクリックして、各項目に以下のように入力します。

　アラームが次の時: 状態: 警告
　通知の送信先: CloudWatch-Monitoring-Alert
　メールリスト: CloudWatchによるプロセス死活監視でアラートメールを送信したいメールアドレス

　アラームが次の時: 状態: OK
　通知の送信先: CloudWatch-Monitoring-Alert
　メールリスト: CloudWatchによるプロセス死活監視でアラートメールを送信したいメールアドレス

　アラームが次の時: 状態: 不足
　通知の送信先: CloudWatch-Monitoring-Alert
　メールリスト: CloudWatchによるプロセス死活監視でアラートメールを送信したいメールアドレス

「新しいメールアドレスの確認」ウィンドウが表示され、Amazon SENから前述の「メールリスト」で指定したメールアドレスに「AWS Notification - Subscription Confirmation」というメールが送信されます。

「AWS Notification - Subscription Confirmation」メール本文中の「Confirm subscription」をクリックして、CloudWatchからのメール受信を許可します。

試しにEC2インスタンスのnginxを停止して、アラートメールが届くか確認します。

```
[root@cloudwatch-example-server ~]# ps awux | grep -v grep | grep nginx
root     26561  0.0  0.1 109236  1960 ?        Ss   22:42   0:00 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
nginx    26563  0.0  0.6 109676  6716 ?        S    22:42   0:00 nginx: worker process
[root@cloudwatch-example-server ~]#

[root@cloudwatch-example-server ~]# /etc/init.d/nginx stop
Stopping nginx:                                            [  OK  ]
[root@cloudwatch-example-server ~]#

[root@cloudwatch-example-server ~]# ps awux | grep -v grep | grep nginx
[root@cloudwatch-example-server ~]#
```

5分程待つと、前述の「メールリスト」で指定したアドレスに以下のようなアラートメールが届きます。

　アラートメール件名: ALARM: "Monitoring-ProcessCount-nginx-cloudwatch-example-server" in Asia Pacific - Tokyo

```html:アラートメール本文例
You are receiving this email because your Amazon CloudWatch Alarm "Monitoring-ProcessCount-nginx-cloudwatch-example-server" in the Asia Pacific - Tokyo region has entered the ALARM state, because "Threshold Crossed: 1 datapoint (0.0) was less than or equal to the threshold (1.0)." at "Sunday 18 September, 2016 13:41:55 UTC".

View this alarm in the AWS Management Console:
https://console.aws.amazon.com/cloudwatch/home?region=ap-northeast-1#s=Alarms&alarm=Monitoring-ProcessCount-nginx-cloudwatch-example-server

Alarm Details:
- Name:                       Monitoring-ProcessCount-nginx-cloudwatch-example-server
- Description:                Monitoring-ProcessCount-nginx-cloudwatch-example-server
- State Change:               OK -> ALARM
- Reason for State Change:    Threshold Crossed: 1 datapoint (0.0) was less than or equal to the threshold (1.0).
- Timestamp:                  Sunday 18 September, 2016 13:41:55 UTC
- AWS Account:                **************

Threshold:
- The alarm is in the ALARM state when the metric is LessThanOrEqualToThreshold 1.0 for 300 seconds.

Monitored Metric:
- MetricNamespace:            AmazonLinux/ProcessCount/nginx
- MetricName:                 cloudwatch-example-server/nginx
- Dimensions:
- Period:                     300 seconds
- Statistic:                  Maximum
- Unit:                       not specified

State Change Actions:
- OK:
- ALARM: [arn:aws:sns:ap-northeast-1:***********:CloudWatch-Monitoring-Alert]
- INSUFFICIENT_DATA:


--
If you wish to stop receiving notifications from this topic, please click or visit the link below to unsubscribe:
https://sns.ap-northeast-1.amazonaws.com/unsubscribe.html?SubscriptionArn=arn:aws:sns:ap-northeast-1:*************:CloudWatch-Monitoring-Alert:********-****-****-****-aca8dccfaff1&Endpoint=**************@gmail.com

Please do not reply directly to this email. If you have any questions or comments regarding this email, please contact us at https://aws.amazon.com/support
```

EC2インスタンスのロードアベレージをCloudWatchへ追加するスクリプト
===

CloudWatchでEC2インスタンスのロードアベレージも監視したい場合、以下の設定をご参照下さい。

http://qiita.com/na0AaooQ/items/1fedb1d0136cd78c6aa1

備考
===

CloudWatchでのメール送信設定手順の画像をQiitaにアップロードしようとしているのですが、画像サイズを1MB未満に縮小しても、以下のようなエラーが出て、新規画像がアップロード出来なくなりました(アップロード可能なサイズ制限に引っかかってしまったようです)。
手順の画像を殆ど掲載出来なかったので、分かりづらい手順で済みません。

```
![Failed to upload "***********.JPG": the image size Monthly limit exceeded]()
```

***

以上になります。