Amazon MSK Serverlessにパブリックアクセスしてみた #reinvent

2021.12.06

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

いわさです。

re:Invent 2021にてAmazon MSK Serverlessがパブリックプレビューで登場しました。

MSKサーバーレスはクラスター構築時にVPCを関連付けする必要があり、VPC内からのみのアクセスが可能です。
そして、現時点でサーバーレスクラスターにはパブリックアクセス機能は提供されておりません。

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

MSKサーバーレスの紹介記事の中で以下のように少しパブリックアクセスの可能性について言及させてもらっていました。

もしかしたらNLBだと出来るかもしれない。今度試してみます。

気になってたので、本日はこちらを試してみました。

MSK Serverlessは本日時点でパブリックプレビューです。今後のアップデートで本検証と異なる結果になる可能性があります。

MSKサーバーレスクラスターとNetwork Load Balancerを作成

まずはMSKサーバーレスクラスターを作成します。

VPC内のインスタンスから名前解決してみると、VPCエンドポイントへのCNAMEが使われていました。

sh-4.2$ nslookup boot-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com
Server:         172.31.0.2
Address:        172.31.0.2#53

Non-authoritative answer:
boot-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com       canonical name = vpce-02e94f6fa85a517a4-g6c6fs45.vpce-svc-05e4c72627dde0f5b.us-east-2.vpce.amazonaws.com.
Name:   vpce-02e94f6fa85a517a4-g6c6fs45.vpce-svc-05e4c72627dde0f5b.us-east-2.vpce.amazonaws.com
Address: 172.31.18.113
Name:   vpce-02e94f6fa85a517a4-g6c6fs45.vpce-svc-05e4c72627dde0f5b.us-east-2.vpce.amazonaws.com
Address: 172.31.8.19
Name:   vpce-02e94f6fa85a517a4-g6c6fs45.vpce-svc-05e4c72627dde0f5b.us-east-2.vpce.amazonaws.com
Address: 172.31.46.215

ネットワークインターフェイス(ENI)を見てみましょう。

NLBでTCP9098をルーティングしてやると動きそうな気もしますね。
では、作成されたENIに向けてパブリックアクセス出来るネットワークロードバランサーを作成します。

接続元(MSKクライアント)からアクセス出来るようにセキュリティグループ許可を設定しておきます。

接続してみる

MSKサーバーレスクラスターはIAM認証のみ許可されています。
クライアント環境は前回macOS上でHomebrewを使ってセットアップした環境がIAM認証でパブリックアクセスする設定になっているのでこれをそのまま使ってみます。

マネジメントコンソール上のブートストラップサーバーはboot-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com:9098となっていましたが、これをこのまま使うと名前解決が出来ません。
なので、ホスト部分をネットワークロードバランサーに変更(nlb-external-d45dfa4f0ff6ee7f.elb.us-east-2.amazonaws.com:9098)して、これをブートストラップサーバーとして指定して接続してみましょう。

[2021-12-06 07:25:19,660] WARN [AdminClient clientId=adminclient-1] Metadata update failed due to authentication error (org.apache.kafka.clients.admin.internals.AdminMetadataManager)
org.apache.kafka.common.errors.SslAuthenticationException: SSL handshake failed
Caused by: javax.net.ssl.SSLHandshakeException: No subject alternative DNS name matching nlb-external-d45dfa4f0ff6ee7f.elb.us-east-2.amazonaws.com found.

SSLでの通信に失敗しました。
ドメイン名をどうにかすればいける可能性がありますが、一旦SSLを無効化して試してみましょう。

クライアント構成ファイルでSASL_SSLを指定しています。
IAM認証は回避できない気がするのでSASLのみを設定(SASL_PLAINTEXT)してみましょう。

# security.protocol = SASL_SSL
security.protocol = SASL_PLAINTEXT
sasl.mechanism = AWS_MSK_IAM
sasl.jaas.config = software.amazon.msk.auth.iam.IAMLoginModule required awsProfileName="hoge";
sasl.client.callback.handler.class = software.amazon.msk.auth.iam.IAMClientCallbackHandler
iwasa.takahito@hoge ~ % export BS=nlb-external-d45dfa4f0ff6ee7f.elb.us-east-2.amazonaws.com:9098                                                                         
iwasa.takahito@hoge ~ % kafka-topics --bootstrap-server $BS --command-config client.properties --create --topic hoge-msk-serverless --partitions 6 --replication-factor 1
Error while executing topic command : The AdminClient thread has exited. Call: createTopics
[2021-12-06 09:13:09,128] ERROR org.apache.kafka.common.errors.TimeoutException: The AdminClient thread has exited. Call: createTopics
 (kafka.admin.TopicCommand$)
[2021-12-06 09:13:09,130] ERROR Uncaught exception in thread 'kafka-admin-client-thread | adminclient-1': (org.apache.kafka.common.utils.KafkaThread)

やはり接続できないですね。
今回はSSL接続を行うために、hostsファイルを使ってローカルで名前解決してMSKクライアントを使ってみたいと思います。

NLBのパブリックIPアドレスをhostsファイルに設定します。

iwasa.takahito@hoge ~ % cat /etc/hosts                                                                                                                               
127.0.0.1    localhost
255.255.255.255    broadcasthost

...

3.22.72.13 boot-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com
iwasa.takahito@hoge ~ % export BS=boot-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com:9098                                                                         
iwasa.takahito@hoge ~ % kafka-topics --bootstrap-server $BS --command-config client.properties --create --topic hoge-msk-serverless --partitions 6 --replication-factor 1
[2021-12-06 09:22:55,669] WARN [AdminClient clientId=adminclient-1] Error connecting to node b97-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com:9098 (id: 97 rack: null) (org.apache.kafka.clients.NetworkClient)
java.net.UnknownHostException: b97-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com: nodename nor servname provided, or not known

...

[2021-12-06 09:22:55,753] WARN [AdminClient clientId=adminclient-1] Error connecting to node b481-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com:9098 (id: 481 rack: null) (org.apache.kafka.clients.NetworkClient)
java.net.UnknownHostException: b481-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com: nodename nor servname provided, or not known

...

[2021-12-06 09:22:55,754] WARN [AdminClient clientId=adminclient-1] Error connecting to node b97-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com:9098 (id: 97 rack: null) (org.apache.kafka.clients.NetworkClient)
java.net.UnknownHostException: b97-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com

...

[2021-12-06 09:22:55,835] WARN [AdminClient clientId=adminclient-1] Error connecting to node b465-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com:9098 (id: 465 rack: null) (org.apache.kafka.clients.NetworkClient)
java.net.UnknownHostException: b465-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com: nodename nor servname provided, or not known

...

先程とまた違うエラーメッセージが大量に表示されましたね。
ブートストラップサーバーからブローカーノードの一覧を受け取って、各ノードへアクセスするのですが、各ブローカーサーバーの名前解決が出来ていません。

わかる範囲でhostsへ追加してみます。

3.22.72.13 boot-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com
3.22.72.13 b97-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com
3.22.72.13 b265-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com
3.22.72.13 b481-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com
3.22.72.13 b225-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com
iwasa.takahito@hoge ~ % kafka-topics --bootstrap-server $BS --command-config client.properties --create --topic hoge-msk-serverless --partitions 6 --replication-factor 1
Created topic hoge-msk-serverless.

おぉ、VPC外からトピックの作成に成功しました!!

その後、プロデューサー、コンシューマーそれぞれから接続する際も同様にブローカーノードへ接続できない旨が大量に表示されるので、同じようにhostsに追加していきました。
大量に出るエラーメッセージのうち数件分だけ...

3.22.72.13 boot-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com
3.22.72.13 b97-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com
3.22.72.13 b265-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com
3.22.72.13 b481-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com
3.22.72.13 b225-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com

3.22.72.13 b65-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com
3.22.72.13 b81-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com
3.22.72.13 b465-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com
3.22.72.13 b73-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com
3.22.72.13 b377-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com
3.22.72.13 b337-otr5ye0h.c1.kafka-serverless.us-east-2.amazonaws.com

その結果、プロデューサーとコンシューマーもパブリックアクセスが出来ました。

iwasa.takahito@hoge ~ % kafka-console-producer --bootstrap-server $BS --producer.config client.properties --topic hoge-msk-serverless  
>111
>222
>333

...

iwasa.takahito@hoge ~ % kafka-console-consumer --bootstrap-server $BS --consumer.config client.properties --topic hoge-msk-serverless --from-beginning
111
222
333

まとめ

VPC外からパブリックアクセス自体は出来ました。
しかし全く実用的じゃないですね。

名前解決の問題もありますし、ブローカーノード情報や各IPアドレスも固定とみなして設定して終わりにはならない気がします。
どうにか接続は出来なくもないですが、おとなしくVPC内で利用するのが良さそう。というところでしょうか。