プログラマーのメモ書き

伊勢在住のプログラマーが気になることを気ままにメモったブログです

ディスク使用量を監視する

もともと、redmineを運用していたサーバーのディスク空き容量が厳しかったので、ディスク使用量を監視しようと思ってました(まあ、その設定をしようとサーバーをみたら、『[Ubuntu] unattended-upgrade 実行失敗と復旧』で書いたように痛い目にあってしまいましたので、なおさら必然性がでてしまったのですが・・・)。

で、『[Ubuntu] unattended-upgrade の通知設定』で書いたように既にメール設定を導入したので、自分でディスク使用量の監視スクリプトとcronを書けば事足りるのですが、CloudWatch を使いたいというのがあったので、今回はこちらで実現しました。

EC2だと、CloudWatch を使えば、いくつかの指標(メトリックス)に関しては、デフォルトかつ無料(5分単位の監視の場合)で利用可能なのですが、デフォルトで提供されているものには、ディスク使用量は含まれていません。

ちょっと調べてみると、Amazon CloudWatch Monitoring Scripts for Linux を使えば簡単にディスク使用量の監視をカスタムメトリックスとして CloudWatch に追加できるようです。

以下の作業はこちらの記事を参考にさせていただきました。

CloudWatchでEC2のディスク容量のチェックをおこなう

準備

説明ページあるように、必要なパッケージをインストールしておきます。

bitnami@ip-10-132-190-144:~$ sudo apt-get install libwww-perl libdatetime-perl

 問題なくインストールできれば、準備完了です。

CloudWatchの設定

インストールはスクリプトファイルをダウンロードして、設置すれば終わりです。

bitnami@ip-10-132-190-144:~$ wget http://aws-cloudwatch.s3.amazonaws.com/downloads/CloudWatchMonitoringScripts-1.2.1.zip
bitnami@ip-10-132-190-144:~$ cd /usr/local/bin
bitnami@ip-10-132-190-144:/usr/local/bin$ sudo unzip /home/bitnami/CloudWatchMonitoringScripts-1.2.1.zip 
bitnami@ip-10-132-190-144:/usr/local/bin$ 

試してみます。ここで、認証情報は、AWS_ACCESS_KEYとAWS_SECRET_KEYに入っているとしています。

--verifyオプションをつけると、実際にメトリックスを送信することなく、認証を含めて指定の値がとれるか確認します。これで、問題なければ、下記のように表示がされます。

bitnami@ip-10-132-190-144:/usr/local/bin/aws-scripts-mon$ ./mon-put-instance-data.pl --disk-space-avail --disk-path=/ --verify --verbose --aws-access-key=${AWS_ACCESS_KEY} --aws-secret-key=${AWS_SECRET_KEY}   
DiskSpaceAvailable [/]: 4.74913787841797 (Gigabytes)
Endpoint: https://monitoring.ap-northeast-1.amazonaws.com
Payload: {"MetricData":[{"Timestamp":1442134385,"Dimensions":[{"Value":"/dev/xvda1","Name":"Filesystem"},{"Value":"xxxxxxxxxx","Name":"InstanceId"},{"Value":"/","Name":"MountPath"}],"Value":4.74913787841797,"Unit":"Gigabytes","MetricName":"DiskSpaceAvailable"}],"Namespace":"System/Linux","__type":"com.amazonaws.cloudwatch.v2010_08_01#PutMetricDataInput"}

Verification completed successfully. No actual metrics sent to CloudWatch.

bitnami@ip-10-132-190-144:/usr/local/bin/aws-scripts-mon$ 

問題無いようですね。

ちなみに、ここで使用した認証情報に対応する、IAMユーザーは、AmazonEC2FullAccess をポリシーとして持っています。このポリシーの詳細を表示してみると、

f:id:junichim:20160825154800p:plain

のようになっているので、デフォルト状態で、CloudWatchの権限があることがわかります。

それでは、cronから呼び出すようにします。cron から呼び出す場合は、--from-cron オプションを設定してください。

bitnami@ip-10-132-190-144:/etc/cron.d$ cat ec2_monitor_cloudwatch 
# /etc/crontab: system-wide crontab
# Unlike any other crontab you don't have to run the `crontab'
# command to install the new version when you edit this file
# and files in /etc/cron.d. These files also have username fields,
# that none of the other crontabs do.

# m h dom mon dow user  command
*/5 * * * * root /etc/ec2/ec2-cloudwatch.sh
bitnami@ip-10-132-190-144:/etc/cron.d$ 

さきほどコマンドラインから実行した内容は、ec2-cloudwatch.sh にまとめています。

bitnami@ip-10-132-190-144:/etc/ec2$ cat ec2-cloudwatch.sh 
#!/bin/bash
#
# monitor some metrics and push to CloudWatch
#
# writen by Junichi MORI, 2015/9/13

EC2_ENV=/etc/ec2/bash_ec2env

. ${EC2_ENV}

MON_DIR=/usr/local/bin/aws-scripts-mon
MON_SCRIPT=mon-put-instance-data.pl

${MON_DIR}/${MON_SCRIPT} --disk-space-avail --disk-path=/ --aws-access-key=${AWS_ACCESS_KEY} --aws-secret-key=${AWS_SECRET_KEY} --from-cron
bitnami@ip-10-132-190-144:/etc/ec2$ 

認証情報は、EC2_ENV で指定しているファイルで設定しています。

確認

しばらくすると(5分以上)待って、AWSコンソールからCloudWatchを開くと、『メトリックス』に『Linuxシステム』というのが追加されています。

アラームの設定

CloudWatchでカスタムメメトリックスを設定したので、せっかくなので、アラームも設定してみましょう。

『AWSコンソール』から『CloudWatch』を開いて、ダッシュボード中の『アラームの作成』ボタンを押します。下記のようなアラームの設定画面が表示されるので、画面に従って、必要事項を入力していきます。

f:id:junichim:20160825154744p:plain

最初はアラームを設定するメトリックスを選択します。メトリックスを選択すると、アラーム定義画面に移ります。

f:id:junichim:20160825154745p:plain

始めに、アラームの名称・説明を入力し、次に、アラームの閾値を設定します。

f:id:junichim:20160825154748p:plain

この例の場合は、ディスクの残り領域が、4.7GB以下が1回連続した場合にアラームを発行するという基準にしています。

次に、アラームの閾値に対して、どのような行動を取るかを指定します。

『アラームが次の時』の意味は、対象となるメトリックスがアラーム閾値の条件を満たし場合が『警告』、満たさない場合が『OK』になります。『不足』はメトリックスが取得できていないなどの状態です。

『警告』を選択すると、アラームが閾値を満たした場合(上記の場合だと、ディスクの残り容量が4.7GBを切ったとき)に通知が飛びます。同じ閾値に対して『OK』を選択すると、ディスクの残り容量が4.7GBより大きい場合に通知が発行されます。

f:id:junichim:20160825154749p:plain

『通知の送信先』には、アラーム基準を満たした場合の通知先を入力します。ただし、この欄は、Amazon SNS のトピックとして入力する必要があります。

まだ、SNSを設定していない場合は、『新しいリスト』を選択します。すると、

f:id:junichim:20160825154751p:plain

のように、『メールリスト』欄が現れます。

この『メールリスト』欄に、送信先のメールアドレスを入力します。さらに、『通知の送信先』にSNSのトピック名を入力します。今回は新規での作成になるため、トピック名としては(使える文字・記号と文字列の長さは守る必要がありますが)任意の文字列を指定すればよいと思います。

メールアドレスだけ指定すればいいと勝手に思い込んでいたもんで、実は、ここで結構はまりました。『通知の送信先』が空欄だと、『アラームの作成』ボタンを押しても、エラーとなり、そのエラーメッセージも文字種別の不正、のような内容のため、メールアドレスが間違っているのかと勘違いしてました。

問題なく入力できていると、入力したメールアドレス宛に、すぐに確認メールが送られます。こんな感じです。

f:id:junichim:20160825154752p:plain

メールに記載されているリンクをクリックすることで、メールアドレスが登録されます。画面もすぐに下記のように変わります。

f:id:junichim:20160825154754p:plain

問題なく設定できると、CloudWatchの画面で

f:id:junichim:20160825154756p:plain

こんな感じで、アラームが設定されたことがわかります。

なお、CloudWatchのアラームの作成については、こちらのリファレンスなどをご参考にしてください。ちゃんと読むとSNS設定のことなども載ってますね。

確認

では、実際にアラームを発生させてみます。

監視対象のサーバーにログインして、適当なファイルをコピーして、ディスクの空き容量を4.7GB以下にします。

すると、そのうち、

f:id:junichim:20160825154758p:plain

のように、設定したアラームがアラーム状態に変化します(紛らわしい・・・)。 メールも送られているはずなので、確認してみると、

You are receiving this email because your Amazon CloudWatch Alarm "LowFreeDiskSpace" in the APAC - Tokyo region has entered the ALARM state, because "Threshold Crossed: 1 datapoint (4.4244499206543) was less than or equal to the threshold (4.7)." at "Sunday 13 September, 2015 10:56:13 UTC".

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

Alarm Details:
- Name:                       LowFreeDiskSpace
- Description:                Low free disk space
- State Change:               OK -> ALARM
- Reason for State Change:    Threshold Crossed: 1 datapoint (4.4244499206543) was less than or equal to the threshold (4.7).
- Timestamp:                  Sunday 13 September, 2015 10:56:13 UTC
- AWS Account:                xxxxxxxxxxxx

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

Monitored Metric:
- MetricNamespace:            System/Linux
- MetricName:                 DiskSpaceAvailable
- Dimensions:                 [Filesystem = /dev/xvda1] [InstanceId = xxxxxxxxxx] [MountPath = /]
- Period:                     300 seconds
- Statistic:                  Average
- Unit:                       not specified

State Change Actions:
- OK: 
- ALARM: [arn:aws:sns:ap-northeast-1:xxxxxxxxxxxx:ec2administrator]
- INSUFFICIENT_DATA: 

こんな感じのメールが送られていました。無事に監視できているようです。

その他

カスタムメトリックを利用するとCloudWatch の料金が発生しますが、CloudWatchの料金の説明を読むと、

新規および既存のお客様は、10 メトリックス(Amazon EC2 インスタンスまたはカスタムメトリックス、または CloudWatch Logs* の詳細モニタリングに適用)、10 アラーム、および 100 万の API リクエストを追加料金なしでご利用いただけます。

とあるので、10メトリックスまでなら無料で使えそうです。

また、SNS も料金の説明を読むと無料利用枠があるので、数個のアラームに使う分には追加料金も不要のようです。ありがたいことです。

あと、CloudWatch を少し触ってみた印象としては、サーバーの状態の中でも数値が刻々と変化していく指標に使うのが良さそうです。グラフィカルに変化を見ることができるので、これを利用しない手はないという印象です。もちろん、エラーの有無などをメトリックスにしてアラームを設定することも可能ですが、わざわざCloudWatchを使わなくても良さそうです。気になる指標が出てきたら、いろいろ追加して使ってみようと思います。