せっかくサーバを仮想化しているのだから、ネットワークも仮想化して自由に構成したい。データセンターではセキュリティや管理の為にセグメントを分けるのは常識だし、クラスタ間は専用のネットワークを繋ぐ前提で作られているソフトウェアも多い。このネットワークシステムを、1台のサーバ内で仮想的に構築したい。
まずXenのネットワークの基礎を説明する。Xenでは仮想ネットワークは下記のような構造になる。
peth0 vif0.0 eth0
[物理I/F]-----(xenbr0)----------[Domain0]
| |vif1.0 eth0
| +-----------[Domain-U]
|vif2.0 eth0
+---------------[Domain-U]
Domain0(実サーバ)やDomain-U(仮想サーバ)から見ると、自分が使っているインターフェースはおなじみのeth0という名前だが、その間はXenが作った仮想ブリッジ(xenbr0)でつながっている。また物理インターフェースも実サーバに直接つながっているわけではなく、仮想ブリッジにつながっている。こうすることで、仮想サーバも物理インターフェースから直接外部に出ることができるのである。
peth0、vif0.0、vif1.0などは仮想ブリッジ側のインターフェースであり、IPアドレスは付与しない。vif x.yのxは仮想サーバのIDをさしており、yは仮想サーバ側から見たインターフェース番号をあらわしている。つまり仮想サーバ1に2つのインターフェースを持たせてそれぞれeth0、eth1とすると、それにつながる仮想ブリッジのポートはvif1.0、vif1.1となる。なお仮想サーバのIDは起動するごとに変わるので不定である。
物理インターフェースが2つある場合は、単純に下記のようになる。
peth0 vif0.0 eth0 eth1 vif1.0 peth1
[物理I/F]-----(xenbr0)----------[Domain0]----------(xenbr1)-----[物理I/F]
| | | |
| |vif1.0 eth0 eth1 vif1.1| |
| +-----------[DomainU]-----------+ |
|vif2.0 vif2.0|
| eth0 eth1 |
+---------------[DomainU]---------------+
物理インターフェースが1つしかないが仮想サーバで2つのインターフェースを使いたい場合はdummyインターフェースを作成する。
peth0 vif0.0 eth0 dummy0 vif1.0 peth1
[物理I/F]-----(xenbr0)----------[Domain0]----------(xenbr1)
| | | |
| |vif1.0 eth0 eth1 vif1.1| |
| +-----------[DomainU]-----------+ |
|vif2.0 vif2.0|
| eth0 eth1 |
+---------------[DomainU]---------------+
Domain0のdummy0インターフェースにはIPを付与して仮想サーバと通信をすることも出来るし、IPを付与せず仮想サーバ同士の通信だけをさせることも出来る。
この考え方を元に、DMZや仮想サーバ間専用リンクを持った複雑なネットワークを作ってみる。なおvif名は設定上関係ないので省略する。
peth1 eth1 eth0 peth0
[物理I/F]-----(xenbr1)----------[Domain0]----------(xenbr0)-----[物理I/F]
|dummy0 | | | | eth0
| | | | +-----[ns1]
| | | | eth0
| | | +-------[ns2]
| | | eth0
| | +---------[storage1]
| | eth0
(xenbr2) +-----------[manager1]
| |
| | eth0 eth1 eth0
| +---[lvs1]-----+ +------[www1]
| |eth2 | |
| (xenbr4) (xenbr3)
| |eth2 | | eth0
+--------[lvs2]-----+ +------[www2]
eth0 eth1
xenbr2~4はDMZに相当する。図では示していないがDomain0はxenbr3、xenbr4にdummy1、dummy2でつながっている。
①dummyインターフェースを複数使用可能にするため、カーネルモジュールの設定をする。またxenbrがループバックデバイスを消費し、デフォルト数の4を越えてしまうので増やしておく。(この2行の設定に行き着くまでにまる一日かかった...)
[root@ml115 ~]# vi /etc/modprobe.conf ... options dummy numdummies=3 netloop nloopbacks=5 ...
ここでいちど再起動をしたほうがいいと思う。
②dummyインターフェースの設定を作成し、起動させる。
[root@ml115 ~]# vi /etc/sysconfig/network-script/ifcfg-dummy0 DEVICE=dummy0 BROADCAST=192.168.2.255 HWADDR=00:16:3E:2B:02:fe IPADDR=192.168.2.254 NETMASK=255.255.255.0 NETWORK=192.168.2.0 ONBOOT=yes [root@ml115 ~]# ifconfig dummy0 updummy1、dummy2も同様
③Xenのネットワーク設定をする
/etc/xen/scripts/に下記の内容のファイルを作成する。
[root@ml115 ~]# vi /etc/xen/scripts/network-bridge.wrap
#!/bin/sh
# Exit if anything goes wrong.
set -e
# First arg is the operation.
OP=$1
shift
script=/etc/xen/scripts/network-bridge
case ${OP} in
start)
$script start vifnum=0 bridge=xenbr0 netdev=eth0
$script start vifnum=1 bridge=xenbr1 netdev=eth1
$script start vifnum=2 bridge=xenbr2 netdev=dummy0
$script start vifnum=3 bridge=xenbr3 netdev=dummy1
$script start vifnum=4 bridge=xenbr4 netdev=dummy2
;;
stop)
$script stop vifnum=0 bridge=xenbr0 netdev=eth0
$script stop vifnum=1 bridge=xenbr1 netdev=eth1
$script stop vifnum=2 bridge=xenbr2 netdev=dummy0
$script stop vifnum=3 bridge=xenbr3 netdev=dummy1
$script stop vifnum=4 bridge=xenbr4 netdev=dummy2
;;
status)
$script status vifnum=0 bridge=xenbr0 netdev=eth0
$script status vifnum=1 bridge=xenbr1 netdev=eth1
$script status vifnum=2 bridge=xenbr2 netdev=dummy0
$script status vifnum=3 bridge=xenbr3 netdev=dummy1
$script status vifnum=4 bridge=xenbr4 netdev=dummy2
;;
*)
echo 'Unknown command: ' ${OP}
echo 'Valid commands are: start, stop, status'
exit 1
esac
次に/etc/xen/xend-config.sxpを編集する
... (network-script network-bridge) ...↓↓↓
... (network-script network-bridge.wrap) ...
④各仮想サーバ定義ファイルのネットワーク設定をする。いじるのはvif=の行。ちなみにMACアドレスを重複しないように決めるのが大変なので、IPアドレスの下2オクテットを16進数にしてMACアドレスの下2オクテットとして使っている。
[root@ml115 xen]# vi /etc/xen/lvs1 name = "lvs1" memory = "256" disk = [ 'tap:aio:/var/lib/xen/images/lvs1,xvda,w', ] vif = [ 'mac=00:16:3e:2b:02:02, bridge=xenbr2', 'mac=00:16:3e:2b:03:fc, bridge=xenbr3', 'mac=00:16:3e:2b:04:01, bridge=xenbr4'] ←前の行の続き。間で改行しない。 vfb = ["type=vnc,vncunused=1"] uuid = "f83c4a0b-4831-f424-d341-ccf824e91410" bootloader="/usr/bin/pygrub" vcpus=1 on_reboot = 'restart' on_crash = 'restart'
他の仮想サーバも同様に設定する。
⑤各サーバを立ち上げてネットワーク設定をする
[root@lvs1 ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth0 # Xen Virtual Ethernet DEVICE=eth0 BROADCAST=192.168.2.255 HWADDR=00:16:3E:2B:02:02 IPADDR=192.168.2.2 NETMASK=255.255.255.0 NETWORK=192.168.2.0 ONBOOT=yes [root@lvs1 ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth1 # Xen Virtual Ethernet DEVICE=eth1 BROADCAST=192.168.3.255 HWADDR=00:16:3E:2B:03:FC IPADDR=192.168.3.252 NETMASK=255.255.255.0 NETWORK=192.168.3.0 ONBOOT=yes [root@lvs1 ~]# vi /etc/sysconfig/network-scripts/ifcfg-eth2 # Xen Virtual Ethernet DEVICE=eth2 BROADCAST=192.168.4.255 HWADDR=00:16:3E:2B:04:01 IPADDR=192.168.4.1 NETMASK=255.255.255.0 NETWORK=192.168.4.0 ONBOOT=yes [root@lvs1 ~]#
ここで仮想サーバを起動していたら
Error: destroyDevice() takes exactly 3 arguments (2 given)
などというエラーがでて起動しなくなってしまった。これを追っかけていって上記のnetloop nloopbacks=5にたどり着いた次第。
⑥Domain0のiptablesを設定する
Domain0からみると新しいインターフェースdummy0ができるので、その先からの通信を許可する必要がある。ここはDMZなので本当は厳しくフィルタをする必要があるが、まずはテストなのですべて許可にしてしまう。
[root@ml115 ~]# vi /etc/sysconfig/iptables ... -A RH-Firewall-1-INPUT -i dummy0 -j ACCEPT ... [root@ml115 ~]# service iptables reload
⑦通信確認
構成図のlvs1とlvs2が出来上がったら、相互にpingを打って通信確認をしよう。
[root@lvs1 ~]# ping 192.168.2.3 PING 192.168.2.3 (192.168.2.3) 56(84) bytes of data. 64 bytes from 192.168.2.3: icmp_seq=1 ttl=64 time=0.968 ms 64 bytes from 192.168.2.3: icmp_seq=2 ttl=64 time=0.384 ms 64 bytes from 192.168.2.3: icmp_seq=3 ttl=64 time=0.451 ms --- 192.168.2.3 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 1999ms rtt min/avg/max/mdev = 0.384/0.601/0.968/0.260 ms [root@lvs1 ~]# ping 192.168.3.253 PING 192.168.3.253 (192.168.3.253) 56(84) bytes of data. 64 bytes from 192.168.3.253: icmp_seq=1 ttl=64 time=0.438 ms 64 bytes from 192.168.3.253: icmp_seq=2 ttl=64 time=0.368 ms 64 bytes from 192.168.3.253: icmp_seq=3 ttl=64 time=0.432 ms --- 192.168.3.253 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 1998ms rtt min/avg/max/mdev = 0.368/0.412/0.438/0.039 ms [root@lvs1 ~]# ping 192.168.4.2 PING 192.168.4.2 (192.168.4.2) 56(84) bytes of data. 64 bytes from 192.168.4.2: icmp_seq=1 ttl=64 time=0.642 ms 64 bytes from 192.168.4.2: icmp_seq=2 ttl=64 time=0.476 ms 64 bytes from 192.168.4.2: icmp_seq=3 ttl=64 time=0.428 ms --- 192.168.4.2 ping statistics --- 3 packets transmitted, 3 received, 0% packet loss, time 1998ms rtt min/avg/max/mdev = 0.428/0.515/0.642/0.093 ms [root@lvs1 ~]#
