kun432's blog

Alexaなどスマートスピーカーの話題中心に、Voiceflowの日本語情報を発信してます。たまにAWSやkubernetesなど。

〜スマートスピーカーやVoiceflowの記事は右メニューのカテゴリからどうぞ。〜

EC2カスタムメトリクスのCloudwatch設定

f:id:kun432:20220131170623p:plain

今更感ありますが、まとめ。

目次

概要

EC2のメトリクスは標準でCloudWatchで取得されますが、以下のようなものは取得されません。

  • メモリ使用率
  • ディスク使用率
  • プロセス数

これらはカスタムメトリクスとしてユーザが定義する必要があります。早速やっていきましょう。

メモリ・ディスク使用率

メモリ・ディスク使用率はCloudWatch Agentを使えばよいです。

CloudWatch Agentのインストール

パッケージインストールします。collectdも必要になりますので合わせてインストールしておきましょう。

$ sudo yum install amazon-cloudwatch-agent collectd -y

設定ファイルを作成するためのウィザードを実行します。

$ sudo /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-config-wizard

ここからは対話形式になります。順に設定していきます。

=============================================================
= Welcome to the AWS CloudWatch Agent Configuration Manager =
=============================================================
On which OS are you planning to use the agent?
1. linux
2. windows
3. darwin
default choice: [1]:

→ OSの種類。Amazon Linuxであればデフォルト(1)で。

Trying to fetch the default region based on ec2 metadata...
Are you using EC2 or On-Premises hosts?
1. EC2
2. On-Premises
default choice: [1]:

→ ec2のメタデータを取得するか。ECの場合はデフォルト(1)で。

Which user are you planning to run the agent?
1. root
2. cwagent
3. others
default choice: [1]:

→ CloudWatch Agentを実行するユーザ。本当は分けたほうがいいんだろうけど、とりあえずデフォルト(1)で。

Do you want to turn on StatsD daemon?
1. yes
2. no
default choice: [1]:

→ statsdを使うか?必要なのでデフォルト(1)で。

Which port do you want StatsD daemon to listen to?
default choice: [8125]

→ statsdのポート。デフォルト(8125)で。

What is the collect interval for StatsD daemon?
1. 10s
2. 30s
3. 60s
default choice: [1]:

→ statsdの収集間隔。デフォルト(1)で。

What is the aggregation interval for metrics collected by StatsD daemon?
1. Do not aggregate
2. 10s
3. 30s
4. 60s
default choice: [4]:

→ statsdのデータの集約間隔。デフォルト(4)で。

Do you want to monitor metrics from CollectD?
1. yes
2. no
default choice: [1]:

→ statsdでメトリクスを集約するか?当然デフォルト(1)で。

Do you want to monitor any host metrics? e.g. CPU, memory, etc.
1. yes
2. no
default choice: [1]:

→ CPUやメモリなどを監視するか?デフォルト(1. yes)で。

Do you want to monitor cpu metrics per core? Additional CloudWatch charges may apply.
1. yes
2. no
default choice: [1]:

→ CPUコア単位のメトリクスを監視するか?デフォルト(1. yes)で。

Do you want to add ec2 dimensions (ImageId, InstanceId, InstanceType, AutoScalingGroupName) into all of your metrics if the info is available?
1. yes
2. no
default choice: [1]:

→ メトリクスにEC2インスタンスの属性を追加するか、です。ここはちょっと選択によって変わります。とりあえず1にしておきます。

Would you like to collect your metrics at high resolution (sub-minute resolution)? This enables sub-minute resolution for all metrics, but you can customize for specific metrics in the output json file.
1. 1s
2. 10s
3. 30s
4. 60s
default choice: [4]:

→ メトリクスの収集間隔をどれぐらいにするか?デフォルト(4. 60s)で。

Which default metrics config do you want?
1. Basic
2. Standard
3. Advanced
4. None
default choice: [1]:
3

→メトリクスセットのどれを使うか?3(Advanced)にします。

docs.aws.amazon.com

{
        "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
                        },
                        "cpu": {
                                "measurement": [
                                        "cpu_usage_idle",
                                        "cpu_usage_iowait",
                                        "cpu_usage_user",
                                        "cpu_usage_system"
                                ],
                                "metrics_collection_interval": 60,
                                "resources": [
                                        "*"
                                ],
                                "totalcpu": false
                        },
                        "disk": {
                                "measurement": [
                                        "used_percent",
                                        "inodes_free"
                                ],
                                "metrics_collection_interval": 60,
                                "resources": [
                                        "*"
                                ]
                        },
                        "diskio": {
                                "measurement": [
                                        "io_time",
                                        "write_bytes",
                                        "read_bytes",
                                        "writes",
                                        "reads"
                                ],
                                "metrics_collection_interval": 60,
                                "resources": [
                                        "*"
                                ]
                        },
                        "mem": {
                                "measurement": [
                                        "mem_used_percent"
                                ],
                                "metrics_collection_interval": 60
                        },
                        "netstat": {
                                "measurement": [
                                        "tcp_established",
                                        "tcp_time_wait"
                                ],
                                "metrics_collection_interval": 60
                        },
                        "statsd": {
                                "metrics_aggregation_interval": 60,
                                "metrics_collection_interval": 10,
                                "service_address": ":8125"
                        },
                        "swap": {
                                "measurement": [
                                        "swap_used_percent"
                                ],
                                "metrics_collection_interval": 60
                        }
                }
        }
}
Are you satisfied with the above config? Note: it can be manually customized after the wizard completes to add additional items.
1. yes
2. no
default choice: [1]:

→設定が表示されます。これで問題なければ1(yes)で。

Do you have any existing CloudWatch Log Agent (http://docs.aws.amazon.com/AmazonCloudWatch/latest/logs/AgentReference.html) configuration file to import for migration?
1. yes
2. no
default choice: [2]:

→事前に設定されたCloudWatch Logのエージェント設定があるか。ないのでデフォルト(2. no)で。

Do you want to monitor any log files?
1. yes
2. no
default choice: [1]:
2

→ログファイルの監視をするか。今回はパスします。

Saved config file to /opt/aws/amazon-cloudwatch-agent/bin/config.json successfully.
Current config as follows:
{
        "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
                        },
                        "cpu": {
                                "measurement": [
                                        "cpu_usage_idle",
                                        "cpu_usage_iowait",
                                        "cpu_usage_user",
                                        "cpu_usage_system"
                                ],
                                "metrics_collection_interval": 60,
                                "resources": [
                                        "*"
                                ],
                                "totalcpu": false
                        },
                        "disk": {
                                "measurement": [
                                        "used_percent",
                                        "inodes_free"
                                ],
                                "metrics_collection_interval": 60,
                                "resources": [
                                        "*"
                                ]
                        },
                        "diskio": {
                                "measurement": [
                                        "io_time",
                                        "write_bytes",
                                        "read_bytes",
                                        "writes",
                                        "reads"
                                ],
                                "metrics_collection_interval": 60,
                                "resources": [
                                        "*"
                                ]
                        },
                        "mem": {
                                "measurement": [
                                        "mem_used_percent"
                                ],
                                "metrics_collection_interval": 60
                        },
                        "netstat": {
                                "measurement": [
                                        "tcp_established",
                                        "tcp_time_wait"
                                ],
                                "metrics_collection_interval": 60
                        },
                        "statsd": {
                                "metrics_aggregation_interval": 60,
                                "metrics_collection_interval": 10,
                                "service_address": ":8125"
                        },
                        "swap": {
                                "measurement": [
                                        "swap_used_percent"
                                ],
                                "metrics_collection_interval": 60
                        }
                }
        }
}
Please check the above content of the config.
The config file is also located at /opt/aws/amazon-cloudwatch-agent/bin/config.json.
Edit it manually if needed.

→ /opt/aws/amazon-cloudwatch-agent/bin/config.jsonとして設定が保存されました。調べてみるとどうもパスはここではないみたいですが、それはのちほど。

Do you want to store the config in the SSM parameter store?
1. yes
2. no
default choice: [1]:
2
Program exits now.

→SSMパラメータストアに設定を保存するか。今回は使わないでおきます。これで設定は完了です。

ではさっそくcloudwatch-agentを上げてみましょう。

$ systemctl start amazon-cloudwatch-agent
$ systemctl status amazon-cloudwatch-agent
● amazon-cloudwatch-agent.service - Amazon CloudWatch Agent
   Loaded: loaded (/etc/systemd/system/amazon-cloudwatch-agent.service; disabled; vendor preset: disabled)
   Active: inactive (dead)

Jan 31 07:29:08 ip-10-0-2-57.ap-northeast-1.compute.internal systemd[1]: Started Amazon CloudWatch Agent.

上がっていませんね。ログを見てみましょう。

$ cat /opt/aws/amazon-cloudwatch-agent/logs/amazon-cloudwatch-agent.log
2022/01/31 07:29:08 I! I! Detected the instance is EC2
2022/01/31 07:29:08 Reading json config file path: /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json ...
/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json does not exist or cannot read. Skipping it.
No json config files found, please provide config, exit now

2022/01/31 07:29:08 I! Return exit error: exit code=99
2022/01/31 07:29:08 I! there is no json configuration when running translator

/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.jsonが存在しないということでエラーになっています。対話形式で作成したものは /opt/aws/amazon-cloudwatch-agent/bin/config.jsonです。なんかパスがあってないですね。

調べてみたんですが、特にこういうことをしなくてもよいみたいなのですが・・・・とりあえずbin/config.jsonを etc/amazon-cloudwatch-agent.jsonとしてコピーしてみましょう。

$ cp -pi /opt/aws/amazon-cloudwatch-agent/bin/config.json /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.json

再度上げてみます。

$ systemctl start amazon-cloudwatch-agent
$ systemctl status amazon-cloudwatch-agent
● amazon-cloudwatch-agent.service - Amazon CloudWatch Agent
   Loaded: loaded (/etc/systemd/system/amazon-cloudwatch-agent.service; disabled; vendor preset: disabled)
   Active: active (running) since Mon 2022-01-31 07:50:26 UTC; 1s ago
 Main PID: 2723 (amazon-cloudwat)
   CGroup: /system.slice/amazon-cloudwatch-agent.service
           └─2723 /opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent -config /opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.toml -envconfig...

Jan 31 07:50:26 ip-10-0-2-57.ap-northeast-1.compute.internal systemd[1]: Started Amazon CloudWatch Agent.
Jan 31 07:50:26 ip-10-0-2-57.ap-northeast-1.compute.internal start-amazon-cloudwatch-agent[2723]: Valid Json input schema.
Jan 31 07:50:26 ip-10-0-2-57.ap-northeast-1.compute.internal start-amazon-cloudwatch-agent[2723]: I! Detecting run_as_user...

あがりましたね。

マネジメントコンソールから見てみましょう。

f:id:kun432:20220131213618j:plain

すべてのメトリクスでみると、CWAgentというカスタムネームスペースがあります。これがCloudWatch Agentで作成されたメトリクスになります。クリックしてみるとこうなります。

f:id:kun432:20220131214013j:plain

ここ2つの表示がありますが、実は何度かやり直しているのでこうなってます。ここは、ウィザードの以下の質問によって変わります。

Do you want to add ec2 dimensions (ImageId, InstanceId, InstanceType, AutoScalingGroupName) into all of your metrics if the info is available?
1. yes
2. no
default choice: [1]:

"yes"を選んだ場合は赤枠、"no"を選んだ場合は青枠になります。それぞれの中のデータを見てみましょう。

まず赤枠。

f:id:kun432:20220201000822j:plain

こちらは対話時の質問にある通り、Auto Scaling Groupの名称やAMI IDなどが表示されていますね。

青枠の方も見てみましょう。

f:id:kun432:20220201000941j:plain

こちらはちょっとグラフには出ていませんが、EC2インスタンスのDNS名が表示されて、デバイス名が表示されていますね。

なんとなくですが、EC2インスタンスをAuto Scalingで管理する場合は前者、個別にEC2インスタンスを管理する場合には後者という感じでしょうか。このあたりはしばらく使ってみないとなんともですね。

プロセス数

プロセス監視も今はCloudWatch Agentでできるのでやってみましょう。

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/CloudWatch-Agent-procstat-process-metrics.html

たとえばapacheのプロセス監視の場合。以下のようなJSONを追加すれば良いようです。

  "metrics": {
    "metrics_collected": {
      "procstat": [
        {
          "exe": "httpd",
          "measurement": [
            "pid_count"
          ],
          "metrics_collection_interval": 60
        }
      ]
    }
  }

/opt/aws/amazon-cloudwatch-agent/etc/amazon-cloudwatch-agent.jsonにはmetrics.metrics_collectedはすでに存在するので、そこに追加してあげればよいですね。

まるっと追加するとこうなります。一番下。

{
  "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
      },
      "cpu": {
        "measurement": [
          "cpu_usage_idle",
          "cpu_usage_iowait",
          "cpu_usage_user",
          "cpu_usage_system"
        ],
        "metrics_collection_interval": 60,
        "resources": [
          "*"
        ],
        "totalcpu": false
      },
      ...snip...
      "swap": {
        "measurement": [
          "swap_used_percent"
        ],
        "metrics_collection_interval": 60
      },
      // ここから
      "procstat": [
        {
          "exe": "httpd",
          "measurement": [
            "pid_count"
          ],
          "metrics_collection_interval": 60
        }
      ]
      // ここまで
    }
  }
}

では反映させてみてましょう。

$ systemct start amazon-cloudwatch-agent

それっぽいのができましたね。

f:id:kun432:20220131221727p:plain

httpdのプロセス数の監視ができました。

f:id:kun432:20220131221912j:plain

その他

他にもいくつか方法はあるようで、例えば、ちょっと古いけど。

スクリプトでなにかをチェックしてaws cliで直接メトリクスを送るというもの。複雑なものやカスタマイズされたものなどはこういうやり方は今でも使えなくはない気がする。

まとめ

今はCloudWatch Agentを有効に使うというのが良いようです。

参考

https://sayjoyblog.com/cloudwatch_agent/sayjoyblog.com

qiita.com