ようへいの日々精進XP

よかろうもん

ECS タスクメタデータエンドポイントを使ったバッチ処理コンテナのリソースモニタリングツール kobanzame を作りました

追記 (2020/06/15) Container Insights は GA しています!

2020/06/14 現在はベータ版として提供されていますが

この記述は誤りで Container Insights は 2019 年 11 月には既に GA されておりますので, ここで訂正させて頂きます.

aws.amazon.com

確認不足で誤った情報を記述してしまい大変申し訳ございませんでした.

tl;dr

以前に以下のような記事を書きました.

inokara.hateblo.jp

この記事では, Fargate で動いているバッチ処理タスクの CPU 使用率やメモリ使用量のリソース情報を ECS タスクメタデータエンドポイントから取得し, バッチ処理タスクが終了したらリソース情報を集計してバッチ処理タスクのログに差し込む仕組みを紹介させて頂いています.

docs.aws.amazon.com

記事を書いてからもうすぐ一年が経過しようとしているところで, この仕組みのコードを夜な夜なコツコツと整理して gem 化したので紹介させて頂きます.

kobanzame

作ったもの

github.com

rubygems.org

Kobanzame = コバンザメ.

サイドカー的にバッチ処理が実行されるコンテナにくっついてリソースの情報を取得する様が, 大きなクジラにくっついてそのおこぼれ等を餌にしているコバンザメのようだったので命名しました.

仕組み

仕組み自体は以下のようなイメージです.

f:id:inokara:20200613223419p:plain

ECS タスクにサイドカーコンテナとして Kobanzame コンテナを追加します. Kobanzame コンテナは Batch Worker コンテナが動き続けている限り, タスクメタデータエンドポイントにアクセス (デフォルトで 1 秒毎) して Batch Worker コンテナの CPU 使用率とメモリ使用量を収集します.

Batch Worker コンテナが終了 (正常, 異常問わず) すると, CPU 使用率とメモリ使用量を集計して Batch Worker のログが出力されている CloudWatch Logs の Log Stream の最終行に差し込みます. (下図の通り.)

f:id:inokara:20200613224916p:plain

集計された情報は, 以下のようにテキストまたは JSON フォーマットで送信することが可能です.

# テキストフォーマット
REPORT TaskID: xxxxxxxx Duration: 10ms, Memory Used: 133.4MiB(ave)/200.621MiB(max), CPU Usage: 62.567%(ave)/90.3%(max)

# JSON フォーマット
{
  "report": {
    "duration": {
      "duration": 10,
      "unit": "ms"
    },
    "memory_used": {
      "average": 133.4,
      "max": 200.621,
      "unit": "MiB"
    },
    "cpu_usage": {
      "average": 62.567,
      "max": 90.3,
      "unit": "%"
    }
  },
  "task_id": "xxxxxxxx",
  "docker_name": "foo"
}

また, 前回は実装していなかったのですが, CPU 使用率とメモリ使用量を CloudWatch メトリクスにカスタムメトリクスとして記録するようにしています.

f:id:inokara:20200613225453p:plain

なんちゃってプラグインアーキテクチャ

現時点では, 集計情報は Batch Worker の Log Stream に差し込み, メトリクスは CloudWatch メトリクスのみに記録するようになっていますが, なんちゃってプラグインアーキテクチャになっている為, 必要に応じて, Slack や Datadog 等に送信することも可能です.

以下は雑に Slack チャンネルに通知した様子です.

f:id:inokara:20200614072724p:plain

使い方

設定ファイル

kobanzame は JSON で設定ファイルを書きます. 以下は設定例です.

{
  "container": {
    "name": "batch-worker",
    "check_interval": 1,
    "report_format": "json"
  },
  "metrics": {
      "name": "cloudwatch",
      "namespace": "Custom/Kobanzame"
  },
  "outputs": [
    {
      "name": "cloudwatch_logs",
      "log_group_name": "kobanzame-sample-dev-batch-worker",
      "log_stream_prefix": "batch-worker",
      "log_stream_name": "batch-worker-resource-statistics"
    }
  ]
}

以下に設定内容について簡単に解説させて頂きます.

container セクションには, 対象コンテナ名を指定します (「仕組み」にて掲載している図の Batch Worker を指しています).

Key Required Value Example description
name Yes batch-worker 対象コンテナ名を指定します
check_interval Yes 1 リソース情報取得する間隔を指定します
report_format Yes json 集計情報を出力するフォーマットを指定します. JSON 以外に Text や CSV も指定可能です

metrics セクションには, リソース情報を送信する CloudWatch のネームスペースを指定します (現在は CloudWatch のみに対応しています).

Key Required Value Example description
name Yes cloudwatch 取得したメトリクスを送信します (現在は CloudWatch のみ対応)
namespace Yes Custom/Kobanzame CloudWatch メトリクスのネームスペースを指定します

outputs セクションには, リソースの集計情報の送信先を指定します.

Key Required Value Example description
name Yes cloudwatch_logs 集計した情報を CloudWatch Logs に送信します
log_group_name Yes kobanzame-sample-dev-batch-worker 送信する Log Group 名を指定します
log_stream_prefix No batch-worker 送信する Log Stream 名を指定します
log_stream_name No batch-worker-resource-statistics 送信する Log Stream 名を指定します

log_stream_prefix を指定した場合には, Batch Worker が出力する Log Stream のプレフィックスを指定すると, Lambda ファンクションの実行結果のようにログが出力されています. また log_stream_name を指定した場合には, 集計結果のみが指定した Log Stream に集積されます.

尚, 設定ファイル名自体は任意で OK です.

実行

設定ファイルを setting.json というファイル名で作成した場合, 以下のように kobanzame を実行します.

$ kobanzame --config=setting.json

その他のオプションは以下の通りです.

$ kobanzame --config=setting.json
Usage: kobanzame [options]
    -c, --config PATH                config file path (default: kobanzame.json)
    -d, --daemonize                  enable daemonize (default: false)
    -p, --pid-file PATH              pid file path (default: kobanzame.pid)
    -l, --log-file PATH              log file path (default: STDOUT)
    -D, --debug                      start with debug mode (default: false)

Example

kobanzame を実装するにあたって利用した各種ファイル (Fargate 等を構築する Terraform コードや Run Task をラップしたシェルスクリプト等) をリポジトリexample フォルダに置きました.

f:id:inokara:20200614123313p:plain

参考

今回, kobanzame を実装するにあたって, 以下の OSS ツールを参考 (利用) させて頂きました.

github.com

serverengine はその名の通り, Ruby でサーバーを実装するにあたって必要な PID ファイルの作成やログファイルの出力, 安全にプロセスを停止する為の仕組みが提供されていて, あの fluentd でも利用されているライブラリです. serverengine については, udzura さんの以下のブログ記事も参考にさせて頂きました.

udzura.hatenablog.jp

kobanzame には緩い感じのプラグイン機構が備わっていて, 集計結果の出力先やメトリクスの送信先をコア部分に影響が無いように追加することが可能です. このなんちゃってプラグイン機構のヒントと実装は sonots さんの alerty を参考にさせて頂きました.

github.com

serverengine も fluentd も alerty も以前から存じ上げていましたが, 改めて kobanzame を実装するにあったて, ソースコードを読みましたが, 理解出来ているかは置いといて大変勉強になりました. 有難うございました.

それ, Container Insights で良いんじゃないのか

おっしゃるとおり

docs.aws.amazon.com

ちゃんと使えていないのですが, コンテナのリソースを収集して CloudWatch メトリクスで確認出来る Container Insights が東京リージョンでも利用出来ます. 2020/06/14 現在はベータ版として提供されていますが, ECS のクラスタ毎, サービス毎, タスク毎にコンテナのメトリクスを確認出来ますし, 当然 kobanzame では取得出来ないメトリクスも確認出来るので, ちゃんとコンテナを監視したい場合には Container Insights を利用することをオススメしたいと思います.

じゃあ, なぜ, 俺は kobanzame を作ったのか

こちら にも書いたように, 以下のような目的がありました. 当時は Container Insights は GA されていなかったりして, Fargate で動いているコンテナのリソース状況を 手軽 に把握する術を模索していました. (Datadog や Mackrel 等のツールも検討しましたが, これらのツールどのようにコンテナのリソースを収集しているかを調べるうちに自分で実装していたという感じです.)

  • バッチ処理でどのくらいの CPU やメモリリソースが使われているのかざっくりと把握したい
  • 今後のコンテナリソースサイズを検討する際の参考にしたい

そして, バッチ処理のログ出力に Lambda ファンクションのログ出力のようなリソース使用状況を出力したかったことも理由です. 実際にログに出力して, そのログを Elasticsearch に転送して可視化したりして, バッチ処理の改善に役立てることが出来ていると思います.

以上

ECS タスクメタデータエンドポイントを使ったコンテナのリソースモニタリングツール kobanzame を紹介させて頂きました. 多くの人に使って頂きたいというわけではありませんが, 同じような悩みを持たれている方の課題解決に少しでもお役に立てれば幸いです.