sardine - mackerel plugin のメトリクスを CloudWatch で集約する agent を書いた

OSS紹介 Advent Calendar 2017 - Qiita 22日目の記事です。

f:id:sfujiwara:20171222113112j:plain

最近、監視を Zabbix から Mackerel に切り替えていっています。それと並行して、新規プロジェクトは Amazon ECS でコンテナで運用するようにもしていっています。そこで考えどころなのが、コンテナで動作するプロセスのモニタリングをどうするかです。

たとえば、コンテナで動作する nginx を mackerel-plugin-nginx で監視する場合、普通にやるとこんな感じになるのですが…

  • nginx と mackerel-agent を同一タスク (ECS用語) に定義する
  • mackerel-agent.conf で cloud_platform = "none"設定をして、コンテナがホストの EC2 とは切り離された状態でホストとして認識されるようにする

すべてのタスクを Mackerel 上のホストとして認識させることになると、いくつか困ることがあります。

  • 課金対象が増える
    • タスクは EC2 のホストなどよりかなり多くなるため、インパクトが大きい
    • 今後の Fargate 化を考えると、Fargate は最大4コアなので、多数のタスクを配置することになり EC2 で大きなインスタンスを動作させるよりもかなり数が増えそう
  • タスクはデプロイごとに入れ替わるので、ホストの入れ替わりイベントが大量に発生する
    • 自動退役すればみなくてよいとはいえ…

複数コンテナのメトリクスは、集約した状態で一つの値がみられれば用が足りることが多いため、何らかの形で集約メトリクスを実現したかったのですが、現状の Mackerel では同一時刻に登録したサービスメトリックの値は上書きされてしまいます。

そこで、CloudWatch で集約することを考えました。

CloudWatch では同一時刻に複数回送信した値を、合計、最大、最低、平均などの統計(statistics)を指定して取得することができるため、nginx でいうと RequestCount の合計なら単位時間内の総クエスト数、平均なら1コンテナあたりの平均リクエスト数、のように、目的に合わせて値を読み取れます。

sardine

github.com

mackerel-plugin (互換) のコマンドを実行し、得たメトリクスを CloudWatch へ投稿する agent として、sardine を書きました。 Go で実装されたシンプルな agent です。

命名は、mackerel(鯖)より小さいのが群れているので sardine(鰯) ということで。

[plugin.metrics.nginx]
command = "mackerel-plugin-nginx --host nginx --port 80 --path /nginx_status"
dimensions = ["Service=staging", "Service=staging,Task=app"]

このような、mackerel-agent.conf に類似した設定ファイルで定義をします。各 ECS タスクに同梱して動作させる想定です。

デフォルトでは60秒ごとにプラグインをコマンドとして実行し、たとえば得られた出力が以下だった場合に

nginx.requests.requests 123.0 1512057958

CloudWatch のメトリクスとしては以下の値を投稿します。

  • Namespace: nginx/requests
  • MetricName: requests
  • Value: 123.0
  • Timestamp: 2017-12-01T16:05:58Z

これで複数の同一種類のコンテナ、タスクから投稿された値を、大づかみにして把握できます。

f:id:sfujiwara:20171222121835p:plain

この集約されたメトリクスを、Fluentd を用いて (plugin-cloudwatch + plugin-macakrel) Mackerel に値を持っていくことで、Mackerel 上でグラフを並べてみることもできます。

f:id:sfujiwara:20171222121956p:plain

まとめ

  • コンテナ、タスク単位で Mackerel にホストを作らず、集約メトリクスを実現するために sardine を作りました
  • Mackerel 本体だけで、このような集約メトリクスが実現できると嬉しいです