CentOSとiptablesでper-packet loadbalance with coreemu

Posted on 2013/01/26(Sat) 02:20 in technical

Linuxでパケット単位のロードバランスをしながら、coreemuの宣伝をします。

今回のキーワードは、 CentOS, coreemu, iptables, fwmark, loadbalance, per-packet loadbalance 辺りでしょうか。

Install coreemu for CentOS 6.3

さっくりインストールするので、いくつか現時点のハマりどころを書いておく。

基本的には、2.2.2. Installing from Packages on Fedora/CentOSを読みながら進みましょう。

  1. tkimgとlibevを先にインストールしておく必要があります。(EPEL使う場合は勝手に入るのでOK)
  2. SELINUXを無効にするか適切に設定しないとzebra(およびルーティングデーモン)が動きません
  3. ホスト側でiptablesを無効にするか空っぽにしておかないと、仮想リンク間のパケットが全部叩き落とされます。 iptables -F; /etc/init.d/iptables save とかで良いですかね。
  4. yumで入るtkのバージョンが古いので、仮想リンクの遅延等を設定しようとすると Error: Invalid command name "ttk::spinbox" が出るので、tcl/tk8.5をソースからコンパイルして上書きしましょう。また、この時 tk のconfigure中に X11 のライブラリリンクを要求されるので、 libX11-devel をインストールしておきましょう。(以下参考画像)

centos_ttk_spinbox_001

centos_ttk_spinbox_002

Let's topology making

さて、トポロジを作りましょう。とりあえずこんな感じですかね。(各ノードはデフォルト設定のまま放り込んでいます)

loadbalance_001

そして、OSPFのコンバージェンス後、n1のルーティングテーブルは以下のようになります。

[root@n1 n1.conf]# ip route
10.0.4.0/24 dev eth2 proto kernel scope link src 10.0.4.1
10.0.5.0/24 proto zebra metric 30
nexthop via 10.0.0.2 dev eth0 weight 1
nexthop via 10.0.1.2 dev eth1 weight 1
10.0.0.0/24 dev eth0 proto kernel scope link src 10.0.0.1
10.0.1.0/24 dev eth1 proto kernel scope link src 10.0.1.1
10.0.2.0/24 via 10.0.0.2 dev eth0 proto zebra metric 20
10.0.3.0/24 via 10.0.1.2 dev eth1 proto zebra metric 20

通常時のロードバランス(ECMP)

n1~n4のルータではOSPFが動作しており、特に設定をしていないので、必然的にECMP(Equal-cost multi-path)になります。

LinuxにおけるECMPの動作は、通常宛先IPベースで別々の次ホップに割り当てていくので、トラフィックが流れっぱなしになっていると、キャッシュが消えるまで常に同じ経路を通ることになります。

その動きをしているのが下の図。

左側のノードから右側のノードに向けて、 ping 10.0.5.20 -i 0.1 -l 1400 のようにしてpingを投げています。

n1とn2の間は遅延5[ms]、n1とn3の間は遅延10[ms]に設定しているので、行きも帰りもn2を経由していることになります。

loadbalance_002

ここで、n1でキャッシュを確認後、消してみると、RTTが15[ms]となり、行きの経路が下を通るようになります。

loadbalance_003

OSPF等で宛先が複数あっても、パケット毎にロードバランスが行われないことは、まぁ、普通ですよね。

iptablesを用いたper-packet loadbalance

そこでiptablesを用いて、パケット毎に別々の経路を通るように設定してみます。

コンフィグはこんな感じ。

ip route add 10.0.5.0/24 via 10.0.0.2 table 101
ip route add 10.0.5.0/24 via 10.0.1.2 table 102
ip rule add fwmark 1 table 101
ip rule add fwmark 2 table 102
iptables -t mangle -A PREROUTING -j MARK --set-mark 1
iptables -t mangle -A PREROUTING -m statistic --mode nth --every 4 --packet 0 -j MARK --set-mark 2
では、コンフィグ投入後の動作を見てみましょう。
loadbalance_004

遅延が15[ms]と20[ms]で切り替わっているので、n5→n6のパケットがn1でパケット毎のロードバランスが行われていることになります。応答パケットとなるn6→n5については、常にn3を通る経路を(n4が)選択しています。

直感からすると、 --every 4 は2じゃないのか、って思うんですけど、これ僕がmanを読み違えてるのか、バグなのか分かんないんですよねぇ。

ちなみに、これは確率を使うこともできるので、その場合はこうなります。

ip route add 10.0.5.0/24 via 10.0.0.2 table 101
ip route add 10.0.5.0/24 via 10.0.1.2 table 102
ip rule add fwmark 1 table 101
ip rule add fwmark 2 table 102
iptables -t mangle -A PREROUTING -j MARK --set-mark 1
iptables -t mangle -A PREROUTING -m statistic --mode random --probability 0.5 -j MARK --set-mark 2

iptables -t mangle -F で一旦消して、再投入します。

loadbalance_005

ま、大体50%、ということで。

終わる

というわけで、Linuxのロードバランス動作とかiptablesの設定を確認するのに、coreemuは中々使える子だよ、ってのをまた宣伝するための記事でした。

おまけ

まったくもって別件なのだけど、例えば今回のようにn5とn6でパケットキャプチャして、その間で発生したパケロスとか遅延とか、そういうネットワーク品質の測定が出来るとそれはそれで面白いだろうなぁ、と思ってるのね。

で、Pythonでちょこちょこ書いてるツールがあるんだけど、これに放り込むと良い感じに遅延が5[ms]と10[ms]になってるのが分かってちょっと自己満足してる図がこれ。

loadbalance_pcapdiff_001

PySide可愛いよPySide。