Diary of a Perpetual Student

Perpetual Student: A person who remains at university far beyond the normal period

Lambda 新機能の Telemetry API を利用した mackerel-lambda-extension-agent 試作

この記事は Mackerel Advent Calendar 2022 16日目の記事です。


こんにちは、id:arthur-1 です。2022年にはてなに新卒入社して、Mackerel 開発チームのアプリケーションエンジニアをやっています。また、今年の Mackerel Advent Calendar の運営を担当しております。よろしくお願いします。

先日、Mackerel チームで「Mackerel アゲアゲ合宿」を開催しました。これは旧来「開発合宿」と称して行ってきたもので、「Mackerel の未来に繋がることを誰かと一緒にやること」をコンセプトとして、5つのチームに分かれて3日間集中して開発やワークに取り組みました。

こちらの運営も担当させていただいたのですが、詳しい運営話は別の機会にさせていただくかもしれません。運営として、「合宿の成果を Advent Calendar にアウトプットしましょう」と Mackerel スタッフに声掛けしているのですが、まずは自分からやらねば、という気持ちでこのエントリを書いています。

今回は、id:arthur-1 のチームで取り組んだ「Lambda Telemetry API を利用した mackerel-lambda-extension-agent 試作」プロジェクトについてご紹介します。

Lambda Telemetry API

AWS の年次イベント re:Invent2022 が開催される少し前に、 Lambda Telemetry API が発表されました。

aws.amazon.com

もともとは Logs API というものが用意されていました。Lambda 関数に extension を登録し、そこから API を subscribe すると、プラットフォームに関する情報や関数が吐き出したログを取得できる、というものです。これを外部に送信することで、実行環境ごと区別した監視が実現可能になります。

Telemetry API はこの Logs API の進化系という立ち位置になっています。API がログの塊を extension 上のサーバに POST していく仕組みはLog API と同じです。OpenTelemetry と情報的な互換がある形でログに span と trace の id がついていたり、実行環境のライフサイクルに関する情報が増えていたりしています。

Telemetry API に関する詳しい説明は、ドキュメントや他の記事に譲ります。

docs.aws.amazon.com

dev.classmethod.jp

mackerel-lambda-extension-agent

Telemetry API を利用して Mackerel でより詳細な Lambda の監視ができるようにと、合宿の3日間 で mackerel-lambda-extension-agent を試作しました。

github.com

Mackerel の AWS インテグレーションで取得できる Lambda のメトリックは関数単位のものでした。しかし、この agent を利用することで、各実行環境ごと Mackerel のホストとして登録し、Telemetry API で取得できるメトリックを投稿することができます。

自動退役にも対応していて、実行環境がシャットダウンされるとき、Mackerel 上のホストを退役させる API リクエストを投げるようにしています。

設定方法は、監視したい Lambda 関数のレイヤーとしてこの mackerel-lambda-extension-agent を追加し、関数本体に環境変数を指定するだけです。このアプリケーションは Go で開発されていますが、Go 以外のランタイムの関数に対しても適用できます。リポジトリの README.md に terraform での設定例を記載しているのでご確認ください。

試しに、Mackerel の staging 環境のシステムで使われている Lambda 関数(ランタイムは Node.js)の extension として、mackerel-lambda-extension-agent を設定してみました。

指定したロールに複数の実行環境がホストとして登録されている様子

Telemetry API の report から取得した Done Duration のグラフ

仕組み解説

まず、以下のような手順で Telemetry API を subscribe します

  1. Extension API にリクエストを投げ、Lambda レイヤーを extension として登録する
  2. Telemetry API からのレスポンスを受ける HTTP サーバを extension 上に立ち上げる
  3. Telemetry API に HTTP サーバの URL を教えるリクエストを投げ、購読する
  4. Telemetry API からサーバにログの塊が次々と送られてくる

subscribe が終わったら、 Mackerel API にリクエストを投げ、ホストとしての登録やグラフ定義の設定を行います。

Telemetry API から受け取ったログはキューに積まれています。1分ごとキューを flush し、それぞれのログの type を見て、メトリックにできるものがあれば集約して Mackerel に投げるようにしています。具体的には、"platform.initReport"、"platform.report"、"platform.runtimeDone" に含まれる内容からメトリックを取得しています。

また、定期的に Extension API にリクエストを送り、イベントを確認しています。ここでシャットダウンのイベントが来たら、1分経過を待たずにキューを flush して最後のメトリックを送り、その後 Mackerel 上に作ったホストを退役させます。

難しかったところ

難しかったのは、extension 上で行っているメトリック集計の部分です。

Mackerel のメトリックは一番細かいもので 1分粒度なので、Telemetry API のレポートから得たメトリックは 1 分ごと平均/合計演算などでロールアップしてから Mackerel に送る必要があります。

しかし、1回の実行時間が短い Lambda 関数に対してこの agent を適用すると、1分待っている間に実行環境がスリープしてしまい、次に関数が invoke されるまでメトリック送信が遅延してしまうという問題があります。

また、Lambda 関数のタイムアウト時間を短く設定すると、extension もその時間でタイムアウトしてしまうため、メトリックが収集できません。

きちんと観測したいなら、無理に直接 Mackerel に投稿せず、即時に他のサーバに送って集計させてから Mackerel に送る方が良さそうです。

まとめ

新機能の Lambda Telemetry API を用いて、Lambda の可観測性がアゲアゲしたのを体感することができました。クラウドシフトしていくと、大規模なストリームを Lambda でバサバサと処理していくアーキテクチャを選択することも多いでしょう。Lambda のモニタリングについて引き続き良いあり方を模索していきたいなと思いました。


qiita.com

prev: 15日目は id:wafuwafu13 さんの mackerel-agent configtest によるチェックの強化について でした

next: 17日目は Kidapan さんの Mackerelの新機能を振り返ってみた~2022年版~ です