Amazon Web Services ブログ

Amazon MSK の IAM アクセスコントロールと Kafka Quotas によるマルチテナント Apache Kafka クラスター – Part 1

本記事は 2023 年 6 月 19 日 に公開された「Multi-tenancy Apache Kafka clusters in Amazon MSK with IAM access control and Kafka Quotas – Part 1」を翻訳したものです。

Amazon Managed Streaming for Apache Kafka (Amazon MSK) では、Apache Kafka を使ったストリーミングデータ処理アプリケーションを構築・実行できます。ストリーミングデータの処理では、アプリケーションのグループ分けや利用シナリオ、コンプライアンス要件などに基づいて複数の Kafka クラスターを使い分ける場合と、組織全体で 1 つの Kafka クラスターを共有する場合があります。いずれの場合も、Kafka クラスターは一般的にマルチテナントであり、複数のプロデューサーとコンシューマーが同時にストリーミングデータを送受信します。

マルチテナント Kafka クラスターの課題の 1 つは、コンシューマーやプロデューサーがクラスターリソースを過剰に使用しないようにすることです。一部の不適切なアプリケーションがリソースを過剰に消費すると、他の正常なアプリケーションに影響が及びます。マルチテナント Kafka クラスターの管理チームには、アプリケーションによるリソースの過剰消費を防ぐ仕組みが必要です。Kafka Quotas はまさにこの目的で使用され、Kafka クラスター内でクライアントアプリケーションが使用できるリソース量を制御します。

この 2 部構成シリーズの Part 1 では、IAM アクセスコントロールで認証・認可を行いながら、MSK マルチテナント Kafka クラスターに Kafka Quotas を適用する方法を説明します。Part 2 では、サンプルの Kafka クライアントアプリケーションとともに詳細な実装手順を解説します。

Kafka Quotas の概要

Kafka Quotas は、Kafka クラスター内でクライアントアプリケーションが使用できるリソース量を制御します。1 つ以上のクライアントアプリケーションが大量のデータを送受信したり、長時間にわたって高いレートでリクエストを生成し続けたりすると、Kafka クラスターのリソースが独占され、パフォーマンス低下や完全な停止につながります。

アプリケーションによるクラスターの過負荷を防ぐため、Apache Kafka では各クライアントアプリケーションがブローカーごとに送受信できるトラフィック量を Quotas で設定できます。Kafka ブローカーは、割り当てられた Quotas に従ってクライアントのリクエストをスロットリングします。Kafka Quotas は、特定のユーザー、特定のクライアント ID、またはその両方に対して設定できます。クライアント ID は、アプリケーションコード内で定義される論理名で、Kafka ブローカーがメッセージの送信元アプリケーションを識別するために使います。ユーザーは、認証が有効なセキュアな Kafka クラスターにおけるクライアントアプリケーションの認証済みユーザープリンシパルです。

Kafka では 2 種類の Quotas がサポートされています。

  • ネットワーク帯域幅 Quotas – バイトレートのしきい値で、クライアントアプリケーションが Kafka クラスター内の各ブローカーに対して 1 秒あたりにプロデュースおよびコンシュームできるデータ量を定義します。
  • リクエストレート Quotas – 各ブローカーがクライアントアプリケーションのリクエスト処理に費やす時間の割合を制限します。

ビジネス要件に応じてどちらの Quotas も使用できますが、ネットワーク帯域幅 Quotas が一般的です。アプリケーションの 1 秒あたりの送受信データ量に応じてリソース消費を制限できるためです。

本記事では IAM アクセスコントロールを使用する MSK クラスターを対象としているため、アプリケーションのクライアント ID認証済みユーザープリンシパルに基づくネットワーク帯域幅 Quotas の設定について説明します。

Kafka Quotas の考慮事項

Kafka Quotas を使用する際の注意点は以下のとおりです。

  • 適用レベル – Quotas はクラスターレベルではなくブローカーレベルで適用されます。Kafka クラスターに 6 つのブローカーがあり、あるクライアント ID とユーザーに対して 12 MB/sec のプロデュース Quota を指定した場合、そのプロデューサーアプリケーションは各ブローカーで同時に最大 12 MB/sec をプロデュースでき、6 つのブローカー全体で合計最大 72 MB/sec となります。ただし、あるトピックの全パーティションのリーダーシップが 1 つのブローカーに集中している場合、同じプロデューサーアプリケーションは最大 12 MB/sec しかプロデュースできません。スロットリングはブローカーごとに行われるため、すべてのブローカー間でトピックのパーティションリーダーシップを均等に分散させることが重要です。
  • スロットリング – アプリケーションが Quota に達すると、エラーではなくスロットリングされます。つまり、ブローカーは例外をスローしません。ブローカーで Quota に達したクライアントは、Quota を超えないようリクエストがスロットリングされます。クライアントが Quota を超えた場合、ブローカーはエラーを返す代わりにクライアントの速度を落とします。ブローカーはクライアントを Quota 以下に抑えるために必要な遅延量を計算し、レスポンスを遅延させます。このアプローチにより、Quota 違反はクライアントに対して透過的で、クライアント側で特別なバックオフやリトライポリシーを実装する必要はありません。ただし、非同期プロデューサーで Quota を超えるレートでメッセージを送信している場合、メッセージはまずクライアントのメモリにキューイングされます。送信レートが受け入れレートを超え続けると、最終的にバッファ領域が不足し、次の Producer.send() 呼び出しがブロックされます。タイムアウトの遅延がブローカーの追いつきに十分でない場合、Producer.send()TimeoutException をスローします。
  • 共有 Quotas – 複数のクライアントアプリケーションが同じクライアント ID とユーザーを持つ場合、そのクライアント ID とユーザーに設定された Quota はすべてのアプリケーション間で共有されます。client-id="marketing-producer-client"user="marketing-app-user" の組み合わせに対して 5 MB/sec のプロデュース Quota を設定した場合、クライアント IDmarketing-producer-client で認証済みユーザープリンシパルが marketing-app-user であるすべてのプロデューサーアプリケーションが 5 MB/sec のプロデュース Quota を共有し、互いのスループットに影響を与えます。
  • プロデューススロットリング – プロデュースのスロットリング動作は、produce-throttle-time-avgproduce-throttle-time-max などのクライアントメトリクスで確認できます。これらがゼロ以外の場合、送信先のブローカーがプロデューサーの速度を落としていることを示しており、Quotas 設定を見直す必要があります。
  • コンシュームスロットリング – コンシュームのスロットリング動作は、fetch-throttle-time-avgfetch-throttle-time-max などのクライアントメトリクスで確認できます。これらがゼロ以外の場合、送信元のブローカーがコンシューマーの速度を落としていることを示しており、Quotas 設定を見直す必要があります。

クライアントメトリクスは、Kafka クラスターに接続するクライアントが公開するメトリクスです。

  • Quota の設定方法 – Kafka Quotas は、Kafka 設定ファイルによる静的な設定と、kafka-config.sh や Kafka Admin API による動的な設定のどちらでも設定できます。動的な設定の仕組みでは、ブローカーを再起動せずにいつでも新しいプロデューサーやコンシューマーの Quotas を設定できるため、はるかに便利で管理しやすくなっています。アプリケーションがデータを送受信している最中でも、動的な設定変更はリアルタイムで反映されます。
  • 設定キーkafka-config.sh コマンドラインツールでは、consumer_byte_rateproducer_byte_raterequest_percentage の 3 つの設定キーを使用して、コンシューム、プロデュース、リクエストの Quotas をそれぞれ動的に設定できます。

Kafka Quotas の詳細については、Kafka のドキュメントを参照してください。

IAM アクセスコントロールによるネットワーク帯域幅 Quotas の適用

Kafka Quotas の理解を踏まえ、IAM アクセスコントロールで認証・認可を行いながら MSK クラスターに Quotas を適用する方法を見ていきましょう。Amazon MSK の IAM アクセスコントロールにより、認証と認可を別々に用意する必要がなくなります。

次の図は、デモアカウントで IAM アクセスコントロールを使用するよう設定された MSK クラスターを示しています。各プロデューサーおよびコンシューマーアプリケーションには、1 秒あたりに送受信できるデータ量を決定する Quota が設定されています。たとえば、ProducerApp-1 のプロデュース Quota は 1024 bytes/secConsumerApp-1ConsumerApp-2 のコンシューム Quota はそれぞれ 51201024 bytes/sec です。Kafka Quotas はクライアントアプリケーション側ではなく、Kafka クラスター側で設定する点に注意してください。

上の図は、Kafka クライアントアプリケーション (ProducerApp-1ConsumerApp-1ConsumerApp-2) が書き込みおよび読み取り用の IAM ロールを引き受けて MSK クラスター内の Topic-B にアクセスする流れを示しています。ワークフローは以下のとおりです。

  • P1ProducerApp-1 は (ProducerApp-1-Role IAM ロールを通じて) Topic-B-Write-Role IAM ロールを引き受け、MSK クラスター内の Topic-B にメッセージを送信します。
  • P2Topic-B-Write-Role IAM ロールを引き受けた状態で、ProducerApp-1Topic-B へのメッセージ送信を開始します。
  • C1ConsumerApp-1 (ConsumerApp-1-Role IAM ロールを通じて) と ConsumerApp-2 (ConsumerApp-2-Role IAM ロールを通じて) は Topic-B-Read-Role IAM ロールを引き受け、MSK クラスター内の Topic-B からメッセージを読み取ります。
  • C2Topic-B-Read-Role IAM ロールを引き受けた状態で、ConsumerApp-1ConsumerApp-2Topic-B からのメッセージ消費を開始します。

ConsumerApp-1ConsumerApp-2 は別々のコンシューマーアプリケーションです。同じコンシューマーグループには属していません。

クライアント ID の設定と認証済みユーザープリンシパルの理解

前述のとおり、Kafka Quotas は特定のユーザー、特定のクライアント ID、またはその両方に対して設定できます。Kafka Quota の割り当てに必要なクライアント IDユーザーの概念と設定を見ていきましょう。

クライアント ID

アプリケーションの論理名を表すクライアント ID は、アプリケーションのコード内で設定できます。Java アプリケーションでは、ProducerConfig.CLIENT_ID_CONFIGConsumerConfig.CLIENT_ID_CONFIG でプロデューサーとコンシューマーのクライアント ID をそれぞれ設定できます。次のコードスニペットは、ProducerApp-1ProducerConfig.CLIENT_ID_CONFIG でクライアント ID を this-is-me-producerapp-1 に設定する例です。

Properties props = new Properties();
props.put(ProducerConfig.CLIENT_ID_CONFIG,"this-is-me-producerapp-1");

ユーザー

ユーザーとは、認証が有効な Kafka クラスターにおけるクライアントアプリケーションの認証済みユーザープリンシパルです。ソリューションアーキテクチャで示したように、プロデューサーおよびコンシューマーアプリケーションは Topic-B-Write-RoleTopic-B-Read-Role IAM ロールをそれぞれ引き受けて Topic-B の書き込みおよび読み取り操作を行います。認証済みユーザープリンシパルは次のような IAM 識別子になります。

arn:aws:sts::<AWS Account Id>:assumed-role/<assumed Role Name>/<role session name>

詳細については、IAM 識別子を参照してください。

ロールセッション名は、IAM プリンシパル、フェデレーテッドアイデンティティ、またはアプリケーションが IAM ロールを引き受ける際にセッションを一意に識別する文字列識別子です。ここでは ProducerApp-1ConsumerApp-1ConsumerApp-2AWS Security Token Service (AWS STS) SDK を使用して IAM ロールを引き受け、呼び出し時にロールセッション名を指定します。たとえば、ProducerApp-1Topic-B-Write-Role IAM ロールを引き受け、ロールセッション名として this-is-producerapp-1-role-session を使用した場合、認証済みユーザープリンシパルは次のようになります。

arn:aws:sts::<AWS Account Id>:assumed-role/Topic-B-Write-Role/this-is-producerapp-1-role-session

次のコードスニペットは、ProducerApp-1 アプリケーションが AWS STS SDK を使用して Topic-B-Write-Role IAM ロールを引き受ける際に、ロールセッション名として this-is-producerapp-1-role-session を使用する例です。

StsClient stsClient = StsClient.builder().region(region).build();
AssumeRoleRequest roleRequest = AssumeRoleRequest.builder()
          .roleArn("<Topic-B-Write-Role ARN>")
          .roleSessionName("this-is-producerapp-1-role-session") //role-session-name string literal
          .build();

ネットワーク帯域幅 (プロデュースおよびコンシューム) Quotas の設定

以下のコマンドは、IAM アクセスコントロールが設定された MSK クラスターで、クライアントアプリケーションのクライアント ID と認証済みユーザープリンシパルに基づいてプロデュースおよびコンシューム Quotas を動的に設定します。

プロデュース Quota を設定するコマンドは次のとおりです。

kafka-configs.sh --bootstrap-server <MSK cluster bootstrap servers IAM endpoint> \
--command-config config_iam.properties \
--alter --add-config "producer_byte_rate=<number of bytes per second>" \
--entity-type clients --entity-name <ProducerApp client Id> \
--entity-type users --entity-name <ProducerApp user principal>

producer_byte_rate は、クライアント IDユーザーで識別されるプロデューサークライアントが 1 つのブローカーに対して 1 秒あたりにプロデュースできるメッセージ量 (バイト単位) です。--command-config オプションは、IAM アクセスコントロールに必要なプロパティを含む config_iam.properties を指定します。

コンシューム Quota を設定するコマンドは次のとおりです。

kafka-configs.sh --bootstrap-server <MSK cluster bootstrap servers IAM endpoint> \
--command-config config_iam.properties \
--alter --add-config "consumer_byte_rate=<number of bytes per second>" \
--entity-type clients --entity-name <ConsumerApp client Id> \
--entity-type users --entity-name <ConsumerApp user principal>

consumer_byte_rate は、クライアント IDユーザーで識別されるコンシューマークライアントが 1 つのブローカーから 1 秒あたりにコンシュームできるメッセージ量 (バイト単位) です。

ProducerApp-1ConsumerApp-1ConsumerApp-2 クライアントアプリケーションの Quota 設定コマンドの例を見てみましょう。

  • ProducerApp-1 のプロデュース Quota 設定ProducerApp-1 がアプリケーションコードでクライアント ID として this-is-me-producerapp-1 を設定し、Topic-B-Write-Role IAM ロールを引き受ける際のロールセッション名として this-is-producerapp-1-role-session を使用するとします。次のコマンドは、ProducerApp-1 のプロデュース Quota を 1024 bytes/sec に設定します。
kafka-configs.sh --bootstrap-server <MSK Cluster Bootstrap servers IAM endpoint> \
--command-config config_iam.properties \
--alter --add-config "producer_byte_rate=1024" \
--entity-type clients --entity-name this-is-me-producerapp-1 \
--entity-type users --entity-name arn:aws:sts::<AWS Account Id>:assumed-role/Topic-B-Write-Role/this-is-producerapp-1-role-session
  • ConsumerApp-1 のコンシューム Quota 設定ConsumerApp-1 がアプリケーションコードでクライアント ID として this-is-me-consumerapp-1 を設定し、Topic-B-Read-Role IAM ロールを引き受ける際のロールセッション名として this-is-consumerapp-1-role-session を使用するとします。次のコマンドは、ConsumerApp-1 のコンシューム Quota を 5120 bytes/sec に設定します。
kafka-configs.sh --bootstrap-server <MSK Cluster Bootstrap servers IAM endpoint> \
--command-config config_iam.properties \
--alter --add-config "consumer_byte_rate=5120" \
--entity-type clients --entity-name this-is-me-consumerapp-1 \
--entity-type users --entity-name arn:aws:sts::<AWS Account Id>:assumed-role/Topic-B-Read-Role/this-is-consumerapp-1-role-session

ConsumerApp-2 のコンシューム Quota 設定ConsumerApp-2 がアプリケーションコードでクライアント ID として this-is-me-consumerapp-2 を設定し、Topic-B-Read-Role IAM ロールを引き受ける際のロールセッション名として this-is-consumerapp-2-role-session を使用するとします。次のコマンドは、ConsumerApp-2 のコンシューム Quota をブローカーあたり 1024 bytes/sec に設定します。

kafka-configs.sh --bootstrap-server <MSK Cluster Bootstrap servers IAM endpoint> \
--command-config config_iam.properties \
--alter --add-config "consumer_byte_rate=1024" \
--entity-type clients --entity-name this-is-me-consumerapp-2 \
--entity-type users --entity-name arn:aws:sts::<AWS Account Id>:assumed-role/Topic-B-Read-Role/this-is-consumerapp-2-role-session

上記のコマンドにより、ProducerApp-1ConsumerApp-1ConsumerApp-2 クライアントアプリケーションは、割り当てられたプロデュースおよびコンシューム Quotas を超えた場合、IAM アクセスコントロールを使用する MSK クラスターによってスロットリングされます。

ソリューションの実装

このシリーズの Part 2 では、サンプルのプロデューサーおよびコンシューマークライアントアプリケーションとともに、IAM アクセスコントロールを使用した Kafka Quotas 設定の詳細な実装手順を紹介します。

まとめ

Kafka Quotas により、プロデューサーおよびコンシューマーアプリケーションに制限を設定できます。Amazon MSK では、Kafka Quotas は 2 つの重要な目的を果たします。設計が不十分なプロデューサーやコンシューマーの Quota を制限して問題を未然に防ぐこと、そして中央のストリーミングデータプラットフォームの運用コストを異なるコストセンターやテナント (アプリケーションチームやプロダクトチーム) に配分することです。

本記事では、IAM アクセスコントロールを使用しながら Amazon MSK でネットワーク帯域幅 Quotas を設定する方法を説明しました。また、Quotas 設定時にクライアント ID と認証済みプリンシパルがどのように使われるかを示すサンプルコマンドとコードスニペットも紹介しました。IAM アクセスコントロールを使用した Kafka Quotas のみを紹介しましたが、Amazon MSK がサポートする他の認証メカニズムでも Quotas を設定できます。

このシリーズの Part 2 では、Amazon MSK で IAM アクセスコントロールを使用したネットワーク帯域幅 Quotas の設定方法を実演し、実際に動作を確認できるサンプルのプロデューサーおよびコンシューマーアプリケーションを提供します。

詳細については、以下のリソースを参照してください。

著者について

Vikas Bajaj

Vikas Bajaj

Amazon Web Services の金融サービス担当シニアマネージャー、ソリューションアーキテクトです。金融サービス組織やデジタルネイティブ企業との経験を活かし、オーストラリアの金融サービスのお客様にテクノロジーの意思決定、アーキテクチャ、製品ロードマップについてアドバイスしています。


この記事は Kiro が翻訳を担当し、Solutions Architect の 榎本 貴之 がレビューしました。