はじめに
こんにちわ。Wano株式会社でエンジニアをやっているnariと申します。
今回は、最近取り組んでいるリソースメトリクスの収集の話をしようと思います。
デフォルトのCloudWatchのEC2メトリクスでは、メモリ、ディスク等々閾値チェックの要望を単体では満たさないことが多いと思います。
その際、CloudWatch AgentをEC2インスタンスに導入して追加のメトリクスを取ることが多いと思うのですが、その作業をインスタンス毎で行いたくない。。。。
そこで、今回の要件であるLoadAverageも追加で収集するcronの設定も含め、TerraformとuserDataで再現性のある形で設定することにしました。
どうやったか
1.CloudWatch Agentの設定をssmのパラメタストアに上げる
- tfファイル
ssm.tf
resource "aws_ssm_parameter" "cwagent" {
name = var.ssm_parameter_name
type = "String"
value = file("${path.module}/templates/amazon-cloudwatch-agent.json")
}
-
設定ファイル
- どういうメトリクスを取るか、ログのpathなどを設定する
- CloudWatch エージェントにより収集されるメトリクス - Amazon CloudWatch
amazon-cloudwatch-agent.json
{
"logs": {
"logs_collected": {
"files": {
"collect_list": [
{
"file_path": "/var/log/messages",
"log_group_name": "messages"
}
]
}
}
},
"metrics": {
"append_dimensions": {
"AutoScalingGroupName": "${aws:AutoScalingGroupName}",
"InstanceId": "${aws:InstanceId}"
},
"metrics_collected": {
"cpu": {
"measurement": [
"cpu_usage_idle",
"cpu_usage_iowait",
"cpu_usage_user",
"cpu_usage_system"
],
"metrics_collection_interval": 10,
"resources": [
"*"
],
"totalcpu": false
},
"disk": {
"measurement": [
"used_percent",
"inodes_free"
],
"metrics_collection_interval": 10,
"resources": [
"*"
]
},
"diskio": {
"measurement": [
"io_time",
"write_bytes",
"read_bytes",
"writes",
"reads"
],
"metrics_collection_interval": 10,
"resources": [
"*"
]
},
"mem": {
"measurement": [
"mem_used_percent"
],
"metrics_collection_interval": 10
},
"netstat": {
"measurement": [
"tcp_established",
"tcp_time_wait"
],
"metrics_collection_interval": 10
},
"swap": {
"measurement": [
"swap_used_percent"
],
"metrics_collection_interval": 10
}
}
}
}
2.CloudWatchAgentServerPolicyを持ったroleを作成する
3.userDataで、CloudWatch Agent導入し、LoadAverage通知Cronを仕込む
- packagesで、amazon-cloudwatch-agentをinstall
- runcmdで、 LoadAverageのcronを設定し、1で作ったssmパラメタストアの設定を使用してamazon-cloudwatch-agentを起動する
cloud_init.yml
#cloud-config
packages:
- https://s3.amazonaws.com/amazoncloudwatch-agent/amazon_linux/amd64/latest/amazon-cloudwatch-agent.rpm
runcmd:
# add LoadAverage cron
- curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py"
- sudo python get-pip.py
- sudo pip install awscli
- |
cat <<EOT > /root/cloudwatch_put_loadaverage.sh
#!/bin/bash
## AWS CloudWatchのカスタムメトリックスにロードアベレージを追加する
aws cloudwatch --region ap-northeast-1 put-metric-data \
--metric-name $(curl 169.254.169.254/latest/meta-data/instance-id/)/LoadAverage --namespace "AmazonLinux/LoadAverage" \
--dimensions "InstanceId=$(curl 169.254.169.254/latest/meta-data/instance-id/)" \
--value $(uptime | awk 'BEGIN{FS="load average: "}{print $2}' | awk 'BEGIN{FS="."}{print $1}') \
--unit "Count"
EOT
- chmod 755 /root/cloudwatch_put_loadaverage.sh
- /root/cloudwatch_put_loadaverage.sh
- echo '*/5 * * * * /root/cloudwatch_put_loadaverage.sh' > /root/cron.conf
- crontab /root/cron.conf
# start cloudwatch agent
- |
/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \
-a fetch-config \
-m ec2 \
-c ssm:${ssm_parameter_name} \
-s