プル方式はスケーリングしない — 本当か?
2016年7月23日筆者: Julius Volz
特に根強く残る迷信について話しましょう。モニタリングシステムについて議論していると、Prometheusのプルベースのメトリクス収集アプローチに話題が移った際、誰かが必ず「プルベースのアプローチは根本的にスケーリングしない」と口を挟みます。その理由とされるものは、しばしば曖昧であったり、Prometheusとは根本的に異なるシステムにしか適用できないものです。実際、私たちはプルベースのモニタリングを最大規模で運用してきた経験から、この主張は私たちの運用経験とは全く逆のものです。
Prometheusがプッシュではなくプルを選択する理由については、FAQにすでに記載がありますが、スケーリングの側面には特化していません。ここでは、この主張を巡る一般的な誤解を詳しく見ていき、それらがPrometheusにどの程度、どのように適用されるのかを分析します。
PrometheusはNagiosではない
プル方式のモニタリングシステムと聞くと、多くの人はNagiosを思い浮かべます。Nagiosは、CPU負荷の高いサブプロセスを起動してホストやサービスの健全性を判断するアクティブチェックを行うため、スケーリングがうまくいかないという評判があります。このようなチェックアーキテクチャは、中央のNagiosホストがすぐに飽和してしまうため、確かにスケーリングには向きません。その結果、通常は数分に一度しかチェックを実行しないように設定するか、より深刻な問題に直面することになります。
しかし、Prometheusは根本的に異なるアプローチを採用しています。チェックスクリプトを実行する代わりに、インストゥルメント化されたターゲットセットからネットワーク経由で時系列データを収集するだけです。各ターゲットに対し、PrometheusサーバーはHTTP経由でそのターゲットのすべてのメトリクスの現在の状態を(ゴルーチンを使用して非常に並列的に)取得するだけで、プルに関連する他の実行オーバーヘッドはありません。ここで次の点に移ります。
接続をどちらが開始するかは関係ない
スケーリングの目的においては、メトリクスが転送されるTCP接続をどちらが開始するかは関係ありません。どちらの方法でも、接続確立の労力は、メトリクスペイロードやその他の必要な作業と比較してわずかです。
しかし、プッシュベースのアプローチならUDPを使って接続確立を回避できる、と言うかもしれません!確かにその通りですが、PrometheusにおけるTCP/HTTPのオーバーヘッドは、Prometheusサーバーがデータを収集するために行う他の作業(特に時系列データをディスクに永続化すること)と比較すると、依然として無視できるほど小さいです。具体的な数字を挙げると、単一の大きなPrometheusサーバーは、数百万の時系列データを容易に保存でき、SoundCloudでの実際のプロダクションメトリクスデータで測定された記録は毎秒80万サンプルです。10秒のスクレイプ間隔とホストあたり700の時系列で、これは単一のPrometheusサーバーから10,000台以上のマシンを監視できることを意味します。ここでのスケーリングのボトルネックは、メトリクスをプルすることではなく、通常はPrometheusサーバーがメモリにデータを取り込み、ディスク/SSDに持続的に保存・期限切れ処理する速度に関連しています。
また、今日のネットワークは非常に信頼性が高くなっていますが、TCPベースのプルアプローチを使用することで、メトリクスデータが確実に到着すること、またはネットワークの破損によりメトリクスの転送が失敗した場合、モニタリングシステムがすぐにそれを知ることができるようになります。
Prometheusはイベントベースのシステムではない
一部のモニタリングシステムはイベントベースです。つまり、HTTPリクエスト、例外など、個々のイベントが発生したときにすぐに中央のモニタリングシステムに報告します。この中央システムは、イベントをメトリクスに集計する(StatsDがその代表例です)か、後で処理するために個々のイベントを保存します(ELKスタックがその例です)。このようなシステムでは、プルは確かに問題になります。インストゥルメント化されたサービスは、プル間でイベントをバッファリングする必要があり、プッシュベースのアプローチと同じ「リアルタイム性」をシミュレートし、イベントバッファを飽和させないためには、プルを非常に頻繁に行う必要があります。
しかし、ここでも、Prometheusはイベントベースのモニタリングシステムではありません。Prometheusに生のイベントを送信することも、Prometheusがそれを保存することもできません。Prometheusは集計された時系列データを収集するビジネスを行っています。これは、メトリクス生成の基となったイベントではなく、指定されたメトリクスセットの現在の*状態*を定期的に収集することのみに関心があることを意味します。例えば、インストゥルメント化されたサービスは、HTTPリクエストを処理するたびにPrometheusにメッセージを送信するのではなく、メモリ内でそれらのリクエストをカウントアップするだけです。これは、モニタリングトラフィックを発生させることなく、毎秒数十万回発生する可能性があります。Prometheusは、15秒または30秒ごと(または設定した間隔)にサービスインスタンスに現在のカウンター値について問い合わせ、その値をスクレイプタイムスタンプとともにサンプルとして保存します。ゲージ、ヒストグラム、サマリーなどの他のメトリクスタイプも同様に処理されます。結果として生じるモニタリングトラフィックは少なく、プルベースのアプローチもこの場合問題を引き起こしません。
しかし、私のモニタリングはサービスインスタンスを知る必要があるのでは?
プルベースのアプローチでは、モニタリングシステムはどのサービスインスタンスが存在し、どのように接続するかを知る必要があります。一部の人々は、モニタリングシステム側でこの追加設定が必要になることを懸念しており、これを運用上のスケーラビリティの問題と見なしています。
真剣なモニタリング設定においては、どのような場合でもこの設定作業を避けることはできないと私たちは主張します。モニタリングシステムが、世界が*どうあるべきか*、どの監視対象サービスインスタンスが*存在するべきか*を知らなければ、インスタンスが報告しない、障害でダウンしている、またはもはや存在すべきではない場合をどのように判断できるでしょうか?これは、個々のインスタンスの健全性に全く関心がない場合、例えば、十分な数のエフェメラルワーカーが結果を報告すれば十分な場合のみ許容されます。ほとんどの環境は、そのようなものだけで構成されているわけではありません。
モニタリングシステムが、どうしても世界の望ましい状態を知る必要がある場合、プッシュベースのアプローチは実際には*より多く*の設定を必要とします。モニタリングシステムがどのサービスインスタンスが存在すべきかを知るだけでなく、サービスインスタンスもモニタリングシステムに到達する方法を知る必要があります。プルアプローチは、設定が少なくなるだけでなく、モニタリング設定をより柔軟にします。プルを使用すると、ラップトップで本番環境のモニタリングのコピーを実行して実験できます。また、他のツールでメトリクスを取得したり、メトリクスエンドポイントを手動で検査したりすることもできます。高可用性を実現するために、プルを使用すると、同じ設定の2つのPrometheusサーバーを並列で実行できます。そして最後に、モニタリングが到達可能なエンドポイントを移動する必要がある場合、プルアプローチではすべてのメトリクスソースを再設定する必要はありません。
実用的な面では、Prometheusは、Consul、Marathon、Kubernetes、EC2、DNSベースのSD、Azure、Zookeeper Serversetsなど、クラウドプロバイダーやコンテナスケジューリングシステム向けの幅広いサービスディスカバリメカニズムの組み込みサポートにより、望ましい世界の状態の設定を容易にします。Prometheusは、必要に応じて独自のカスタムメカニズムをプラグインすることもできます。マイクロサービスの世界や、あらゆるマルチティアアーキテクチャにおいて、モニタリングシステムがサービスインスタンスがバックエンドを検出するために使用するのと同じ方法で、監視対象のターゲットを検出することは、根本的に利点となります。これにより、本番トラフィックを提供しているのと同じターゲットを監視していることを確認でき、維持すべきディスカバリメカニズムは1つだけになります。
誤ってモニタリングにDDoS攻撃を仕掛けてしまう
プルでもプッシュでも、時系列データベースは処理できない量のサンプルが送信されれば、ダウンしてしまいます。しかし、私たちの経験では、プッシュベースのアプローチで誤ってモニタリングをダウンさせてしまう可能性の方がわずかに高いです。どのインスタンスからどのメトリクスが取り込まれるかの制御が(モニタリングシステムで)中央化されていない場合、実験的なジョブや不正なジョブが突然大量のゴミデータを本番モニタリングにプッシュしてダウンさせてしまう危険性があります。プルベースのアプローチでも、これが発生する可能性は依然としてたくさんありますが(どこからメトリクスをプルするかは制御できますが、メトリクスペイロードのサイズや性質は制御できません)、リスクは低いです。さらに重要なのは、このようなインシデントは中央で軽減できるということです。
実証
Prometheusがすでに非常に大規模なセットアップの監視に使用されているという事実(DigitalOceanで*数百万台のマシンを監視するために使用*されているなど)に加えて、大規模な環境でプルベースのモニタリングが成功裏に使用されている他の著名な例があります。PrometheusはGoogleのBorgmonに触発されました。BorgmonはGoogle内で(そして部分的には現在も)プルベースのアプローチを使用して、すべての重要な本番サービスを監視するために使用されていました。GoogleでBorgmonに関して遭遇したスケーリングの問題は、プルアプローチによるものではありませんでした。プルベースのアプローチが、多数のデータセンターと数百万台のマシンを持つグローバル環境にスケーリングできるのであれば、プルはスケーリングしないとはほとんど言えないでしょう。
しかし、プルには他の問題があるのでは?
プルベースのアプローチで監視するのが難しいセットアップは確かに存在します。著名な例は、ファイアウォールや複雑なネットワーク設定のために直接到達できない、世界中に分散した多数のエンドポイントがあり、各ネットワークセグメントにPrometheusサーバーを直接実行することが現実的ではない場合です。これはPrometheusが構築された環境ではありませんが、回避策が可能な場合が多いです(*Pushgatewayまたはセットアップの再編成を通じて*)。いずれにせよ、プルベースのモニタリングに関するこれらの残りの懸念は、通常スケーリングに関連するものではなく、TCP接続を開くことに関するネットワーク運用上の困難によるものです。
これで全て解決?
この記事では、プルベースのモニタリングアプローチに関する最も一般的なスケーラビリティの懸念に対処しました。Prometheusやその他のプルベースのシステムが非常に大規模な環境で成功裏に使用されており、プルという側面が実際にはボトルネックとならないことを考えると、結果は明らかです。「プルはスケーリングしない」という議論は、実際には懸念事項ではありません。今後の議論が、このミスリードよりも重要な側面に焦点を当てることを願っています。