mongodb+srv
最近、mongodbプロトコル接続用に HAProxy で SNI ベースのルーティングを設定しようとしました。
私はそれを動作させましたが、
tcp-request inspect-delay 5s
tcp-request content accept if { req_ssl_hello_type 1 }
フロントエンドの設定で正常に動作するようになった
これらがなければ(またはたった1つでこれらのうち、約 70% のリクエストで散発的に接続がリセットされ続けました。ただし、接続が確立されることもありました。
によるとhttp://cbonte.github.io/haproxy-dconv/2.0/configuration.html#4-tcp-request%20content
コンテンツベースのルールは、宣言された順序どおりに評価されます。一致するルールがない場合、またはルールがない場合、デフォルトのアクションはコンテンツを受け入れることです。挿入できるルールの数に特定の制限はありません。
したがって、デフォルトで動作するはずでした。
基本的な TCP 概念か、Mongo の特定の接続の詳細が欠けているのかもしれません。しかし、SNI ベースのルーティングを選択する場合、ほぼすべての人が同じルールを定義していることに気付きました。そのため、ほとんどの人にとっては意味があるはずです。
動作する HAProxy 構成:
frontend fe_mongo-nonprod
bind :27017
tcp-request inspect-delay 5s
tcp-request content accept if { req_ssl_hello_type 1 }
acl mongoAtlas-01 req_ssl_sni -i host1.mongodb.net
acl mongoAtlas-02 req_ssl_sni -i host2.mongodb.net
acl mongoAtlas-03 req_ssl_sni -i host3.mongodb.net
use_backend be_mongo-nonprod if mongoAtlas-01 || mongoAtlas-02 || mongoAtlas-03
backend be_mongo-nonprod
mode tcp
acl mongoAtlas-01 req_ssl_sni -i host1.mongodb.net
acl mongoAtlas-02 req_ssl_sni -i host2.mongodb.net
acl mongoAtlas-03 req_ssl_sni -i host3.mongodb.net
use-server server-01 if mongoAtlas-01
use-server server-02 if mongoAtlas-02
use-server server-03 if mongoAtlas-03
server server-01 host1.mongodb.net:27017
server server-02 host2.mongodb.net:27017
server server-03 host3.mongodb.net:27017
また、HAProxy は Kubernetes (GCP 内の Google 管理クラスタ) にデプロイされ、istio-sidecar を持ち、Internal LoadBalancer k8s サービスを介して公開されていることも言及する価値があります。
前述のとおり、上記の設定は完全に正常に動作します。私が興味を持っているのは、なぜtcp-request content accept
が絶対に必要なのか、そしてなぜここでは接続がデフォルトで [常に] 受け入れられないのかということです。
答え1
少し考えてから、自分自身の質問に答えてみようと思います。
したがって、HAProxy のドキュメントには次のような記述もあります。 http://cbonte.github.io/haproxy-dconv/2.0/configuration.html
コンテンツの切り替えが必要な場合は、以下の例のように、まず完全なクライアント ハロー (タイプ 1) を待機することをお勧めします。
さて、SNIデータはリクエストのClient Helloセクションにも含まれているので(https://www.rfc-editor.org/rfc/rfc6066#page-6) 私の仮定は次のとおりです。
Client Hello が複数の TCP パケットに分散していて、 がない場合tcp-request content accept is configured
、最初のパケットを受信すると、HAProxy はそれをルーティングしようとし、次の 2 つのいずれかが発生します。
- デフォルトのバックエンドが設定されている場合、パケットはこのバックエンドに転送されます。
- デフォルトのバックエンドが設定されていない場合 (私の場合)、パケットはドロップされ、接続がリセットされます。
また、最初に説明したケースでも、バックエンド セクションで HAProxy が指すサーバーには SNI が必要な場合があることにも注意してください。そのため、SNI 表示のない不完全なリクエストを転送すると、接続がリセットされることになります。