[AWS SDK][CloudWatch]EC2 ディスクの使用率を取得する

2014.11.28

はじめに

t.hondaです。EC2のディスクの使用率をプログラムにて取得してみたので、その方法についてです。とはいっても、ディスクの使用率自体はCloudWatchのメトリクスで取得し、プログラムからはメトリクスを参照する形となります。今回はAWS SDK for Javaを使いましたが、その他の言語でも処理の概要は変わらないかと思います。

CloudWatchの設定

CloudWatchにメトリクスを追加する方法については、以下のサイトが詳しいので、そちらを参照してください。 Amazon ClouldWatchで始めるAWSのリソース監視、はじめの一歩
簡単に行うことを纏めると

  1. ディスク使用率などを取得するためのスクリプトをEC2にインストール
  2. cronで上記のスクリプトを定期的に実行するように設定
  3. Management Consoleでディスク使用率などが取得できるかを確認

となります。

ディスク使用率を取得するプログラム

では、プログラムです。このような感じとなります。

package cloudwatchsample;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.services.cloudwatch.AmazonCloudWatchClient;
import com.amazonaws.services.cloudwatch.model.Datapoint;
import com.amazonaws.services.cloudwatch.model.Dimension;
import com.amazonaws.services.cloudwatch.model.GetMetricStatisticsRequest;
import com.amazonaws.services.cloudwatch.model.GetMetricStatisticsResult;
import com.amazonaws.services.cloudwatch.model.ListMetricsRequest;
import com.amazonaws.services.cloudwatch.model.ListMetricsResult;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.List;

/**
 *
 * @author
 */
public class CloudWatchSample {
    private final static String ACCESS_KEY = "Your Access Key";
    private final static String SECRET_ACCESS_KEY = "Your Secret Key";
    private final static String MONITORING_END_POINT = "your monitoring end point";
    private final static String NAME_SPACE = "System/Linux";
    private final static String METRIC_NAME = "DiskSpaceUtilization";
    private final static String INSTANCE_ID = "Your Instance Id";
    private final static String FILE_SYSTEM = "/dev/xvda1";
    private final static String MOUNT_PATH = "/";
        
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        AWSCredentials awsCredentials = new BasicAWSCredentials(ACCESS_KEY, SECRET_ACCESS_KEY);
        AmazonCloudWatchClient client = new AmazonCloudWatchClient(awsCredentials);
        client.setEndpoint(MONITORING_END_POINT);
                
        getMetrics(client);
        getMetricsStatistics(client);
    }
    
    private static void getMetricsStatistics(AmazonCloudWatchClient client){
        GetMetricStatisticsRequest request = new GetMetricStatisticsRequest();
        Calendar c = Calendar.getInstance();
        c.setTime(new Date());
        c.add(Calendar.HOUR, -1);
        request.setStartTime(c.getTime());
        request.setEndTime(new Date());
        request.setNamespace(NAME_SPACE);
        request.setMetricName(METRIC_NAME);
        request.setPeriod(60);
        
        Collection<Dimension> dimensions = new ArrayList<>();
        dimensions.add(new Dimension().withName("InstanceId").withValue(INSTANCE_ID));
        dimensions.add(new Dimension().withName("Filesystem").withValue(FILE_SYSTEM));
        dimensions.add(new Dimension().withName("MountPath").withValue(MOUNT_PATH));

        request.setDimensions(dimensions);

        Collection<String> statistics = new ArrayList<>();
        statistics.add("Average");
        request.setStatistics(statistics);
        
        GetMetricStatisticsResult result = client.getMetricStatistics(request);
        System.out.println(result.getLabel());
        List<Datapoint> dataPoints = result.getDatapoints();
        dataPoints.stream().forEach((p) -> {
            Date timeStamp = p.getTimestamp();
            Double avg = p.getAverage();
            System.out.println(timeStamp.getTime()+" : "+avg);
        });
    }
    
    private static void getMetrics(AmazonCloudWatchClient client){
        ListMetricsRequest request = new ListMetricsRequest();
        request.setNamespace(NAME_SPACE);
        request.setMetricName(METRIC_NAME);
        ListMetricsResult list = client.listMetrics(request);
                
        list.getMetrics().stream().forEach((m) -> {
            System.out.printf("metricsName=%s, namespace=%s, dimension=%s%n", m.getMetricName(), m.getNamespace(), m.getDimensions());
        });
    }
}

大きく分けて、今回使う定数の固まり、main処理、今回呼び出すメトリクスを取得するgetMetrics()、メトリクスよりディスクの使用率を取得するgetMetricsStatistics()に分かれます。

定数の「MONITORING_END_POINT」の値については、以下のリンクより該当するCloudWatchのendpointの値を探して記述してください。

リージョンとエンドポイント

「NAME_SPACE」「METRIC_NAME」に設定すべき値は、Management ConsoleのCloudWatchのグラフから確認できます。

CloudWatchNamespace

main()では、Credentialsのインスタンス、およびCloudWatchのインスタンスを作成しています。今回はCredentialsのAccess Key、Secret Access Keyを定数で保持していますが、本来はアプリ内に持たないのが良いでしょう。
参考 [AWS SDKs]ローカル開発環境でのアクセスキー/シークレットキーの管理について AWS Simple Icons 2.2 16

getMetrics()では、今回呼び出すメトリクスについての情報を取得しています。ディスクの使用率を取得するという目的からすれば、おまけの機能ですね。

最後に、getMetricsStatistics()でディスクの使用率を取得しています。今回は直近1時間の60秒ごとの値を取得しています。またdimensionsリストにメトリクスのDimensionを設定していますが、これは上記のgetMetrics()で取得出来ているので、実際には定数で持つ必要はないかもしれません。

このアプリを実行すると、実行結果が以下のように出力されます。

metricsName=DiskSpaceUtilization, namespace=System/Linux, dimension=[{Name: Filesystem,Value: /dev/xvda1}, {Name: InstanceId,Value: xxxxxx}, {Name: MountPath,Value: /}]
DiskSpaceUtilization
1417075800000 : 28.175787425903
1417074300000 : 28.1755412360601
1417074900000 : 28.1756397119973
1417077000000 : 28.1760336157459
1417074600000 : 28.1756397119973
1417076100000 : 28.175787425903
1417076700000 : 28.1758366638716
1417074000000 : 28.1755412360601
1417075500000 : 28.175787425903
1417077300000 : 28.1759351398088
1417076400000 : 28.1758366638716
1417075200000 : 28.1756397119973

getMetrics()で取得したメトリクスの情報、getMetricsStatistics()で取得したディスクの使用率が、無事表示されています。

まとめ

今回はCloudWatchよりディスクの使用率を取得しましたが、その他の監視したい値も取得できるはずです。その辺は要件に合わせて変えてみてください。

参考サイト

Amazon ClouldWatchで始めるAWSのリソース監視、はじめの一歩
Amazon CloudWatch Java API