Amazon MSKでブローカーノードへの接続時にパブリックアクセスを構成出来るようになりました

2021.11.23

いわさです。

Amazon MSKではVPC内にクラスターが作成され、従来はVPC内からのみアクセスが可能でした。
本日のアップデートでパブリックアクセスを選択してインターネット経由でアクセス出来るようになりました。

本日はmacOSからインターネット経由でアクセスしてみましたので、こちらのセットアップ方法など含めて試してみましたのでご紹介したいとおもいます。
ちなみに、FAQの更新がまだですが、こちらも近日更新されるとおもいます。

よくある質問 - Amazon MSK | AWS

Q: パブリックインターネット経由でクラスターに接続することは可能ですか?

Amazon MSK は、パブリックエンドポイントをサポートしていません。ただし、クライアントと Amazon VPC の間にバーチャルプライベートネットワーク (VPN) 接続を使用して、Amazon MSK クラスターに接続することは可能です

パブリックアクセスを有効化

クラスター作成時は有効化できない

まず、パブリックアクセスの設定ですが、初期状態でパブリックアクセスを有効化した状態でクラスター作成は出来ません。
クラスター構成時も以下のようにオフから変更出来ない状態です。

パブリックアクセスオフの状態でクラスターを作成後、パブリックアクセスの有効化を行う必要があります。

前提条件としてセキュアな設定が必要

ただし、パブリックアクセスの前提条件を満たした設定の既存クラスターのみ有効化が可能です。
条件としてはインターネット経由でもセキュアな状態を確保するために以下の設定が必要となります。

  • クラスターバージョンがApache Kafka 2.6.0以降である
  • 認証されていないアクセス制御オフ、かつSASL/IAM、SASL/SCRAM、mTLSのアクセス制御方法のどれか1つ以上を選択
  • クラスター内の暗号化をオンにする(デフォルトオンだがオフで作成したクラスターをオンに変更することは出来ないため注意)
  • プレーンテキストトラフィックはオフ
  • SASL/IAM以外の場合は、Apache Kafka ACLが必要(allow.everyone.if.no.acl.foundがtrueだと設定出来ない)

また、パブリックIPアドレスを関連付けする関係でRDSのパブリックアクセスのように、インターネットゲートウェイが紐付いたパブリックサブネットに存在している必要があります。

クライアントの設定

今回は自宅からmacOSでKafkaクライアントを構成してプロデューサー、コンシューマーそれぞれで接続してみたいとおもいます。
後述しますが、ZooKeeperノードへのアクセスのみVPC内のEC2インスタンスを使っています。

公式ドキュメントがVPC内インスタンスから接続する方法だったので設定周りは少し苦労しました。

クライアント設定

公式ドキュメントには記述はありませんが、今回はmacOSなのでHomebrewを使ってインストールしてみます。

iwasa.takahito@hoge ~ % brew install kafka

...

==> Caveats
==> kafka
To restart kafka after an upgrade:
  brew services restart kafka
Or, if you don't want/need a background service you can just run:
  /usr/local/opt/kafka/bin/kafka-server-start /usr/local/etc/kafka/server.properties

VPC外からアクセスするのでセキュリティグループでマイIPを許可しました。
認証方法ごとのポートは以下を参考にしてください。

クライアントからIAM認証を出来るようにする

公式ドキュメントのIAM認証のページで以下のライブラリが案内されています。
こちらを使って、kafkaクライアントからIAM認証出来るように構成したいとおもいます。

ソースコードをダウンロード、ビルドし、パスを通しておきます。

iwasa.takahito@hoge aws-msk-iam-auth-main % export JAVA_HOME=/Library/Java/JavaVirtualMachines/amazon-corretto-11.jdk/Contents/Home
iwasa.takahito@hoge aws-msk-iam-auth-main % gradle clean shadowJar
Starting a Gradle Daemon (subsequent builds will be faster)

...

BUILD SUCCESSFUL in 30s
6 actionable tasks: 5 executed, 1 up-to-date
iwasa.takahito@hoge aws-msk-iam-auth-main % export CLASSPATH=~/Downloads/aws-msk-iam-auth-main/build/libs/aws-msk-iam-auth-1.1.2-PRE-all.jar

接続時に使うプロパティファイルを構成します。
こちらにIAM認証の設定を行い、AWS CLIで構成済みのプロファイルを指定しました。

iwasa.takahito@hoge config % cat client.properties 
# Sets up TLS for encryption and SASL for authN.
security.protocol = SASL_SSL

# Identifies the SASL mechanism to use.
sasl.mechanism = AWS_MSK_IAM

# Binds SASL client implementation.
sasl.jaas.config = software.amazon.msk.auth.iam.IAMLoginModule required awsProfileName="hoge";

# Encapsulates constructing a SigV4 signature based on extracted credentials.
# The SASL client bound by "sasl.jaas.config" invokes this class.
sasl.client.callback.handler.class = software.amazon.msk.auth.iam.IAMClientCallbackHandler

接続してみる

接続時にBootstrapBroker情報が必要なのでaws kafka get-bootstrap-brokersで取得することになるのですが、最新版のAWS CLIでない場合はパブリック用の文字列が取得出来ないのでご注意ください。

iwasa.takahito@hoge config % aws --version
aws-cli/2.3.5 Python/3.8.8 Darwin/20.6.0 exe/x86_64 prompt/off
iwasa.takahito@hoge config % aws kafka get-bootstrap-brokers --region ap-northeast-1 --cluster-arn arn:aws:kafka:ap-northeast-1:123456789012:cluster/hoge-cluster/7954b85a-e8f3-4ecd-b2ff-79262868bfc5-3 --profile hoge
{
    "BootstrapBrokerStringSaslIam": "b-2.hoge-cluster.vifp72.c3.kafka.ap-northeast-1.amazonaws.com:9098,b-1.hoge-cluster.vifp72.c3.kafka.ap-northeast-1.amazonaws.com:9098"
}

iwasa.takahito@hoge config % curl "https://awscli.amazonaws.com/AWSCLIV2.pkg" -o "AWSCLIV2.pkg"
sudo installer -pkg AWSCLIV2.pkg -target /
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 25.8M  100 25.8M    0     0  14.2M      0  0:00:01  0:00:01 --:--:-- 14.2M
installer: Package name is AWS Command Line Interface
installer: Upgrading at base path /
installer: The upgrade was successful.

iwasa.takahito@hoge config % aws --version                                                     
aws-cli/2.4.0 Python/3.8.8 Darwin/20.6.0 exe/x86_64 prompt/off
iwasa.takahito@hoge config % aws kafka get-bootstrap-brokers --region ap-northeast-1 --cluster-arn arn:aws:kafka:ap-northeast-1:123456789012:cluster/hoge-cluster/7954b85a-e8f3-4ecd-b2ff-79262868bfc5-3 --profile hoge
{
    "BootstrapBrokerStringSaslIam": "b-1.hoge-cluster.vifp72.c3.kafka.ap-northeast-1.amazonaws.com:9098,b-2.hoge-cluster.vifp72.c3.kafka.ap-northeast-1.amazonaws.com:9098",
    "BootstrapBrokerStringPublicSaslIam": "b-1-public.hoge-cluster.vifp72.c3.kafka.ap-northeast-1.amazonaws.com:9198,b-2-public.hoge-cluster.vifp72.c3.kafka.ap-northeast-1.amazonaws.com:9198"
}

パラメータではBootstrapBrokerStringPublicSaslIamを使う必要があります。
名前解決するとわかりますが、BootstrapBrokerStringSaslIamはプライベートIPアドレス、BootstrapBrokerStringPublicSaslIamはパブリックIPアドレスを指しています。それだけです。

プロデューサーからの接続確認

まずは、プロデューサーからメッセージをいくつか送ってみましょう。

iwasa.takahito@hoge aws-msk-iam-auth-main % kafka-console-producer --broker-list b-1-public.hoge-cluster.vifp72.c3.kafka.ap-northeast-1.amazonaws.com:9198,b-2-public.hoge-cluster.vifp72.c3.kafka.ap-northeast-1.amazonaws.com:9198 --producer.config client.properties --topic AWSKafkaTutorialTopic
>aaa
>bbb
>ccc
>ddd
>eee

コンシューマーからの接続確認

次にコンシューマーで受信してみます。

iwasa.takahito@hoge aws-msk-iam-auth-main % kafka-console-consumer --bootstrap-server b-1-public.hoge-cluster.vifp72.c3.kafka.ap-northeast-1.amazonaws.com:9198,b-2-public.hoge-cluster.vifp72.c3.kafka.ap-northeast-1.amazonaws.com:9198 --consumer.config client.properties --topic AWSKafkaTutorialTopic --from-beginning
aaa
bbb
ccc
ddd
eee

確認出来ましたね。

ZooKeeperノードはパブリックアクセス出来ないのか?

For security reasons, Amazon MSK doesn't allow public access to Apache ZooKeeper nodes.

とあるように、セキュリティ的な理由からパブリックアクセスは引き続き不可です。
ですので今回の検証範囲でいうと、トピック作成に関してははプライベートネットワークを介して実施させて頂きました。

まとめ

本日はAmazon MSKクラスターへインターネット経由でアクセスしてみました。
開発中などインターネット経路でローカルから確認を行いたい時などにパブリックアクセスが使えると MSK Connect設定せずに使えるので便利そうだなとおもいました。

MSKの情報が他のサービスよりも少なくて、クライアントからIAM認証で接続するあたりで少し苦労しました。
今まではVPC前提ということもあって、検証程度であればEC2のインスタンスプロファイルでどうにかなっていたのかとおもいます。
オンプレKafkaからの移行だとmTLSかSASL/SCRAMが多そうですが、こっちだと逆にACLの設定が必要なのでどちらか悩んでIAM認証にしました。
インスタンスプロファイル以外でのIAM認証がうまくいかないという方の参考にもなれば嬉しいです。