WSL2とDockerでロードバランサーのテストを考える

WSL2とDockerでロードバランサーのテストを考える

こんにちは。樋口です。
最近業務で知り合った方に「MBSのブログ見てますよ」と言っていただけることが増えてきました。さらに、嬉しいことに「樋口さんの書いたこの記事が役に立ったんですよ~」なんて言っていただけることが何度かあり、ブログ執筆へのモチベーションもますます上がってきています。
ただ、いざそんな嬉しいことを言っていただけても、どんなリアクションを取ってよいかわからずオドオドしてしまったのは反省です。

ロードバランサーのテストをしたい

さて、本日はあるオンプレミスの機器を検証しているときに、機器のロードバランサー機能をテストしようと思ったときの話です。
パブリッククラウドサービスでは様々なサービスがあり、ロードバランサーも分散先のサーバも簡単に用意できますが、オンプレミス環境の機器をテストで触っているときはなかなかそうもいきません。

今回は以下のようなhttpのトラフィックを3台のサーバにロードバランスする機能のテストを行いました。Web1~3のところは、実際にはサーバが来ることになりますが、あくまで挙動を簡単に確かめてみたいという場合はサーバを準備するのはなかなか面倒です。

そこで今回は1台のWindowsPCで3台分のサーバの挙動を極力簡単にテストする方法を探ってみました。
まず最初に行った方法は、普段からWSL2のUbuntuを使っていたこともあり、このWSL2上でdockerで3台分のwebサーバを立ててみるといった方法です。

WSL2のUbuntuでdockerを動かす

ひとまず以下のようなdocker-compose.ymlでwebサーバとなるコンテナを3つ立ち上げてみました。このときWSL2(Ubuntu)でWindows側から見えているIPアドレスは現状1つなので、ポートを80,81,82と分けることにしました。

version: "3"
services:
  web1:
    image: nginx:latest
    container_name: web1
    ports:
      - "80:80"
    volumes:
      - ./web1:/usr/share/nginx/html
  web2:
    image: nginx:latest
    container_name: web2
    ports:
      - "81:80"
    volumes:
      - ./web2:/usr/share/nginx/html
  web3:
    image: nginx:latest
    container_name: web3
    ports:
      - "82:80"
    volumes:
      - ./web3:/usr/share/nginx/html

この時点で、ホストのWindows PCからはIPアドレス、もしくはlocalhostへのポートフォワーディングが有効になっていればlocalhostでアクセスが可能になっていると思います。

余談ですが、このlocalhostのポートフォワーディングの有効/無効は.wslconfigファイルで設定可能ですが、デフォルトは有効になっているようです。(参考:WSLでの詳細設定の構成 - Microsoft Learn)

ただし、このままではホストのWindows PCからしか見えないので、ネットワーク上の他のPCからも見えるよう、WSL2(Ubuntu)のIPアドレスにポートフォワーディングの設定をしてやる必要があります。

> netsh interface portproxy add v4tov4 listenaddress=<ホストのIPアドレス> listenport=<転送元ポート> connectaddress=<転送先ipアドレス=WSL2のUbuntuのIPアドレス> connectport=<転送先ポート>

たとえば仮にWeb1を80番ポート、Web2を81番ポート、Web3を82番ポートで見たければ以下の3つの設定を入れる必要があります。(転送先IPアドレスは環境によって変わります、上述の設定ができていればlocalhostでも良いと思います)

> netsh interface portproxy add v4tov4 listenaddress=192.168.100.100 listenport=80 connectaddress=172.27.174.134 connectport=80
> netsh interface portproxy add v4tov4 listenaddress=192.168.100.100 listenport=81 connectaddress=172.27.174.134 connectport=81
> netsh interface portproxy add v4tov4 listenaddress=192.168.100.100 listenport=82 connectaddress=172.27.174.134 connectport=82

ポートフォワーディングの設定

今回は上図のようにそのまま1つのIPアドレスに対するアクセスをポート番号で振り分けても目的を達成できません。ロードバランサはIPアドレスで振り分けるので、下図のようにWeb1からWeb3を異なるポートではなく異なるIPアドレスで識別する必要があります。

そこで、まずはホストのPCに必要なIPアドレスを割り当てます。
Windows PCのネットワークの設定から、以下のように必要なIPアドレスを割り当てます。今回は有線での接続でテストしたので、当該アダプタの設定に入ります。

これで以下のようにイーサネットアダプタに、192.168.100.101~103の3つのIPアドレスが割り当てられました。

さらにWindows PCで以下のようにポートフォワーディングの設定を行います。
今回は192.168.100.101の80番ポートに届いたものをWeb1に振り分けるので、以下のようになります。

> netsh interface portproxy add v4tov4 listenaddress=192.168.100.101 listenport=80 connectaddress=172.27.174.134 connectport=80
> netsh interface portproxy add v4tov4 listenaddress=192.168.100.102 listenport=80 connectaddress=172.27.174.134 connectport=81
> netsh interface portproxy add v4tov4 listenaddress=192.168.100.103 listenport=80 connectaddress=172.27.174.134 connectport=82

必要に応じてWindows PCのファイアウォールの設定を変えると、ネットワーク上の他のPCからもアクセスができるようになります。以下は同じセグメントの別PCからそれぞれのIPアドレスで各コンテナにアクセスしている様子です。(注意:ファイアウォールの設定変更は問題のない環境で必要最低限にし、テスト終了後は元に戻すことを推奨します)

今回の構成の問題点

これにて、当初の目的であったロードバランサー機能でトラフィックが振り分けられていることを確認することはできました。以下は同一セグメント上の別PC(192.168.100.11)から各コンテナにアクセスした様子です。

一方で今回の構成では問題点があります。多くのロードバランサーにはサーバなどのターゲットがリクエストを処理できるかどうかを定期的に確認し、処理不能と判断するとそのターゲットには転送しないヘルスチェックの機能があります。

ヘルスチェックの方法はいくつもありますが、今回の構成だと80番ポート以外の通信、例えばpingによるヘルスチェックが行われる場合に問題があります。実際にターゲットに192.168.100.101~103のIPアドレスが割り当てられているのではなく、あくまでホストのWindows PCに割り当てられています。現状ではホストのPCが動いている限り、pingに対しては応答します。

これを回避するためには、ホストのWindows PCにIPアドレスを割り当てるのではなく、コンテナに割り当てて、さらにホストのHyper-Vマネージャーで外部スイッチを作成し、WSLの設定でその外部スイッチを利用し、・・・といった設定が必要になるようです。こちらは試そうとしたところ少し躓いてしまったので、また整理ができたら紹介したいなと思います。

Next Post Previous Post