以前にLVSのメンテナンスをする機会があってテスト用に環境構築していた時にいろいろ調べたことをメモとしてつらつらと残しておく。 文字ベースだけど必要そうな図とかそのうち作るかもしれない。
LVS
LVSはLinux Virtual Serverの略で、The Linux Virtual Server Project - Linux Server Cluster for Load Balancingで開発されている。
多くのケースではIPVSを差すことが多いと思う。が、他にもある。 Linux Virtual Serverという表現だとピンとこないが、LVS Introduction - Load Balancing Server Clusterの説明や図を見る限りだと、クラスタリングや負荷分散技術を利用してシステム全体を1つのサーバとみなせるよう可用性の高いシステムを構築しよう、という感じっぽい。 パケットのロードバランス周りではL4レベルでパケットをロードバランスするIPVS (IP Virtual Server)というカーネルモジュール(Linuxカーネル 2.4以降で取り込まれ、現在 net/netfilter/ipvs 以下にソースコードが配置されている)の他、L7レベルでパケットをロードバランスするKTCPVS (Kernel TCP Virtual Server)というものもあるが、これは今も開発されているのかよくわからない。
keepalivedというソフトウェアもあるが、これはざっくりいうとIPVSをkeepalived経由で設定可能にしたものに、さらにヘルスチェック機能やVRRPによる冗長化機能を追加したもの…という認識。 IPVS単体だと負荷分散先のサーバの死活監視ができないのでサーバが落ちてもリクエストを振り続けるといった事態になるためこれに対応する手段が必要になる。また、冗長化機能はないのでシステム全体として可用性を高める必要がある場合は何かしら手段を考える必要がある。
負荷分散時の通信方式
LVSでの負荷分散時の通信方式としてはNATかL2DSRになるのではないかと思う。 NATはロードバランサのアプライアンス製品だと一般的だがDSRは最近は馴染みのない人も多いかもしれない。L3DSRというのもあるがいろいろ手間がかかりそうで自分ではやったことないので割愛する。
NAT
NAT方式はLVSサーバを経由する通信で送信元IPアドレス変換を行う。往復の通信処理がLVSサーバを経由し、トラフィックの処理にCPU処理が入る分負荷が高くなるようだが、この方式を試したことはないのでどのくらいのリクエストでどのくらいの負荷がかかるのかは不明。ただ、F社などのLBアプライアンス製品を扱っていることが多い人だとNAT方式の方がわかりやすいんじゃないだろうか。 この方式だと行きと戻りの通信がLVSを経由することになる(Client -> LVS -> Real Server -> LVS -> Client)ので通信経路が一致するのと、LVS配下のサーバ(リクエスト振り分け先のサーバ)で何か特殊な設定をする必要もないのが良い。
L2DSR
一方でL2DSRだと、クライアントからLVS(VIP)へ通信が発生した場合、LVSサーバーは配下のRealサーバーへ ARP リクエストを行い、そのMACアドレスを取得してそのMACアドレスを持つRealサーバー宛にリクエストを送信する。Realサーバーは送信元IPアドレスをloopbackアドレス、送信元MACアドレスを自身のアドレスに書き換えて、戻り直接クライアントに返す。 そのため、Client -> LVSサーバ -> Realサーバ -> Client という経路になる。この方式だと戻りの通信がLVSサーバを経由しない分LVSサーバの負荷が低くなるが、行きと戻りの通信経路が非対称になってしまう。 また、L7レベルのMACアドレス変換を行えるようReal サーバ側にもVIPのアドレスの設定が必要(※)であったりと、LVSとReal Serverを同一セグメントに置く必要があるなど制約も多い。
※L2DSRでは、Real サーバのloopbackインタフェースにLVSでセットしているVIPを割り当てておくことで、LVSを経由してきた通信(宛先IPはLVSのVIPのまま)を自身のloopbackインタフェースで受けることができる。特定のNICに複数のIPを割り当てることも設定としてはできるが、VIPへのARP要求にLVSサーバもReal サーバも応じることになりおかしいことになる。loopbackインタフェースならARP要求に応答しないため、loopbackインタフェースに設定する。この場合、戻り通信は、受信時の送信元IP(クライアント)を宛先IPにしてデフォルトゲートウェイに返す。
※L2DSRの構成イメージ | +-----------+ | LVS | eth0:192.168.10.101/24(実IP) +-----------+ eth0:192.168.10.100/32(VIP(alias)) | +--------------------+--------------------+ | | | +-----------+ +-----------+ +-----------+ |Realサーバ1| |Realサーバ2| |Realサーバ3| +-----------+ +-----------+ +-----------+ eth0 192.168.10.1 eth0 192.168.10.2 eth0 192.168.10.3 lo:0 192.168.10.100 lo:0 192.168.10.100 lo:0 192.168.10.100
loopbackインタフェースにVIPのアドレスをセットしていない場合、クライアントからLVSのVIPにSYNが送られているけど、Real ServerからLVSのVIPに対してtcp retransmissionが発生していた。
loopbackインタフェースにエイリアスを設定する場合は以下のコマンドを実行する。
$ sudo ip addr add local LVSのVIP dev lo:0
この辺ちゃんとわかっていないとハマる気がする。
まとめ
LVSと通信方式について少し調べておいたことを書いた。 L3DSRはまだ触ってないのでそのうちやりたい。
参考
- The Linux Virtual Server Project - Linux Server Cluster for Load Balancing
- Linux Virtual Server - Wikipedia
- ロードバランスを考える - JANOG32
- 6. LVS: The ARP Problem
- ループバックインターフェイスと仮想IPについて - teratail
- Yahoo! JAPAN 仮想化への取り組み ~ OpenStack with LBaaS ~
- L3DSR – Overcoming Layer 2 Limitations of Direct Server Return Load Balancing
- 雑な LVS/TUN の解説図 - mura日記 (halfrack)