AWS CloudWatch Agent導入+LoadAverage送信cronをTerraformとuserDataで設定して、デフォルトのEC2メトリクスを補填する

![2016-07-13_16h12_14-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321850/663fdeb9-581b-4539-d89e-65d3fbbd353e.png)

# はじめに
こんにちわ。Wano株式会社でエンジニアをやっているnariと申します。

今回は、最近取り組んでいるリソースメトリクスの収集の話をしようと思います。

[デフォルトのCloudWatchのEC2メトリクス](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/viewing_metrics_with_cloudwatch.html)では、メモリ、ディスク等々閾値チェックの要望を単体では満たさないことが多いと思います。

その際、[CloudWatch Agent](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/Install-CloudWatch-Agent.html)を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](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/metrics-collected-by-CloudWatch-agent.html)
    
```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を作成する
- [CloudWatch エージェントで使用する IAM ロールおよびユーザーを作成する - Amazon CloudWatch](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/create-iam-roles-for-cloudwatch-agent-commandline.html) を参照

## 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
```

# 参考文献
- [CloudWatch エージェントを使用して Amazon EC2 インスタンスとオンプレミスサーバーからメトリクスとログを収集する - Amazon CloudWatch](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/Install-CloudWatch-Agent.html)
- [新しいCloudWatch Agentでメトリクスとログの収集が行なえます ｜ DevelopersIO](https://dev.classmethod.jp/cloud/aws/new-cloudwatch-agent-collect-metrics-and-logs/)
- [AWSでEC2のLoad AverageをCloudWatch metricsに追加するScript - Qiita](https://qiita.com/wildeagle/items/8b75c6945698e5f22949)