AWS CloudWatch では EC2 に対していくつかのメトリクスが自動で収集されているのですが、なぜかメモリ使用率などがありません。
公式では CloudWatch Agent を使って収集するよう書かれています。
CloudWatch エージェントにより収集されるメトリクス
https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/metrics-collected-by-CloudWatch-agent.html
これで EC2 のメモリ使用率のメトリクスは取得できます。
しかし、やはり docker を使っているのでコンテナ毎のメトリクスが欲しいのですが、CloudWatch Agent では取得できなさそうです。
何か方法がないかと探してみると、以下のツールが見つかりました。
--docker
オプションを付けるとコンテナ毎の CPU使用率、メモリ使用率が取れるようです。
[github] mon-put-instance-data
https://github.com/mlabouardy/mon-put-instance-data
ただ、残念なことにコンテナのメトリクスの Dimention が固定で EC2 インスタンスID、コンテナ名、コンテナID、イメージ名となっていて変更できません。
これだとコンテナを起動し直すたびにメトリクスが増えてしまい使い勝手がいまいちでした。。
コンテナのモニタリング
少し脱線して。
コンテナ毎の CPU使用率やメモリ使用率をモニタリングするにはどんな方法があるか調べてみると、そもそも標準の docker cli にありました。。汗
top コマンドのようにコンソールで逐次再表示されます。
$ docker container stats
CONTAINER ID NAME CPU % MEM USAGE / LIMIT MEM % NET I/O BLOCK I/O PIDS
a486eca37e08 dev002-app001 0.00% 2.098MiB / 3.853GiB 0.05% 4.46kB / 0B 0B / 30.7kB 2
84140062b59c dev002-app002 0.00% 2.078MiB / 3.853GiB 0.05% 4.46kB / 0B 0B / 29.7kB 2
他にも、もう少しグラフィカルに表示する ctop
というのがありました。
ctop
https://github.com/bcicen/ctop
docker コンテナにもなっていて、ホストにツールをインストールせず docker run で実行できるようです。
docker run --rm -ti \
--name=ctop \
--volume /var/run/docker.sock:/var/run/docker.sock:ro \
quay.io/vektorlab/ctop:latest
で、ctop の docker 起動コマンドを見ていて一つ気になりました。
--volume /var/run/docker.sock:/var/run/docker.sock:ro
って何?
Docker Engine API
/var/run/docker.sock
を調べてみると、docker はコマンド(cli) とサーバ(engine) 間に Docker Engine API
という REST API があるようです。
Develop with Docker Engine API
https://docs.docker.com/engine/api/
Docker Engine API (v1.41)
https://docs.docker.com/engine/api/v1.41/
以下のように、curl
などのコマンドで簡単に操作できます。
例はコンテナ一覧の取得処理。
$ curl --unix-socket /var/run/docker.sock -X GET http://localhost/containers/json | jq .
[
{
"Id": "a486eca37e0870704fd290d8e33ba2ba4b7a09d2663929651ca91b01b2a70f8c",
"Names": [
"/dev002-app001"
],
"Image": "nginx:latest",
"ImageID": "sha256:f0b8a9a541369db503ff3b9d4fa6de561b300f7363920c2bff4577c6c24c5cf6",
"Command": "/docker-entrypoint.sh nginx -g 'daemon off;'",
:
docker コマンドでできる操作はすべて API があるので、docker container stats
の情報も取得できます。
$ curl --unix-socket /var/run/docker.sock -X GET http://localhost/containers/a486eca37e0870704fd290d8e33ba2ba4b7a09d2663929651ca91b01b2a70f8c/stats?stream=false | jq .
{
"read": "2021-05-29T16:32:58.667688785Z",
"preread": "2021-05-29T16:32:57.662946911Z",
"pids_stats": {
"current": 2
},
:
"num_procs": 0,
"storage_stats": {},
"cpu_stats": { ★CPU情報
"cpu_usage": {
"total_usage": 193324165,
"percpu_usage": [
193324165
],
"usage_in_kernelmode": 30000000,
"usage_in_usermode": 150000000
},
:
"memory_stats": { ★メモリ情報
"usage": 2215936,
"max_usage": 7733248,
"stats": {
"active_anon": 1470464,
:
"name": "/dev002-app001",
"id": "a486eca37e0870704fd290d8e33ba2ba4b7a09d2663929651ca91b01b2a70f8c",
:
}
これを使えばシェルスクリプトでも簡単なモニタリングのツール組めるのでは?
docker コンテナの簡易モニタリングツール
ということで、シェルスクリプトによるモニタリングツールを作ってみました。
[github] mon-docker-cloudwatch
https://github.com/batatch/mon-docker-cloudwatch
[dockerhub] mon-docker-cloudwatch
https://hub.docker.com/r/batatch/mon-docker-cloudwatch
作り込まずに最低限の使い方ができることに意味があるので、本当に簡単な内容です。
$ sh mon-docker-cloudwatch.sh
2021/05/29 16:42:28 Docker - InstanceId:i-aaaaaaaaaaaa ContainerName:dev002-app001 : MemUtilization:0.0531709 MemUsed:2199552 MemAvairable:4136755200
2021/05/29 16:42:28 Docker - InstanceId:i-aaaaaaaaaaaa ContainerName:dev002-app001 : CPUUtilization:0 CPUUser:193324165 CPUSystem:615096770000000
2021/05/29 16:42:30 Docker - InstanceId:i-aaaaaaaaaaaa ContainerName:dev002-app002 : MemUtilization:0.0526759 MemUsed:2179072 MemAvairable:4136755200
2021/05/29 16:42:30 Docker - InstanceId:i-aaaaaaaaaaaa ContainerName:dev002-app002 : CPUUtilization:0 CPUUser:189791026 CPUSystem:615098780000000
:
docker で実行することもできます。
$ docker run --rm -it -v /var/run/docker.sock:/var/run/docker.sock:ro batatch/mon-docker-cloudwatch:latest
2021/05/29 17:09:53 Docker - InstanceId:i-aaaaaaaaaaaa ContainerName:dev002-app001 : MemUtilization:0.0531709 MemUsed:2199552 MemAvairable:4136755200
2021/05/29 17:09:53 Docker - InstanceId:i-aaaaaaaaaaaa ContainerName:dev002-app001 : CPUUtilization:0 CPUUser:193324165 CPUSystem:616729170000000
:
シェルスクリプトを実行すれば、全コンテナの CPU使用率、メモリ使用率などを収集/算出して CloudWatch のメトリクスとして送信します。
(メトリクスの内容を標準出力にもログとして表示します)
Dimention と Metrics は以下の内容で固定です。
-
Dimentions
- InstanceId
- ContainerName
-
Metrics
- ContainerCPUUtilization (%)
- ContainerCPUUser (Bytes)
- ContainerCPUSystem (Bytes)
- ContainerMemoryUtilization (%)
- ContainerMemoryUsed
- ContainerMemoryAvairable
メトリクスの算出方法は REST API の説明に倣ったので docker container stats
の内容と合ってるはずです。
Docker Engine API
、いろいろ遊べそうですね。
// EOF