Prometheusエージェントモードの紹介:メトリクス転送のための効率的でクラウドネイティブな方法

2021年11月16日筆者: Bartlomiej Plotka(@bwplotka)

Bartek Płotkaは2019年からPrometheusメンテナーを務め、Red Hatのプリンシパルソフトウェアエンジニアです。CNCF Thanosプロジェクトの共同著者でもあります。CNCFアンバサダーであり、CNCF TAG Observabilityのテックリードでもあります。余暇には、O'Reilly社から「Efficient Go」というタイトルの本を執筆しています。意見は私個人のものです!

Prometheusプロジェクトで私が個人的に気に入っていること、そしてチームに参加した多くの理由の一つは、プロジェクトの目標に対するレーザーのような集中力でした。Prometheusは、実用的で信頼性が高く、安価でありながら非常に価値のあるメトリクスベースの監視を提供することに関して、常に限界を押し広げてきました。Prometheusの超安定した堅牢なAPI、クエリ言語、統合プロトコル(例:Remote WriteとOpenMetrics)により、Cloud Native Computing Foundation(CNCF)のメトリクスエコシステムはこれらの強固な基盤の上に成長することができました。その結果、素晴らしいことが起こりました。

  • コミュニティのエクスポーターが、実質的にあらゆるものに関するメトリクスを取得しているのを見ることができます。例えば、コンテナeBPFMinecraftサーバーの統計、さらにはガーデニングでの植物の健康状態に関するものまであります。
  • 今日、ほとんどの人は、クラウドネイティブなソフトウェアがPrometheusがスクレイピングできるHTTP/HTTPSの/metricsエンドポイントを持つことを期待しています。これはGoogle内で秘密裏に開発され、Prometheusプロジェクトによって世界的に普及したコンセプトです。
  • オブザーバビリティのパラダイムは変化しました。SREと開発者が初日からメトリクスに大きく依存することで、ソフトウェアの回復力、デバッグのしやすさ、データ駆動型の意思決定が向上しています!

結局のところ、Prometheusが実行されていないKubernetesクラスターはほとんど見かけません。

Prometheusコミュニティの強い焦点は、他のオープンソースプロジェクトも成長させ、Prometheusのデプロイモデルを単一ノードを超えて拡張させました(例:CortexThanosなど)。Amazon、Google、Grafana、Logz.ioなどのクラウドベンダーがPrometheusのAPIとデータモデルを採用していること(例:Amazon Managed PrometheusGoogle Cloud Managed PrometheusGrafana Cloudなど)は言うまでもありません。Prometheusプロジェクトがこれほど成功している理由を一つ挙げるとすれば、それはこれです。監視コミュニティを重要なことに集中させること

この(長文の)ブログ記事では、「エージェント」と呼ばれるPrometheusの新しい運用モードをご紹介したいと思います。これはPrometheusのバイナリに直接組み込まれています。エージェントモードは、Prometheusの通常の機能の一部を無効にし、リモートロケーションへのスクレイピングとリモート書き込みのためにバイナリを最適化します。機能を減らすモードを導入することで、新しい使用パターンが可能になります。このブログ記事では、なぜこれがCNCFエコシステムにおける特定のデプロイメントにとってゲームチェンジャーとなるのかを説明します。私はこれに非常に興奮しています!

転送ユースケースの歴史

Prometheusの核となる設計は、プロジェクトの全期間を通じて変更されていません。GoogleのBorgmon監視システムに触発されて、監視したいアプリケーションの隣にPrometheusサーバーをデプロイし、Prometheusにそれらへの到達方法を伝え、定期的にメトリクスの現在の値をスクレイピングさせることができます。この収集方法(しばしば「プルモデル」と呼ばれます)は、Prometheusを軽量で信頼性の高いものにする中心的な原則です。さらに、アプリケーションの計測とエクスポーターを非常にシンプルにします。複雑なプッシュインフラストラクチャや自明ではないクライアントライブラリを必要とせずに、追跡されているすべてのメトリクスの現在の値(OpenMetrics形式)を含むシンプルな人間が読めるHTTPエンドポイントを提供するだけでよいからです。全体として、簡略化された典型的なPrometheus監視デプロイメントは以下のようになります。

Prometheus high-level view

これは非常にうまくいき、何百万もの成功したデプロイメントが長年にわたって数千万のアクティブシリーズを処理してきました。中には、2年程度のより長い期間の保持のために使用されているものもあります。これらはすべて、クラスター管理者と開発者の両方にとって有用なメトリクスをクエリ、アラート、記録することを可能にします。

しかし、クラウドネイティブの世界は常に成長し、進化しています。マネージドKubernetesソリューションと、数秒でオンデマンドで作成されるクラスターの成長により、私たちはついにクラスターを「家畜」(つまり、個々のインスタンスについてあまり気にしない)として扱うことができるようになりました。場合によっては、ソリューションはもはやクラスターの概念すら持っていません。例えば、kcpFargate、その他のプラットフォームなどです。

Yoda

もう1つの興味深いユースケースとして、**エッジ**クラスターまたはネットワークの概念が浮上しています。電気通信、自動車、IoTデバイスなどの産業がクラウドネイティブ技術を採用するにつれて、リソースが制限されたはるかに小さなクラスターが増加しています。これにより、すべてのデータ(オブザーバビリティを含む)をリモートのより大きな対応する場所に転送する必要が生じています。これらのリモートノードにはほとんど何も保存できないためです。

それは何を意味するのでしょうか?監視データは何らかの方法で集約され、ユーザーに提示され、場合によっては**グローバル**レベルで保存される必要があります。これはしばしば**グローバルビュー**機能と呼ばれます。

素朴に考えると、これを実現するには、グローバルレベルにPrometheusを置いてリモートネットワーク全体でメトリクスをスクレイピングするか、アプリケーションから直接中央の場所にメトリクスをプッシュして監視目的で使う、という方法が考えられます。しかし、どちらも一般的に**非常に**悪いアイデアであることを説明させてください。

🔥 ネットワーク境界を越えてスクレイピングを行うと、監視パイプラインに新たな未知の要素が加わり、課題となる可能性があります。ローカルプルモデルでは、Prometheusはメトリックターゲットがどのような問題で、いつ発生したかを正確に把握できます。ダウンしている、設定ミス、再起動、メトリックを提供するのに遅すぎる(CPUが飽和しているなど)、サービスディスカバリで検出できない、アクセスするための資格情報がない、DNS、ネットワーク、またはクラスター全体がダウンしているなどです。スクレーパーをネットワークの外に配置することで、個々のターゲットとは無関係なスクレイピングの信頼性の低下を引き起こし、これらの情報の一部を失うリスクがあります。さらに、ネットワークが一時的にダウンした場合、重要な可視性を完全に失うリスクもあります。これはしないでください。それだけの価値はありません。(

🔥 アプリケーションから直接中央の場所にメトリクスをプッシュすることも同様に良くありません。特に大規模なフリートを監視する場合、リモートアプリケーションからメトリクスが見えないとき、文字通り何もわかりません。アプリケーションがダウンしているのか?受信パイプラインがダウンしているのか?アプリケーションの認証に失敗したのか?リモートクラスターのIPアドレスを取得できなかったのか?遅すぎるのか?ネットワークがダウンしているのか?さらに悪いことに、一部のアプリケーションターゲットからのデータが失われていることさえ知らないかもしれません。そして、データを送信すべきすべてのものの状態とステータスを追跡する必要があるため、大きなメリットもありません。このような設計は、簡単に失敗のレシピとなる可能性があるため、慎重な分析が必要です。

注意サーバーレス関数や短命コンテナは、アプリケーションからのプッシュを救済策として考えるケースがよくあります。しかし、この時点では、より長く存続する時系列に集約したいイベントやメトリクスの一部について話しています。このトピックはこちらで議論されていますので、ぜひ貢献して、これらのケースをよりよくサポートする手助けをしてください!

Prometheusは、グローバルビューケースをサポートするために3つの方法を導入しました。それぞれに長所と短所があります。それらを簡単に見ていきましょう。以下の図ではオレンジ色で示されています。

Prometheus global view

  • フェデレーションは、集約目的で最初に導入された機能です。これにより、グローバルレベルのPrometheusサーバーは、リーフPrometheusからメトリクスの一部をスクレイピングできます。このような「フェデレーション」スクレイピングは、フェデレーションエンドポイントによって公開されるメトリクスに元のサンプルのタイムスタンプが含まれるため、ネットワーク間の未知の要素の一部を減らします。しかし、通常はすべてのメトリクスをフェデレーションできないことや、より長いネットワークパーティション(数分)中にデータを失うことの問題を抱えています。
  • Prometheus Remote Readは、直接PromQLクエリを使用せずに、リモートPrometheusサーバーのデータベースから生のメトリクスを選択することを可能にします。Prometheusまたは他のソリューション(例:Thanos)をグローバルレベルにデプロイして、このデータに対してPromQLクエリを実行し、複数のリモートロケーションから必要なメトリクスをフェッチできます。これは、データを「ローカル」に保存し、必要なときにのみアクセスできるため、非常に強力です。残念ながら、欠点もあります。クエリプッシュダウンのような機能がないと、極端なケースでは1つのクエリに答えるためにGB単位の圧縮されたメトリクスデータをプルすることになります。また、ネットワークパーティションが発生した場合、一時的に何も見えなくなります。最後に、特定のセキュリティガイドラインでは、エグレスのみを許可し、イングレストラフィックを許可しない場合があります。
  • 最後に、今日最も人気のある選択肢であると思われるPrometheus Remote Writeがあります。エージェントモードはリモート書き込みのユースケースに焦点を当てているため、これについて詳しく説明します。

リモート書き込み

Prometheus Remote Writeプロトコルを使用すると、Prometheusによって収集されたすべてのメトリクス、またはその一部をリモートロケーションに転送(ストリーミング)できます。Prometheusを、Remote Write APIをサポートする1つまたは複数のロケーションに特定のメトリクス(必要であれば、すべてのメタデータとエグゼンプラーも!)を転送するように設定できます。実際、PrometheusはRemote Writeの取り込みと送信の両方をサポートしているため、Prometheusをグローバルレベルにデプロイして、そのストリームを受信し、クラスター間でデータを集約できます。

公式のPrometheus Remote Write API仕様はレビュー段階ですが、エコシステムはRemote Writeプロトコルをデフォルトのメトリクスエクスポートプロトコルとして採用しました。例えば、Cortex、Thanos、OpenTelemetry、そしてAmazon、Google、Grafana、Logz.ioなどのクラウドサービスはすべて、Remote Writeを介したデータ取り込みをサポートしています。

Prometheusプロジェクトは、そのAPIの公式準拠性テストも提供しています。例えば、Remote Writeクライアント機能を提供するソリューション向けのremote-write sender complianceがあります。これは、このプロトコルを正しく実装しているかどうかを迅速に判断する素晴らしい方法です。

このようなスクレーパーからのデータストリーミングは、メトリクスデータを一元的な場所に保存することを可能にすることで、グローバルビューのユースケースを可能にします。これにより、関心の分離も可能になり、アプリケーションがオブザーバビリティまたは監視パイプラインとは異なるチームによって管理されている場合に役立ちます。さらに、Remote Writeが、顧客からできるだけ多くの作業をオフロードしたいベンダーに選ばれる理由でもあります。

ちょっと待ってください、バーテック。アプリケーションから直接メトリクスをプッシュするのは最善のアイデアではないと以前に言ったばかりですよね!

確かにそうですが、素晴らしい点は、リモート書き込みを使用しても、Prometheusは依然としてプルモデルを使用してアプリケーションからメトリクスを収集しているため、これらの異なる障害モードを理解できることです。その後、サンプルとシリーズをバッチ処理し、データをリモート書き込みエンドポイントにエクスポート、レプリケート(プッシュ)することで、中央ポイントが持つ監視の未知の数を制限します!

信頼性が高く効率的なリモート書き込みの実装は、解決するのが簡単ではない問題であることに注意することが重要です。Prometheusコミュニティは、安定したスケーラブルな実装を考案するのに約3年を費やしました。WAL(write-ahead-log)を数回再実装し、内部キューイング、シャーディング、スマートなバックオフなどを追加しました。これらはすべてユーザーからは隠されており、ユーザーは大量のメトリクスを一元的な場所に保存する、高性能なストリーミングを楽しむことができます。

実践的なリモート書き込みの例:Katacodaチュートリアル

これらすべてはPrometheusにとっては新しいことではありません。私たちの多くはすでにPrometheusを使って必要なすべてのメトリクスをスクレイピングし、そのすべてまたは一部をリモートロケーションにリモート書き込みしています。

リモート書き込み機能の実践を試したい場合は、Thanos KatacodaのPrometheusからのメトリクスリモート書き込みチュートリアルをお勧めします。Prometheusがすべてのメトリクスをリモートロケーションに転送するために必要なすべての手順を説明しています。無料ですので、アカウントを登録してチュートリアルをお楽しみください!🤗

この例では、Thanosを受信モードでリモートストレージとして使用していることに注意してください。今日では、リモート書き込みAPIと互換性のある他の多くのプロジェクトを使用できます。

リモート書き込みがうまく機能するのに、なぜPrometheusに特別なエージェントモードを追加したのでしょうか?

Prometheusエージェントモード

Prometheus v2.32.0(次のリリース)からは、誰もが実験的な--enable-feature=agentフラグを使ってPrometheusバイナリを実行できるようになります。リリース前に試したい場合は、Prometheus v2.32.0-beta.0を使用するか、quay.io/prometheus/prometheus:v2.32.0-beta.0イメージを使用してください。

エージェントモードは、リモート書き込みのユースケース向けにPrometheusを最適化します。クエリ、アラート、ローカルストレージを無効にし、カスタムのTSDB WALに置き換えます。その他はすべて同じです。スクレイピングロジック、サービスディスカバリ、および関連する設定はそのままです。データをリモートのPrometheusサーバーまたは他のRemote-Write互換プロジェクトに転送したいだけの場合、Prometheusのドロップイン代替として使用できます。本質的にはこのようになります。

Prometheus agent

Prometheus Agentの最も素晴らしい点は、Prometheusに組み込まれていることです。同じスクレイピングAPI、同じセマンティクス、同じ設定とディスカバリーメカニズムを使用します。

データをローカルでクエリしたりアラートしたりせず、メトリクスを外部にストリームする予定がある場合、Agentモードを使用するメリットは何でしょうか?いくつかあります。

まず第一に、効率性です。カスタマイズされたAgent TSDB WALは、書き込みが成功するとすぐにデータを削除します。リモートエンドポイントに到達できない場合、リモートエンドポイントがオンラインに戻るまでデータを一時的にディスクに保持します。これは現在、非エージェントPrometheusと同様に2時間バッファに制限されていますが、まもなく解除されることを期待しています。これは、メモリにデータチャンクを構築する必要がないことを意味します。クエリ目的で完全なインデックスを維持する必要もありません。本質的に、Agentモードは、通常のPrometheusサーバーが同様の状況で使用するリソースのごく一部しか使用しません。

この効率性が重要なのでしょうか?はい!すでに述べたように、エッジクラスターで使用されるメモリのGBとCPUコアは、一部のデプロイメントにとって重要です。一方、メトリクスを使用した監視のパラダイムは、今日では非常に成熟しています。つまり、同じコストでより高いカーディナリティを持つ関連するメトリクスをより多く転送できる方が良いということです。

注意エージェントモードの導入により、従来のPrometheusサーバーモードは引き続き推奨される、安定した、維持されるモードとして残ります。エージェントモードとリモートストレージを組み合わせると、さらに複雑さが増します。注意して使用してください。

第二に、新しいエージェントモードの利点は、取り込みの水平スケーラビリティを容易にすることです。これが私が最も興奮していることです。その理由を説明させてください。

夢:自動スケーラブルなメトリクス取り込み

スクレイピングのための真に自動スケーラブルなソリューションは、メトリクスターゲットの量とそれらが公開するメトリクス数に基づいていなければなりません。スクレイピングするデータが多ければ多いほど、Prometheusのインスタンスを自動的に多くデプロイします。ターゲットの数やメトリクス数が減れば、スケールダウンしていくつかのインスタンスを削除できます。これにより、Prometheusのサイズ調整の手作業の負担がなくなり、クラスターが一時的に小さい状況でPrometheusに過剰なリソースを割り当てる必要がなくなります。

サーバーモードのPrometheusだけでは、これを達成するのは困難でした。これは、サーバーモードのPrometheusがステートフルであるためです。収集されたものはすべて、単一の場所にそのまま残ります。つまり、スケールダウン手順では、終了する前に収集されたデータを既存のインスタンスにバックアップする必要がありました。そうすると、スクレイピングの重複、誤解を招く鮮度マーカーなどの問題が発生します。

それに加えて、すべてのインスタンスにわたってすべてのサンプルを集約できるグローバルビュークエリ(Thanos QueryやPromxyなど)が必要になります。最後に、サーバーモードのPrometheusのリソース使用量は、取り込みだけでなく、アラート、記録、クエリ、圧縮、リモート書き込みなど、メトリクスターゲットの数とは無関係に、より多くのリソースまたはより少ないリソースを必要とする可能性があるものに依存します。

エージェントモードは、基本的にディスカバリ、スクレイピング、リモート書き込みを個別のマイクロサービスに移動します。これにより、取り込みのみに特化した運用モデルが可能になります。その結果、エージェントモードのPrometheusはほぼステートレスになります。確かに、メトリクスが失われるのを避けるためには、エージェントのHAペアをデプロイし、永続ディスクを接続する必要があります。しかし、技術的に言えば、数千のメトリクスターゲット(例:コンテナ)がある場合、複数のPrometheusエージェントをデプロイし、どのレプリカがどのターゲットをスクレイピングするかを安全に変更できます。これは、最終的にすべてのサンプルが同じ中央ストレージにプッシュされるためです。

全体として、Prometheusのエージェントモードは、Prometheusベースのスクレイピングの容易な水平自動スケーリング機能を実現し、メトリクスターゲットの動的な変更に対応できます。これは間違いなく、Prometheus Kubernetes Operatorコミュニティと共に今後検討していくことでしょう。

それでは、現在実装されているPrometheusのエージェントモードの状態を見てみましょう。使用準備はできていますか?

エージェントモードは大規模に実証済み

次期Prometheusリリースには、エージェントモードが実験的な機能として含まれる予定です。フラグ、API、ディスク上のWAL形式は変更される可能性があります。しかし、実装のパフォーマンスは、Grafana Labsのオープンソース活動のおかげで、すでに実戦でテストされています。

エージェントのカスタムWALの最初の実装は、既存のPrometheusサーバーのTSDB WALに触発され、PrometheusメンテナーのTom Wilkieの指導のもと、2019年にRobert Frattoによって作成されました。その後、多くのGrafana Cloud顧客とコミュニティメンバーによって使用されているオープンソースのGrafana Agentプロジェクトで使用されました。ソリューションの成熟度を考慮して、ネイティブ統合とより広範な採用のために実装をPrometheusに寄贈する時期が来ました。Robert(Grafana Labs)は、Srikrishna(Red Hat)とコミュニティの助けを借りて、コードをPrometheusコードベースに移植し、2週間前にmainにマージされました!

寄贈プロセスは非常にスムーズでした。Prometheusのメンテナーの一部が以前Grafana Agent内でこのコードに貢献しており、新しいWALがPrometheus自身のWALに触発されているため、現在のPrometheus TSDBメンテナーが完全に保守を引き継ぐことは難しくありませんでした!また、RobertがPrometheusチームにTSDBメンテナーとして参加することになったことも非常に役立ちます(おめでとうございます!)。

では、その使い方を詳しく説明しましょう!(

エージェントモードの詳しい使い方

これからは、Prometheusのヘルプ出力(--helpフラグ)を表示すると、多かれ少なかれ次のようになるはずです。

usage: prometheus [<flags>]

The Prometheus monitoring server

Flags:
  -h, --help                     Show context-sensitive help (also try --help-long and --help-man).
      (... other flags)
      --storage.tsdb.path="data/"
                                 Base path for metrics storage. Use with server mode only.
      --storage.agent.path="data-agent/"
                                 Base path for metrics storage. Use with agent mode only.
      (... other flags)
      --enable-feature= ...      Comma separated feature names to enable. Valid options: agent, exemplar-storage, expand-external-labels, memory-snapshot-on-shutdown, promql-at-modifier, promql-negative-offset, remote-write-receiver,
                                 extra-scrape-metrics, new-service-discovery-manager. See https://prometheus.dokyumento.jp/docs/prometheus/latest/feature_flags/ for more details.

エージェントモードは、前述のとおり、機能フラグの背後にありますので、--enable-feature=agentフラグを使用してPrometheusをエージェントモードで実行してください。残りのフラグは、サーバーとエージェントの両方、または特定のモード専用です。どのフラグがどのモード用であるかは、フラグのヘルプ文字列の最後の文を確認することでわかります。「Use with server mode only」という記載があればサーバーモード専用です。このような記載がなければ、そのフラグは共有されています。

エージェントモードは、同じディスカバリーオプションとリモート書き込みオプションを持つ同じスクレイピング設定を受け入れます。

また、クエリ機能は無効になっていますが、通常のPrometheusサーバーと同様に、ビルド情報、設定、ターゲット、サービスディスカバリー情報を表示するウェブUIも公開しています。

実践的なPrometheusエージェントの例:Katacodaチュートリアル

Prometheusリモート書き込みチュートリアルと同様に、Prometheus Agent機能の実践的な体験を試したい場合は、Thanos KatacodaのPrometheus Agentチュートリアルをお勧めします。Prometheus Agentの実行がいかに簡単かを説明しています。

まとめ

この情報が面白いと感じていただけたなら幸いです!この投稿では、以下のような新たなケースについて説明しました。

  • エッジクラスター
  • アクセス制限されたネットワーク
  • 多数のクラスター
  • 一時的かつ動的なクラスター

次に、スクレイピングされたメトリクスをリモート書き込みエンドポイントに効率的に転送できる新しいPrometheus Agentモードについて説明しました。

いつものように、何か問題やフィードバックがあれば、お気軽にGitHubでチケットを提出するか、メーリングリストで質問してください

このブログ記事は、CNCF、Grafana、Prometheusの間で調整されたリリースの一部です。CNCFの発表と、Prometheus Agentの基盤となるGrafana Agentに関する視点もぜひお読みください。