プル型はスケールしない?それともする?

2016年7月23日筆者: Julius Volz

特に根強く残る神話について語りましょう。監視システムとPrometheusのプルベースのメトリクス収集アプローチについて議論があるたびに、誰かが必ず「プルベースのアプローチは根本的にスケールしない」と口を挟みます。その理由は曖昧であるか、Prometheusとは根本的に異なるシステムにのみ当てはまります。実際、最大規模のプルベース監視に携わってきた経験から言えば、この主張は私たちの運用経験に反します。

Prometheusがプッシュではなくプルを選択する理由については、FAQエントリがすでにありますが、スケーリングの側面に特化してはいません。この主張をめぐる一般的な誤解を詳しく見て、それらがPrometheusに当てはまるかどうか、どのように当てはまるかを分析しましょう。

PrometheusはNagiosではない

人々が能動的にプルする監視システムと聞くと、Nagiosを思い浮かべることがよくあります。Nagiosは、特定のホストやサービスの健全性を判断するために、Nagiosホスト上で任意の処理を実行できるアクティブチェック用のサブプロセスを生成するため、スケーリングがうまくいかないという評判があります。この種のチェックアーキテクチャは、中央のNagiosホストがすぐに過負荷になるため、確かにスケールしません。その結果、人々は通常、チェックを数分ごとにしか実行しないように設定するか、より深刻な問題に直面することになります。

しかし、Prometheusは根本的に異なるアプローチをとっています。Prometheusはチェックスクリプトを実行する代わりに、計測されたターゲットのセットからネットワーク経由で時系列データを収集するだけです。各ターゲットについて、Prometheusサーバーは、そのターゲットのすべてのメトリクスの現在の状態をHTTP経由で(ゴルーチンを使用して高度に並列に)フェッチするだけで、プル関連の他の実行オーバーヘッドはありません。これにより、次のポイントに進みます。

接続を開始するのが誰かは問題ではない

スケーリングの目的では、メトリクスが転送されるTCP接続を誰が開始するかは問題ではありません。どちらの方法で行っても、接続確立の労力は、メトリクスのペイロードやその他の必要な作業と比較して小さいです。

しかし、プッシュベースのアプローチはUDPを使用し、接続確立を完全に回避できる、とあなたは言うでしょう!確かにその通りですが、PrometheusにおけるTCP/HTTPのオーバーヘッドは、Prometheusサーバーがデータを取り込むために行う他の作業(特にディスクへの時系列データの永続化)と比較して、依然として無視できるほど小さいです。これを数字で示すと、単一の大きなPrometheusサーバーは、SoundCloudの実際の運用メトリクスデータで測定された、毎秒800,000の受信サンプルという記録を持ちながら、数百万の時系列データを容易に保存できます。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や他のプルベースのシステムが非常に大規模な環境で成功裏に使用されており、プルという側面が実際にはボトルネックになっていないことから、結果は明らかであるべきです。「プル型はスケールしない」という議論は、実際の懸念ではありません。将来の議論が、この見当違いな議論よりも重要な側面に焦点を当てることを願っています。