CloudWatchのモニタリングスクリプトでハマった話

CloudWatchのモニタリングスクリプト設定してあるのに、該当のインスタンスIDのデータがCloudWatchにputDataされていなくてハマった話。

ハマったインスタンスは、すでにクラウドウォッチが設定してあるAMIから立ち上げたインスタンスで、 AMIに配置されている、CloudWatchにputDataするスクリプト自体は、インスタンスIDに依存していないから、 そのまま問題なく正しいインスタンスIDでputDataされるはず。             

だが、実際はAMI作成ものインスタンスIDでメトリクスが登録されてしまう。。

インスタンスIDを確認

# curl -s http://169.254.169.254/latest/meta-data/instance-id
i-xxxxxxxx

で紹介したスクリプトを利用している。

# /usr/bin/check_cw_stats

MemoryUtilization: 12.86724312544 (Percent)
DiskSpaceUtilization [/]: 6.65698036312681 (Percent)
Using AWS credentials file </etc/aws/awscreds.conf>
Endpoint: https://monitoring.ap-northeast-1.amazonaws.com
Payload: {"MetricData":[{"Timestamp":1460957603,"Dimensions":[{"Value":"i-yyyyyyyy","Name":"InstanceId"}],"Value":12.86724312544,"Unit":"Percent","MetricName":"MemoryUtilization"},{"Timestamp":1460957603,"Dimensions":[{"Value":"/dev/xvda1","Name":"Filesystem"},{"Value":"i-yyyyyyyy","Name":"InstanceId"},{"Value":"/","Name":"MountPath"}],"Value":6.65698036312681,"Unit":"Percent","MetricName":"DiskSpaceUtilization"}],"Namespace":"System/Linux","__type":"com.amazonaws.cloudwatch.v2010_08_01#PutMetricDataInput"}
Received HTTP status 200 on attempt 1


Successfully reported metrics to CloudWatch. Reference Id: 1038cd0d-0527-11e6-b8f3-fbed7fa60205

あきらかに、PayloadのインスタンスIDが実際にインスタンスメタデータで取得したInstanceIdと異なっている。 ちなみにi-yyyyyyyyのインスタンスIDはAMIのインスタンスIDになる。

AWSから提供されているCloudWatch登録のスクリプトをおってみる。

  • /usr/local/src/CloudWatch-1.0.20.0/aws-scripts-mon/mon-put-instance-data.pl
338: my $instance_id = CloudWatchClient::get_instance_id();
  • /usr/local/src/CloudWatch-1.0.20/aws-script-mon
sub get_instance_id
...
{
  if (!$instance_id) {
    $instance_id = get_meta_data('/instance-id', USE_CACHE);
  }
  return $instance_id;
}
...

USE_CACHEだと!!というわけで、キャッシュをするようです。

インスタンスIDを取得しているようなメソッドが。

よくよくAmazon EC2 Linux インスタンスのメモリとディスクのメトリックスのモニタリングを読んでみると以下のようにキャシュに関する文章が。

スクリプトパッケージに含まれる CloudWatchClient.pm モジュールは、インスタンスメタデータをローカルでキャッシュします。スクリプトを実行しているインスタンスから AMI を作成すると、キャッシュ TTL(デフォルト: 6 時間、Auto Scaling グループでは 24 時間)以内にこの AMI から起動したすべてのインスタンスは、元のインスタンスの ID を使用してメトリックスを出力します。キャッシュ TTL 期間が経過した後は、スクリプトは新しいデータを取得し、スクリプトは現在のインスタンスの ID を使用します。これをすぐに修正するには、$ rm /var/tmp/aws-mon/instance-id を使用してキャッシュされたデータを削除します

気を取り直し、キャッシュを削除

rm -rf /var/tmp/aws-mon/*

再度メトリクススクリプトの実行。

# /usr/bin/check_cw_stats

MemoryUtilization: 13.8519340228981 (Percent)
DiskSpaceUtilization [/]: 6.65734560054434 (Percent)
Using AWS credentials file </etc/aws/awscreds.conf>
Endpoint: https://monitoring.ap-northeast-1.amazonaws.com
Payload: {"MetricData":[{"Timestamp":1460958577,"Dimensions":[{"Value":"i-xxxxxxxx","Name":"InstanceId"}],"Value":13.8519340228981,"Unit":"Percent","MetricName":"MemoryUtilization"},{"Timestamp":1460958577,"Dimensions":[{"Value":"/dev/xvda1","Name":"Filesystem"},{"Value":"i-xxxxxxxx","Name":"InstanceId"},{"Value":"/","Name":"MountPath"}],"Value":6.65734560054434,"Unit":"Percent","MetricName":"DiskSpaceUtilization"}],"Namespace":"System/Linux","__type":"com.amazonaws.cloudwatch.v2010_08_01#PutMetricDataInput"}
Received HTTP status 200 on attempt 1

となり、正しいインスタンスIDでputDataができました。

ということで、AMIなどから新しいインスタンス、オートスケールなどを実行する際には、

ユーザーデータで

#!/bin/bash
rm -rf /var/tmp/aws-mon/*

と設定しておけば安心です。

AMIからのインスタンス作成し、CloudWatchモニタリングスクリプトではまってしまった お話でした。

_| ̄|○