Adways Advent Calendar 2020 7 日目の記事です。
インフラの奥村です。
表題の通りですが、CloudWatchとCollectdを使用してEC2インスタンスのLoadAverageを取得するAnsibleを作成したいと思います。
本題
前提
CloudWatch エージェントを使用することでEC2インスタンスからシステムレベルのメトリクスを収集することができます。
Linuxのインスタンスの場合にCloudWatch エージェント経由で取得できるメトリクスは以下のリンクに記載されている通りです。
CloudWatch エージェントにより収集されるメトリクス - Amazon CloudWatch
CloudWatchエージェントの設定のみで、大きく分けて以下のメトリクスを取得することができます。
- cpu
- disk
- diskio
- swap
- memory
- net
- netstat
- process
個別に何が取得できるかは CloudWatch エージェント設定ファイルを手動で作成または編集する - Amazon CloudWatch を参照下さい。
LoadAverageの取得はデフォルトの設定ファイルのみだけでは取得できないです。
そこで必要になるのが「collectd」です。
CloudWatchエージェントの設定ファイルでは、
- 自らがメトリクスはを取得する設定
- Collectdから送信されるメトリクスを受け付ける設定
の両方を記述することができます。
Collectdからのメトリクスを受け付ける設定をすると、CloudWatchエージェントがCollectdのサーバーとして「udp://127.0.0.1:25826」で通信を受け付けます。(参考:collectd を使用したカスタムメトリクスの取得 - Amazon CloudWatch)
LoadAverageの取得に必要な設定
- CloudWatchエージェントのインストール
- CloudWatchエージェントの設定ファイルの配置
- Collectdから送信されるメトリクスを受け付ける設定
- Collectdのインストール
- Collectdの設定ファイルの配置
- メトリクスの送信先にCloudWatchエージェントを指定
- CluodWatchエージェントとCollectdの起動
上記の項目を満たすAnsibleのroleを作成します。
Ansible
CloudWatchロールを作成します。
CollectdはCloudWatchエージェントありきで使用するので、CloudWatchロールに含めてしまいます。
Amazon Linux 2に対して実行する事を想定しています。
呼び出し元のPlaybookで cloudwatch
ロールを指定します。
server.yml
--- - hosts: all roles: - cloudwatch
cloudwatchロール(roles/cloudwatch)
. ├── files │ ├── cloudwatch_agent.config │ └── collectd.conf ├── handlers │ └── main.yml └── tasks └── main.yml
tasks/main.yml
--- # collectdのインストールにはepelが必要 - name: install & enable epel repo yum: name: "https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm" become: yes - name: install cloudwatch packages yum: name: - amazon-cloudwatch-agent - collectd become: yes - name: copy cloudwatch config file template: src: cloudwatch_agent.config dest: /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json become: yes notify: "restart cloudwatch agent" - name: copy collectd config file copy: src: collectd.conf dest: /etc/collectd.conf become: yes notify: "restart collectd daemon" - name: start cloudwatch agent systemd: name: amazon-cloudwatch-agent state: started enabled: yes become: yes - name: start collectd daemon systemd: name: collectd state: started enabled: yes become: yes
handlers/main.yml
--- - name: restart cloudwatch agent systemd: name: amazon-cloudwatch-agent state: restarted become: yes - name: restart collectd daemon systemd: name: collectd state: restarted become: yes
cloudwatch_agent.config
インスタンス内で通信が完結するので、 collectd_security_level
は none
に設定します。
Collectdからメトリクスを収集するための最低限の設定を記述しています。
本来はデフォルトで取得できるメトリクスやログ収集の設定などが含まれると思います。
{ "agent": { "metrics_collection_interval": 60, "run_as_user": "root" }, "metrics": { "append_dimensions": { "AutoScalingGroupName": "${aws:AutoScalingGroupName}", "ImageId": "${aws:ImageId}", "InstanceId": "${aws:InstanceId}", "InstanceType": "${aws:InstanceType}" }, "metrics_collected": { "collectd": { "metrics_aggregation_interval": 60, "collectd_security_level": "none" } } } }
collectd.conf
LoadAverageを取得するための load
プラグインとネットワーク経由でメトリクスを送信する network
プラグインの設定のみ記述します。
LoadPlugin load LoadPlugin network <Plugin network> Server "127.0.0.1" "25826" </Plugin>
確認
準備ができたらAnsibleを実行してみましょう。
AWSマネジメントコンソール
CWAgentの名前空間にメトリクスが記録されている事が確認できました。
CWAgentの名前空間で「load」とかで検索するとメトリクスを特定できると思います。
EC2インスタンス
念の為、CloudWatch Agentが25826でListenしているかを調べます。
$ sudo systemctl status amazon-cloudwatch-agent.service | grep PID Main PID: 4718 (amazon-cloudwat)
$ sudo lsof -i | grep 4718 amazon-cl 4718 root 3u IPv4 28042 0t0 UDP localhost:25826
確認できました。
まとめ
これでLoadAverageの取得ができるようになりました。あとはCloudWatchアラームの設定をしてアラーティングをすると良さそうですね。
今までCollectdは使ってこなかったですが、プラグインのリスト(Table of Plugins - collectd Wiki)を見る限り色々取得できそうなので、検証してみようと考えています。
PS. Ansibleあるある言います。Ansibleのロールとサーバーの役割的なロールが両方ともロールなので混乱しがち。
次はりょーまさんの記事です。