AWS:CloudWatchでロードアベレージを監視

0
50

AWSではEC2やRDSのインスタンスタイプを柔軟に変更できますが、変更する必要性に関してはどのように判断すれば良いでしょう?
単純には体感的にレスポンスが遅くなってきたら対処するというような考え方もありますが、できれば事前に予測して、問題が発生する前に対処できた方が良いです。そのためには判断材料となる数値データが必要になります。
そのような数値データを提供してくれるサービスがCloudWatchです。

ただ、不思議なことに、EC2およびRDSのいずれに関してもロードアベレージに関する情報が標準的には収集されるようにはなっていません。CPU使用率はいずれも収集されているのですが。
個人的な経験則としてはCPU使用率は低くてもロードアベレージが高く、レスポンスが遅くなっているケースはしばしばあるので、重要な指標だと思っています。

と言うことで、EC2とRDSのそれぞれに関してCloudWatchでロードアベレージの監視ができるようにしたいと思います。

EC2のロードアベレージ情報収集

EC2に関しては自力でロードアベレージ情報を収集して、AWS CLI でCloudWatchに登録するしかないようです。

AWS CLI インストール

もしAWS CLIがインストールされていなければ、改めてインストールする必要があります。
rootユーザーで以下のように実行します。

cd /tmp
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
./aws/install

インストールできたら必要な情報を設定します。

aws configure

いくつかの情報入力を求められます。

AWS Access Key ID不要
AWS Secret Access Key不要
Default region name当該EC2インスタンスが属するリージョン
Default output formatjson

前半2つはAWS CLI実行に必要な権限の制御に使用されるものですが、今回は後述するIAMロール(ポリシー)の設定で対応しますので不要です。
Default output format」に関しては「json」以外に「table」「text」が選択できるようですが、ネット情報などでは「json」が推奨されていますし、プロセス間で構造化したデータを通信する場合のデータ形式としてはやはり「json」が定番かと思いますので、これを指定します。

IAMロール(ポリシー)の設定

前述したようにAWS CLIの処理に必要な権限をEC2に与えたい訳ですが、具体的には然るべきポリシーを含むIAMロールを当該EC2にアタッチします。ただ、ある程度環境設定が行われたEC2であれば既にIAMロール自体はアタッチされているかと思いますので、実際には同ロールにポリシーを追加するだけで対応可能かと思います。
今回はCloudWatchへの情報登録を行いたいので「CloudWatchAgentServerPolicy」を追加します。

情報収集バッチ作成

ロードアベレージ情報を取得してCloudWatchに送信するバッチを作成します。
具体的には以下のような内容になります。

#!/bin/bash

metric_name="LoadAverage"
name_space="プロダクト名/${metric_name}"
host_ip=`/usr/bin/hostname -I | sed 's/\./-/g'`

#5分のロードアベレージ
load_average=`uptime | awk 'BEGIN{FS="load average: "}{print $2}' | cut -d ' ' -f 2 | cut -d ',' -f 1`

/usr/local/bin/aws cloudwatch --region "リージョン" put-metric-data --metric-name "${host_ip}/${metric_name}" --namespace ${name_space} --value ${load_average}

CloudWatchで「すべてのメトリクス」を表示した際に、上記情報は「–name_space」オプションで指定した「カスタム名前空間」に属する、「–metric-name」オプションで指定したメトリクスとして参照可能になります。よって、同用法を考慮して分かりやすい名称を付けておくと良いです。
上記では複数のEC2から採取された情報を区別できるよう、メトリクス名に各EC2のローカルIPを付加しています。
「–region」にはEC2が属するリージョンを指定します。

ロードアベレージとしては「uptime」コマンドの実行結果から直近5分間の平均ロードアベレージを取得するようにしています。

バッチファイルには実行権を与えておきます。

crontab設定

バッチができたら、あとは定期的に実行するようにcrontabに設定します。

*/5 * * * * バッチファイルのパス

これで5分ごとに直近5分間の平均ロードアベレージが記録されるようになります。

RDSのロードアベレージ情報収集

実はDBインスタンス生成時に「拡張モニタリングの有効化」を有効にしていれば、CloudWatchのロググループ「RDSOSMetrics」のレコードとして当該インスタンスに関する様々なステータスデータが毎分記録されるようになっています。この情報の中にロードアベレージも含まれています。
よって情報採取自体は既に行われているのですが、ログ形式では見難いため、他のメトリクスのようにグラフ化して見られるようにします。

具体的には当該ロググループの「メトリクスフィルター」と言う機能を使用して、ログから抽出したデータをメトリクスとして見られるようにします。

メトリクスフィルターの設定

ロググループの詳細画面で「メトリクスフィルター」タブをクリックすると「メトリクスフィルターの作成」が実行できるようになっています。
本機能を使用してメトリクスフィルターを設定します。

フィルターパターン{ $.loadAverageMinute.five >= 0.00 }
テストするログデータを選択対象ログストリーム選択
フィルター名適当な名称を設定
メトリクス名前空間適当な名前空間を設定
メトリクス名適当なメトリクス名を設定
メトリクス値$.loadAverageMinute.five

ロググループ「RDSOSMetrics」のレコード内では、ロードアベレージは「loadAverageMinute」と命名されており、かつ直近1分、5分、15分の平均値がそれぞれ「one」「five」「fifteen」と言う名称で参照できるようになっています。
よって、「メトリクス値」として「$.loadAverageMinute.five」と指定することで直近5分のロードアベレージを採取している点が上記設定の最も重要な点です。

「フィルターパターン」はロググループとして採取されたレコードの中から集計対象とするものの条件を指定していますが、今回の場合は全レコードを対象としたいので必ず真となる条件を指定しています(他にもっとスマートな指定方法があるかも)。

「フィルター名」は当該フィルターを識別するための名称、「メトリクス名前空間」「メトリクス名」はメトリクス画面での当該情報を識別するための名称なので、それぞれ分かりやすい名称を適当に付けます。

「テストするログデータを選択」に関しては用途を正確に把握していませんが、とりあえず「RDSOSMetrics」内の集計対象ログストリームを指定しておきます。

上記設定を行うことで、RDSのロードアベレージデータがCloudWatchのメトリクスとして確認可能になります。

総括

上記によりEC2、RDSのロードアベレージがCloudWatchで確認できるようになりました。
ロードアベレージの大まかな適正基準はコア数以下であることなので、この辺を意識しながら監視して行きたいと思います。

なお、CPU以外にもメモリやディスクの容量の適正さも監視したいのですが、EC2に関してはこれらも標準的には収集されていません(RDSでは収集されています)。極めて基本的な判断指標と思われるロードアベレージやメモリ・ディスク容量が軒並み対象外というのは何とも解せませんが、嘆いていても仕方がないので、次回はEC2のメモリ・ディスク容量に関する情報収集について書きたいと思います。