みなさん、日々の運用でCloudWatchアラームを使ってリソースを監視していると思います。
私のプロジェクトでは、テスト要件でインスタンをリストアした際の正常性確認を行ったりします。
・そこでふと疑問に思ったのが、リストアでEC2のInstanceIDが変わった時、CloudWatchアラームはどう対応すべきか?
プロジェクトによっては数百〜数千のアラームを構築する必要があることもあります。
インスタンスをリストアするとInstanceIDが変わり、それに紐づいたCloudWatchアラームは「データ不足」となって再作成が必要になります。
頻繁に起こる事象ではありませんが、大量のインスタンスをリストアするケースでは、毎回アラームを手動で再作成するのは非常に工数がかかりますし、見落としの原因となり運用の質に影響があります。。。
そこで最適な運用方法を自分なりに調査してみました。
CloudWatchアラームの構成
・一般的にCloudWatchアラームの作成時、以下のようにInstanceIDを指定する必要があります。
Cloudwatchアラームは「メトリクス名」と「InstanceID」によってどのメトリクス監視をおこないます。
再現シナリオ
2.起動後しばらくしてCloudWatchアラームを確認すると「データ不足」になっていることがわかります。
当然リストア後のInstanceIDは前のEC2のIDなので現在のInstanceIDは違います。
つまり、このCloudWatchアラームは無用の産物と化してしまいます。。。
3.一般的なCloudWatch Agentの記述例
Cloudwatch Agentの設定は以下です。
根本的な原因として「metrics」内の「append_dimensions」で環境依存してしまう設定をしていたことでハレーションが発生することがわかりました。
{
"agent": {
"metrics_collection_interval": 60
},
"metrics": {
"namespace": "test-metrics-001",
"append_dimensions": {
"InstanceId": "${aws:InstanceId}",
"InstanceType": "${aws:InstanceType}"
},
"aggregation_dimensions": [["InstanceId"]],
"metrics_collected": {
"cpu": {
"measurement": [
"cpu_usage_user",
"cpu_usage_system"
],
"metrics_collection_interval": 60,
"totalcpu": true
},
"mem": {
"measurement": [
"mem_used_percent"
],
"metrics_collection_interval": 60
},
"disk": {
"measurement": [
"used_percent"
],
"metrics_collection_interval": 60,
"resources": [
"/"
]
}
}
}
}
対策方針:CloudWatch Agentの設定変更
InstanceIDに依存しないように、CloudWatch Agent設定を工夫します。
以下は前提条件です(詳細は割愛)
1.VPCエンドポイントの各種設定
2.EC2のIAMロールにCloudWatch Agent用のポリシーをEC2にアタッチ
3.EC2にCloudWatch Agentをインストール
4.CloudWatchアラーム用のSNSを作成
5.CloudWatchアラームの作成
注意点と制約
CloudWatch Agentを設定する際、カスタムメトリクスの作成はOS設定内にあるJsonに記述する必要があります。
append_dimensions で使える "${aws:~}" の構文は、AWS が事前に定義したメタデータキーに限られます。
任意のキーと値のペアを持つメトリクスにディメンションを追加する場合は、その特定のタイプのメトリクスのフィールドの append_dimensions パラメータを使用します。
また、基本的な設定内容は以下になります。
キー名 | 展開される内容 |
---|---|
${aws:AutoScalingGroupName} |
Auto Scaling グループ名 |
${aws:ImageId} |
AMI ID(例: ami-xxxxx) |
${aws:InstanceId} |
EC2 インスタンス ID(例: i-xxxxx) |
${aws:InstanceType} |
EC2 インスタンスタイプ(例: t3.micro) |
・"Region" や "AvailabilityZone" などは、明示的に環境変数やスクリプトで埋め込む必要があります
・ EC2 タグの値(Name や Environment など)を ${aws:TagName} のように書いても展開されません(罠ポイントです)
解決策:append_dimensionsとaggregation_dimensionを活用
公式ドキュメントを読んでわかりましたが、個別のメトリクスセクションで append_dimensions を使うことで実現できます。
また、aggregation_dimensionを「ServerName」にし複数のインスタンスが存在しても
わかりやすく区別できるようにします。
1. 設定ファイルの場所
CloudWatch Agentの設定ファイルはいかにあります。
Linuxは以下に設定ファイルがあります。
/opt/aws/amazon-cloudwatch-agent/etc/[任意のファイル名].Json
Windowsは以下に設定ファイルがあります。
$Env:ProgramData\Amazon\AmazonCloudWatchAgent\[任意のファイル名].Json
2.Jsonの設定(例)
Jsonは以下のように設定しました。
{
"agent": {
"metrics_collection_interval": 60
},
"metrics": {
"namespace": "test-metrics-001",
"aggregation_dimensions": [
["ServerName"]
],
"metrics_collected": {
"cpu": {
"measurement": [
"cpu_usage_idle",
"cpu_usage_iowait",
"cpu_usage_system",
"cpu_usage_user"
],
"append_dimensions": {
"ServerName": "test-ec2-01"
},
"metrics_collection_interval": 60,
"totalcpu": true
},
"mem": {
"measurement": ["mem_used_percent"],
"append_dimensions": {
"ServerName": "test-ec2-01"
},
"metrics_collection_interval": 60
},
"disk": {
"measurement": ["used_percent"],
"append_dimensions": {
"ServerName": "test-ec2-01"
},
"metrics_collection_interval": 60,
"resources": ["/"]
}
}
}
}
3.CloudWatch Agentの再起動
Jsonファイルに上記を記述したら以下のコマンドでAgentを再起動します。
sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl -a fetch-config -m ec2 -c file:/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.Json -s
4.CloudWatchアラームの状態確認
CloudWatchメトリクスを確認するとInstance IDではなく、aggregation_dimensionで指定した「ServerName」でメトリクスが整理されています。
さっそくアラームを作成していきます。
先程までInstanceIDだった箇所がaggregation_dimensionで指定した「ServerName」変わっています。
値はappend_dimensionで指定した「test-ec2-01」です。
5.リストア後のCloudWatchアラームの挙動確認
以下のように全く同じInstanceIDが変わったインスタンスをリストアしました。
CloudWatch Agentの内容も引き継がれている状態です。
インスタンス終了からリストアする間に一瞬だけ「データ不足」になりました。
しばらくしてCloudWatchアラームを確認したところ状態は「OK」となり、その後も問題なくアラームは使用できました。
これにより、InstanceIDの変化に影響されずアラームを再作成する必要がない運用が可能になります。
あくまで一案ですのでもし参考になれば幸いです。