Apache Kafkaは、多くのクラウドアーキテクチャーを構成する要素として使われています。パフォーマンスが高く、信頼性と耐久性が保証されているため、大容量のデータをある場所から別の場所へ移動する際に多用されています。クラウド上で大量のデータを処理することにより、クラウドプロバイダーからの請求が高額になることは十分にあり得ます。Apache Kafkaには、クラスタレベルでもクライアントレベルでも、コストを削減するための多くの設定オプションが用意されていますが、適切な値や最適な方法を見つけるのは至難の業です。New RelicはApache Kafkaのヘビーユーザーであり、以前にも大規模なApache Kafka向けの20のベストプラクティスなどのブログを公開しています。この記事では、モニタリングを使用してさらに知見を広げ、Apache Kafkaをチューニングしてクラウドコストを削減する方法をご紹介します。

測定なしの改善はあり得ない

コストを最適化する第一歩は、コストを理解することです。Apache Kafkaのデプロイ方法や使用するクラウドプロバイダーによって、コストデータが変わってきます。例として、Confluent Cloudを使ってみましょう。Confluent Cloudは、主要なクラウドプロバイダーで利用できるマネージドサービスです。課金APIを使用して、1日ごとのコストを集計します。APIは優れた最初の一歩ですが、そのデータをNew Relicにインポートすると、時間の経過に伴う進化を把握し、適切なアラートと通知を備えたアプライドインテリジェンス(AI)による異常検知を行うことも可能になります。予想外のクラウドコストを望む人は誰もいません。

New Relicにデータを送信する一般的な方法は、New Relic Flexです。アプリケーションに依存しないオールインワンのツールで、さまざまなサービスからメトリクスのデータを収集でき、New Relicインフラストラクチャエージェントにバンドルされています。New Relic Flexは24時間ごとにConfluentの課金APIをスクレイピングし、設定を含むYAMLファイルを使用して、データをNew Relicに送信することができます。その後、New Relicのすべての機能を使用して、クラウド内のApache Kafkaのコストを調査することができます。

以下の画像は、New RelicのConfluentCloudのダッシュボードを示しています。

他のプロバイダーを使っている場合、プロセスは似ていますが、APIが異なります。クラウドでセルフマネージドKafkaを使っている場合、Kafkaのコストを他のサービスと区別するために、適切なインテグレーションとリソースのタグ付けが必要になる場合があります。いずれにせよ、異なるアプローチの間には多くの類似点がありますが、これらすべてに最適化のほとんどを適用できます。Apache Kafkaのコストは以下のカテゴリーに分類されます。

  • ネットワーキング:ブローカー間、またはブローカーとクライアント間のトラフィック量
  • ストレージ:動作に必要なディスクのサイズ、I/Oスループット、量
  • サーバーのハードウェア:CPU/RAM、またはインスタンスの数や種類などの高レベルの表現

クラウドでのネットワーク:影響は大きいが、見逃されがちである

クラウドで運用する場合、Kafkaではネットワークがボトルネックになることはあまりないため、多くのエンジニアはボトルネックを最小限に抑えるためにサービスを最適化することはありません。コストに大きな影響が生じる恐れがあるためですが、それは間違いです。

最初のステップは、サービスがKafkaクラスタにどのように接続されているかを理解することです。New Relicはネットワークパフォーマンス監視を提供します。これは、Kafkaへの接続に必要なすべてのネットワークホップを特定するのに役立ちます。コンポーネントの中には、クラウドプロバイダーの請求に大きな影響を与えるものもあります。同じネットワーク内のサービスに接続する場合と、別のネットワーク(または地域)のサービスに接続する場合とでは、コストの差は大きくなります。Apache Kafkaの高スループット機能を考慮すると、これはサービス運用の最大のコストになる可能性があります。

高可用性を実現するために、Kafkaを複数の異なる可用性ゾーンで運用するのが一般的です。1つの可用性ゾーンで障害が発生しても、他の2つのゾーンにはデータのコピーを持つKafkaノード(ブローカー)が存在するため、サービスは中断することなく動作します。残念ながら、ある可用性ゾーンから別の可用性ゾーンへのトラフィックは高価になります。そこでクライアント側の最適化として、New RelicがKafkaのさまざまなフレーバーで大成功を収めている、最も近いレプリカからフェッチするという方法があります。

可能であれば、同じ可用性ゾーンにあるKafkaノードに接続するように、データを読み込むサービスを設定します。これにより、クロスAZトラフィックとそれに伴うコストが大幅に削減されます。データを送信するサービスやノード間の内部データ複製に関連するコストは残りますが、これにより大きく改善させることができます。当然ながら、それはトレードオフになります。データパイプラインのエンドツーエンドのレイテンシが増加するので、レイテンシがどのような影響を受けるかを測定することが重要です。New Relic Javaエージェントは、このような変更の影響を測定するための多くのKafkaメトリクスに加えて、Kafkaを使用したディストリビューティッド(分散)トレーシングをすでにサポートしています。

下の画像は、Javaエージェントを使ったKafkaのディストリビューティッド(分散)トレーシングを示しています。

Apache Kafkaにデータを送信するアプリケーションでは、大きな違いを生むもう一つの最適化に圧縮があります。Kafkaプロデューサーは、個別のメッセージではなく、バッチでデータをKafkaに送信します。送信前にこれらのバッチに圧縮を適用することができます。Apache Kafkaはそれらを圧縮して保存し、Kafkaから消費するアプリケーションはそれらを解凍してメッセージを処理します。これにより、ネットワーク上で送信されるトラフィック量が削減されるだけでなく、Kafkaノードで必要なストレージ量も削減されます。また、Kafkaを消費したりKafkaに生成したりするサービスのCPU使用率も上がりますが、たいていはバランスがうまく取れます。圧縮がパイプラインのレイテンシとスループットにどのような影響を与えるかを測定することが重要です。New Relic Javaエージェントは、圧縮の動作を理解するのに役立つ、いくつかのメトリクスを提供します。outgoing-byte-rateメトリクスはスループットの変化を示し、request-latency-avgメトリクスはレイテンシの変化を示します。Apache Kafkaはいくつかの圧縮アルゴリズムをサポートしており、アプリケーションから送信されるデータの種類によって挙動が異なります。さまざまなアルゴリズムでテストして、あらゆるユースケースにどれが適しているかを見極めるのは興味深いことです。compression-rate-avgメトリクスは、圧縮がどの程度うまく機能しているかを示しますが、圧縮がプロデューサーとコンシューマーのレイテンシ、スループット、CPU使用率にどのような影響を与えるかを理解することも重要です。

ストレージ:最小限の変更でトラフィックを増やす簡単な方法

Apache Kafkaのキャパシティプランニングは容易ではありません。いろいろな要素が絡んでいます。そのうちの1つが、ディスクI/Oとも呼ばれるストレージのスループットです。高スループットのパイプラインでは、ストレージのスループットがボトルネックになりやすくなります。ブローカーを増やすことでこの問題は軽減されますが、同時にコストも増加します。幸いなことに、クラウドでは通常、より高速なディスクを簡単かつ安価に使用できます。

Kafkaを自分で管理している場合、インフラストラクチャエージェントは、Kafkaがどの程度ディスクの限界に近づいているかを把握するためのメトリクスを提供します。マネージドサービスを利用している場合、通常いくつかのメトリクスが提供されます。例えば、もう1つ人気のあるKafkaサービスの、Amazon Managed Streaming for Apache Kafka(Amazon MSK)を使ってみましょう。New Relicでは、AWS CloudWatchメトリクス・ストリームインテグレーションを使用して、Amazon MSKインテグレーションを利用できます。

Amazon MSKは、VolumeQueueLengthVolumeTotalWriteTimeVolumeWriteOpsVolumeWriteBytes、およびReadに相当するようなメトリクスを提供し、ディスクがどの程度飽和しているかを示します。そのような場合、Amazon MSKを使えば、クラスタを再作成したり、現在のトラフィックに影響を与えたりすることなく、プロビジョニングされたストレージのスループットを簡単に増やすことができます。この変更により、信頼性が向上し、復旧時間が短縮し、ブローカーを増設する必要がなくなり、パイプラインの総コストを削減することができます。同じ原則が自己管理クラスタにも当てはまります。

New Relic を活用したこの方法は、最適化の観点で非常に効果的です。ディスクI/Oを増やすと、クラスタあたり20%多いトラフィックを処理できるようになったため、New Relicでは同数のKafkaクラスタを廃止することができました。ディスクI/Oの増加にかかるコストは、クラスタ全体を運用する総コストよりも大幅に低く、かなりの節約につながります。

サーバーハードウェアの性能

ネットワークとスループットの次にクラウドコストを最適化する項目は、Kafkaノード(ブローカー)の数です。ほとんどの場合、Kafkaを実行しているマシンのCPU使用率によって制限されます。CPU使用率を最適化する方法は多くあります。最適なマシンタイプを選択する、圧縮されたトピックの作成を最小限にする(サーバー側で追加の作業が必要)、レプリケーション係数を減らす(データのコピー数を減らす)などです。

興味深いことに、New Relicのクラウドコストに大きな影響を与える設定の1つは、クラスタの設定ではなく、クライアントにあります。Apache Kafkaクライアントは通常、個別のメッセージをサーバーに送信せず、バッチにまとめて送信します。これにより多少のレイテンシが生じますが、ネットワークレベルではより効率的です。また、圧縮は個別のメッセージよりもバッチで行う方がはるかに効果的です。

デフォルトでは、Apache Kafkaクライアントの設定は、バッチ処理には効率的ではありません。多くのバッチではメッセージ数が少なく、サイズも小さくなります。そのため、Kafkaにデータを送信するアプリケーションは、より多くのリクエストを送信できます。Kafkaブローカーが受信するリクエストが多ければ多いほど、その処理に必要なCPUが高くなります。

プロデューサーがNew Relic Javaエージェントを使用している場合、Kafkaクライアントメトリクス(batch-size-avgは)はバッチの平均サイズを示し、request-rateメトリクスは1秒あたりの平均リクエスト数を示します。より大きなバッチを送信するようにアプリケーションを設定することも可能です。例えば、New Relicでは、linger.msを100ミリ秒の値で使用することを社内で推奨しています。これにより、クラスタにバッチを送信するまで100ミリ秒待つことになり、結果としてバッチが大きくなり、ブローカーへのリクエストが少なくなります。New Relicのたった1つのアプリケーションでのこの変更により、クラスタのCPU使用率が15%減少しました。これにより、クラウドコストを大幅に削減しながら、ブローカーの数を減らしてクラスタをスケールダウンできます。

Javaエージェントバージョン8.1.0以降でのKafkaメトリクスウィジェット

Kafkaのショーバック

Apache Kafkaは、パフォーマンスの面で優れたソフトウェアです。それを実現する方法の1つは、使用するアプリケーションにより多くの責任を与えることです。これは非常にうまく機能しますが、キャパシティプランニングやガバナンスも難しくなります。バッチの大きさに関する前述のケースが良い例です。ユーザーに正しいことを強制し、クラスタでのCPU使用率が最適になるようにアプリケーションを調整する簡単な方法はありません。

規模が大きくなれば、これは簡単に回避できるクラウドコストにつながる可能性があります。この問題を解決する興味深いアプローチは、ショーバックやチャージバックを使うことです。最初のステップは、次の3つの異なるレベルで適切なモニタリングを行うことです。

モニタリングを実施したら、Kafkaを使用する各チームに各コンポーネント(ネットワーク、ストレージ、サーバー・ハードウェア)のコストを割り当てる方法です。これは実装例です。

  • ネットワークのコスト:Kafkaへの消費/生産スループットに基づいてチームに割り当てられます
  • ストレージのコスト:保持設定とクライアントのスループットに基づいてチームに割り当てられます。未使用のストレージは、トラフィックの急増に対処するために必要です。未使用のストレージの量は、クラスタを所有するチームによって定義されます。適切なサイズを確保するために、そのチームに割り当てる必要があります
  • サーバーのハードウェア(CPU):Kafkaブローカーへのリクエスト数に応じてチームに割り当てられます。未使用のCPUをチームに割り当てるべきではないため、キャパシティプランニングの問題を特定できます

このアプローチでは、グッドプラクティスを実施し、チームがKafkaリソースを効率的に使用していることを確認することが容易になります。チームはKafkaショーバックを定期的にレビューし、異常や潜在的な最適化を特定することができます。また、適切なアラートと通知変更追跡機能を備えたアプライドインテリジェンスによる異常検知を使用して、新しい開発がクラウドコストにどのような影響を与えるかを特定することもできます。

New Relicのデプロイメント変更追跡機能

まとめ

Apache Kafkaは、大量のデータを高速かつ信頼性の高い方法で転送するための優れた技術です。パフォーマンスを向上させ、クラウドのコストを削減するために、さまざまな設定が可能です。最適な方法を見極め、それが既存のサービスやパイプラインにどのような影響を与えるかを測定するのは難しい場合がありますが、Kafkaサーバーとクライアントに適切なモニタリングを追加することで、そのプロセスをスムーズに進めることができます。課金データ、Kafkaメトリクス、ユーザー間の相関関係を自動化することで、ショーバック/チャージバック戦略を構築し、クラウドコストの長期的な最適化を実現します。