CloudWatchとCollectdを使用してEC2インスタンス(Linux)からLoadAverageを取得するAnsible

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_levelnone に設定します。

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マネジメントコンソール

f:id:AdwaysEngineerBlog:20201209134246p:plain

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のロールとサーバーの役割的なロールが両方ともロールなので混乱しがち。


 

次はりょーまさんの記事です。

blog.engineer.adways.net