Cent0S + LVS on VirtualBox

VirtualBox上でCentOS5.3でLVSを組もうとしたら、ハマりまくったのでメモしときます。

構成


(internet)
|
| eth0 192.168.11.13/24 (ブリッジアダプタ)
| eth0:0 192.168.11.100/24 (仮想IP)
|
+----+----+
| cthulhu | ロードバランサー (LVSサーバ)
+----+----+
|
| eth1 192.168.21.13 (内部ネットワーク `intnet')
|
--+----+-- 192.168.21.0/24
|
| eth1 192.168.21.15 (内部ネットワーク `intnet')
|
+----+----+
| hastur | リアルサーバ (Webサーバ)
+----+----+
|
| eth0 192.168.11.15/24 (ブリッジアダプタ)
|
(internet)



ソフトウェア構成

  • WindowsXP (ホストOS)
  • CentOS5.3 (ゲストOS)
  • VirtualBox 3.0.6

最初はMac OS Xでやろうとしていたけど、AirMacでブリッジアダプタが使えないので、Windowsに変更した。ゲストOSのxmlファイルをいろいろいじったりしたけど、結局うまくいかず…
NATでも出来なくはないと思うけど。



ゲストOSのセットアップ

フツーにインストールして、フツーにclonevdiしたり、ifcfg-eth1を修正したり…で、yum update。どうもyum update kernelをしないとIPVSが動かないような気がする…*1
(参考 http://centos.org/modules/newbb/viewtopic.php?topic_id=20112&forum=37
Guest Additionalをインストールしたので、カーネルがリビルドされてうまく動かなくなっていたのかもしれない。


ちなみになんか引っかかると怖いので、ファイアウォール(iptables)とSELinuxはDisabledにしておいた。



仮想IPの追加

cthulhuに仮想IPを追加する。
フツーに /etc/sysconfig/network-script/ifcfg-eth0:0 を追加して、service network restart。


[/etc/sysconfig/network-script/ifcfg-eth0:0]
DEVICE=eth0:0
IPADDR=192.168.11.100
NETMASK=255.255.255.0
TYPE=Ethernet
BOOTPROTO=none
ONPARENT=yes
ifcfgファイルの中身ってわりと適当に書いても無問題のような気が。あと、動的に仮想IPを追加する場合の ifconfig と ip addr add の違いが分からない…同じ?

[root@cthulhu ~]# ifconfig
eth0 Link encap:Ethernet HWaddr 08:00:27:6A:33:F0
inet addr:192.168.11.13 Bcast:192.168.11.255 Mask:255.255.255.0
inet6 addr: fe80::a00:27ff:fe6a:33f0/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:12 errors:0 dropped:0 overruns:0 frame:0
TX packets:49 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:1845 (1.8 KiB) TX bytes:9166 (8.9 KiB)
Interrupt:11 Base address:0xd020

eth0:0 Link encap:Ethernet HWaddr 08:00:27:6A:33:F0
inet addr:192.168.11.100 Bcast:192.168.11.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
Interrupt:11 Base address:0xd020

eth1 Link encap:Ethernet HWaddr 08:00:27:5A:59:05
inet addr:192.168.21.13 Bcast:192.168.21.255 Mask:255.255.255.0
inet6 addr: fe80::a00:27ff:fe5a:5905/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:54 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 b) TX bytes:8788 (8.5 KiB)
Interrupt:10 Base address:0xd240

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:1718 errors:0 dropped:0 overruns:0 frame:0
TX packets:1718 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:3301244 (3.1 MiB) TX bytes:3301244 (3.1 MiB)


[root@cthulhu ~]# ip addr show
1: lo: mtu 16436 qdisc noqueue
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 08:00:27:6a:33:f0 brd ff:ff:ff:ff:ff:ff
inet 192.168.11.13/24 brd 192.168.11.255 scope global eth0
inet 192.168.11.100/24 brd 192.168.11.255 scope global secondary eth0:0
inet6 fe80::a00:27ff:fe6a:33f0/64 scope link
valid_lft forever preferred_lft forever
3: eth1: mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 08:00:27:5a:59:05 brd ff:ff:ff:ff:ff:ff
inet 192.168.21.13/24 brd 192.168.21.255 scope global eth1
inet6 fe80::a00:27ff:fe5a:5905/64 scope link
valid_lft forever preferred_lft forever
4: sit0: mtu 1480 qdisc noop
link/sit 0.0.0.0 brd 0.0.0.0



LVSの準備

cthulhu

yum install ipvsadm。


それから、/etc/sysctl.confを修正して sysctl -p を実行。


[/etc/sysctl.conf(抜粋)]
# Controls IP packet forwarding
#net.ipv4.ip_forward = 0
net.ipv4.ip_forward = 1

# Controls source route verification
#net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.default.rp_filter = 0

rp_filterの設定変更は必要なのか、必要ないのかいまいちわからず。


それから /etc/sysconfig/network も修正して、念のため service network restart。


[/etc/sysconfig/network]
NETWORKING=yes
NETWORKING_IPV6=no
HOSTNAME=cthulhu
FORWARD_IPV4=yes
これも必要な設定かどうか、ちゃんと分かってない。


ipvsadmの起動スクリプトも修正。


[/etc/init.d/ipvsadm(抜粋)]
# chkconfig: - 11 89

hastur

とりあえずWebサーバを起動しておきましょう。念のためcthulhu側から curl http://192.168.21.15/ とかやってアクセスできることを確認。


192.168.11.100がhastur自身を指すようにループバックに仮想IP*2を追加。


[/etc/sysconfig/network-scripts/ifcfg-lo:0]
DEVICE=lo:0
IPADDR=192.168.11.1
NETMASK=255.255.255.255
ONBOOT=yes
(実際には ip addr add 192.168.11.100 label lo:0 dev loとして、設定ファイルの変更とnetworkのリスタートはしなかった)


[root@hastur ~]# ifconfig
eth0 Link encap:Ethernet HWaddr 08:00:27:12:83:26
inet addr:192.168.11.15 Bcast:192.168.11.255 Mask:255.255.255.0
inet6 addr: fe80::a00:27ff:fe12:8326/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:18 errors:0 dropped:0 overruns:0 frame:0
TX packets:74 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:2685 (2.6 KiB) TX bytes:16384 (16.0 KiB)
Interrupt:11 Base address:0xd020

eth1 Link encap:Ethernet HWaddr 08:00:27:C7:11:08
inet addr:192.168.21.15 Bcast:192.168.21.255 Mask:255.255.255.0
inet6 addr: fe80::a00:27ff:fec7:1108/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:83 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:0 (0.0 b) TX bytes:16200 (15.8 KiB)
Interrupt:10 Base address:0xd240

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:1687 errors:0 dropped:0 overruns:0 frame:0
TX packets:1687 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:3255708 (3.1 MiB) TX bytes:3255708 (3.1 MiB)

lo:0 Link encap:Local Loopback
inet addr:192.168.11.1 Mask:255.255.255.255
UP LOOPBACK RUNNING MTU:16436 Metric:1


[root@hastur ~]# ip addr show
1: lo: mtu 16436 qdisc noqueue
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet 192.168.11.100/32 brd 192.168.11.100 scope global lo:0
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 08:00:27:12:83:26 brd ff:ff:ff:ff:ff:ff
inet 192.168.11.15/24 brd 192.168.11.255 scope global eth0
inet6 fe80::a00:27ff:fe12:8326/64 scope link
valid_lft forever preferred_lft forever
3: eth1: mtu 1500 qdisc pfifo_fast qlen 1000
link/ether 08:00:27:c7:11:08 brd ff:ff:ff:ff:ff:ff
inet 192.168.21.15/24 brd 192.168.21.255 scope global eth1
inet6 fe80::a00:27ff:fec7:1108/64 scope link
valid_lft forever preferred_lft forever
4: sit0: mtu 1480 qdisc noop
link/sit 0.0.0.0 brd 0.0.0.0


ARPに反応しないように /etc/sysctl.conf を修正して sysctl -p を実行。


[/etc/sysctl.conf(抜粋)]
net.ipv4.conf.eth1.arp_ignore = 1
net.ipv4.conf.eth1.arp_announce = 2
ループバックに仮想IPを追加した場合に、この設定変更が必要になるみたい。「リアルサーバで仮想IPをどうするか」問題の対処はいくつかあった気がするけど、よく覚えていない。(see asin:4798011894)


ここにもハマってしばらく立ち往生した。



LVS-DSR

はじめはDSRがうまくいった。たぶんhusterに192.168.11.0/24への足(eth0)がないと、うまくいかない気がする。


cthulhuでipvsadmの設定を追加。


[root@cthulhu ~]# ipvsadm -C
[root@cthulhu ~]# ipvsadm -A -t 192.168.11.100:80 -s lc
[root@cthulhu ~]# ipvsadm -a -t 192.168.11.100:80 -r 192.168.11.15 -g
[root@cthulhu ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.11.100:80 lc
-> 192.168.11.15:80 Route 1 0 0


一応、設定を保存。


[root@cthulhu ~]# /etc/init.d/ipvsadm save
Saving IPVS table to /etc/sysconfig/ipvsadm: [ OK ]
[root@cthulhu ~]# cat /etc/sysconfig/ipvsadm
-A -t 192.168.11.100:80 -s lc
-a -t 192.168.11.100:80 -r 192.168.11.15:80 -g -w 1


クライアントマシンから curl http://192.168.11.110/ を実行。

困ったこと

最初に設定したときはうまくいかなかったので、hasterで tcpdump -n -i eth0 port 80 としてeth0を監視*3。一応パケットが届いていることを確認。その後、ループバックの仮想IPを追加して解決



LVS-NAT

次にNAT。かなり手こずる。

cthulhu

cthulhuでipvsadmの設定を追加。


[root@cthulhu ~]# ipvsadm -C
[root@cthulhu ~]# ipvsadm -A -t 192.168.11.100:80 -s lc
[root@cthulhu ~]# ipvsadm -a -t 192.168.11.100:80 -r 192.168.21.15 -m
[root@cthulhu ~]# ipvsadm -Ln
IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
TCP 192.168.11.100:80 lc
-> 192.168.21.15:80 Masq 1 0 1
[root@cthulhu ~]# /etc/init.d/ipvsadm save
Saving IPVS table to /etc/sysconfig/ipvsadm: [ OK ]
[root@cthulhu ~]# cat /etc/sysconfig/ipvsadm
-A -t 192.168.11.100:80 -s lc
-a -t 192.168.21.100:80 -r 192.168.11.15:80 -m -w 1


cthulhuで192.168.21.15を192.168.11.100に変換。


[root@cthulhu ~]# /etc/init.d/iptables start
[root@cthulhu ~]# iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
[root@cthulhu ~]# /etc/init.d/iptables save
[root@cthulhu ~]# chkconfig iptables on

hastur

まず、eth0を停止。


デフォルトゲートウェイを追加。(設定ファイルはifcfg-eth1かな?)


[root@hastur ~]# route add -net default gw 192.168.21.13
[root@hastur ~]# route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.21.0 * 255.255.255.0 U 0 0 0 eth1
169.254.0.0 * 255.255.0.0 U 0 0 0 eth1
default cthulhu 0.0.0.0 UG 0 0 0 eth1

/etc/resolv.confにcthulhuと同じネームサーバを設定する。


[/etc/resolv.conf(例)]
nameserver 192.168.11.1


Firefox等でhusturからインターネットに抜けられることを確認。


クライアントマシンから curl http://192.168.11.110/ を実行。

困ったこと

(その1)
DSRの直後にNATに設定を変更したらクライアント(Windows)のARPキャッシュが残っていて、パケットがhasturのeth0を通ってくる。仕方ないのでARPキャッシュを削除。


~$ arp -a

Interface: 192.168.11.9 --- 0x2
Internet Address Physical Address Type
192.168.11.1 **-**-**-**-**-** dynamic
192.168.11.100 08-00-27-12-83-26 dynamic
~$ arp -d 192.168.11.100
~$ arp -a

Interface: 192.168.11.9 --- 0x2
Internet Address Physical Address Type
192.168.11.1 **-**-**-**-**-** dynamic


(その2)
VMを再起動するとたまに内部ネットワークが通じなくなる。なのでcthulhucurl http://192.168.21.15/ が通じないときは、cthulhu・hasturでnetworkをリスタート。


(その3)
NATの設定でかなりハマる。

hasturで tcpdump -i eth1。パケットは届いていることは確認。
cthulhutcpdump -i eth0 -n port 80。192.168.21.15が表示されるので、IPの変換がうまくいってないものと推測。
iptablesを再起動したり、hasturを再起動したりとさんざんやって、最終的に上記の手順で動作を確認。
うまく動作しているときは、cthulhutcpdump -i eth0 -n port 80 で192.168.11.100(とクライアントのIP)しか表示されない。


[root@cthulhu ~]# tcpdump -i eth0 -n port 80
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
14:22:47.830981 IP 192.168.11.9.edb-server2 > 192.168.11.100.http: S 1720441602:1720441602(0) win 64240
14:22:47.832678 IP 192.168.11.100.http > 192.168.11.9.edb-server2: S 1180977649:1180977649(0) ack 1720441603 win 5840
14:22:47.833308 IP 192.168.11.9.edb-server2 > 192.168.11.100.http: . ack 1 win 64240
14:22:47.844061 IP 192.168.11.9.edb-server2 > 192.168.11.100.http: P 1:154(153) ack 1 win 64240
14:22:47.848059 IP 192.168.11.100.http > 192.168.11.9.edb-server2: . ack 154 win 6432
14:22:47.853612 IP 192.168.11.100.http > 192.168.11.9.edb-server2: . 1:1461(1460) ack 154 win 6432
14:22:47.853729 IP 192.168.11.100.http > 192.168.11.9.edb-server2: . 1461:2921(1460) ack 154 win 6432
14:22:47.854220 IP 192.168.11.9.edb-server2 > 192.168.11.100.http: . ack 2921 win 64240
14:22:47.855299 IP 192.168.11.100.http > 192.168.11.9.edb-server2: . 2921:4381(1460) ack 154 win 6432
14:22:47.855484 IP 192.168.11.100.http > 192.168.11.9.edb-server2: FP 4381:5242(861) ack 154 win 6432
14:22:47.856240 IP 192.168.11.9.edb-server2 > 192.168.11.100.http: . ack 4381 win 64240
14:22:47.856244 IP 192.168.11.9.edb-server2 > 192.168.11.100.http: . ack 5243 win 63379
14:22:48.835942 IP 192.168.11.9.edb-server2 > 192.168.11.100.http: F 154:154(0) ack 5243 win 63379
14:22:48.839097 IP 192.168.11.100.http > 192.168.11.9.edb-server2: . ack 155 win 6432

*1:一括でアップデートしたので、きちんと特定できず

*2:エイリアスと同義なのかしらん?

*3:ブリッジアダプタだとホストOSの通信もeth0を通っているように見えた