В большинстве случаев на одном физическом сервере размещают несколько виртуальных серверов, при этом необходимо каким-то образом обеспечить доступность сервисов, работающих на виртуальных серверах, другим физическим машинам. Пробрасывать каждому виртуальному серверу по физическому интерфейсу накладно, да и неудобно. Часто хочется спрятать все виртуальные сервера за одним маршрутизатором/брандмауэром.
Посмотрим, какие средства для этого предлагает OpenVZ. Он предлагает 2 типа виртуальных сетевых интерфейсов:
Если в качестве маршрутизатора/брандмауэра для доступа к виртуальным серверам использовать физический сервер, стоит, несомненно, предпочесть venet. Поскольку такая конфигурация более распространена, то и venet-интерфейсы используются чаще. Однако чем сложнее конфигурация маршрутизатора/брандмауэра, тем больше оснований появляется для вынесения его в отдельный виртуальный сервер, чтобы не перегружать физический сервер лишними задачами и лишним ПО. В нашем случае дополнительным поводом стало желание иметь один и тот же адрес виртуального сервера, доступный извне, независимо от адреса узла кластера, на котором он в данный момент работает. Эта конфигурация в некоторых случаях может оказаться еще более сложной, если, например, на проброшенном физическом интерфейсе организовать поддержку IEEE 802.1Q VLAN, чтобы принять несколько vlan-ов, но с точки зрения настройки OpenVZ эта конфигурация не будет ничем отличаться от того, что было рассмотрено выше "-- разница будет только в настройке проброшенного сетевого интерфейса. Более важным является то, что в случае использования в качестве маршрутизатора/брандмауэра виртуального сервера более удобным будет построить виртуальную сеть на veth-интерфейсах. Выглядеть это будет так, как показано на рисунке 3.
Итак, для каждого виртуального сервера мы создаем veth-интерфейс, а концы этих интерфейсов со стороны физического сервера объединяем в бридж "-- в результате получается аналог хаба, в который включены все виртуальные сервера. Один из них уже имеет проброшенный в него физический интерфейс "-- этот виртуальный сервер и будет играть роль маршрутизатора/брандмауэра.
Создаем и стартуем виртуальные сервера:
[root@m1 ~]# vzctl create 102 Creating VE private area: /var/lib/vz/private/102 Performing postcreate actions VE private area was created [root@m1 ~]# vzctl set 102 --name mail --save Name ve1 assigned Saved parameters for VE 102 [root@m1 ~]# vzctl set mail --onboot yes --save Saved parameters for VE 102 [root@m1 ~]# vzctl set mail --hostname mail.mydomain.com --save Saved parameters for VE 102 [root@m1 ~]# vzctl start mail Starting VE ... VE is mounted Adding IP address(es): 192.168.199.2 Setting CPU units: 1000 Set hostname: mail.mydomain.com VE start in progress... [root@m1 ~]# vzctl create 103 Creating VE private area: /var/lib/vz/private/103 Performing postcreate actions VE private area was created [root@m1 ~]# vzctl set 103 --name dbms --save Name ve2 assigned Saved parameters for VE 103 [root@m1 ~]# vzctl set dbms --onboot yes --save Saved parameters for VE 103 [root@m1 ~]# vzctl set dbms --hostname dbms.mydomain.com --save Saved parameters for VE 103 [root@m1 ~]# vzctl start dbms Starting VE ... VE is mounted Adding IP address(es): 192.168.199.3 Setting CPU units: 1000 Set hostname: dbms.mydomain.com VE start in progress...
Создаем и конфигурируем veth-интерфейсы внутри виртуальных серверов:
[root@m1 ~]# vzctl set router --netif_add eth0 --save Configure meminfo: 35000 Configure veth devices: veth101.0 Saved parameters for VE 101 [root@m1 ~]# vzctl exec router ip address add 192.168.199.1/24 dev eth0 [root@m1 ~]# vzctl exec router ip link set eth0 up [root@m1 ~]# vzctl set mail --netif_add eth0 --save Configure meminfo: 35000 Configure veth devices: veth102.0 Saved parameters for VE 101 [root@m1 ~]# vzctl exec mail ip address add 192.168.199.2/24 dev eth0 [root@m1 ~]# vzctl exec mail ip link set eth0 up [root@m1 ~]# vzctl set dbms --netif_add eth0 --save Configure meminfo: 35000 Configure veth devices: veth103.0 Saved parameters for VE 101 [root@m1 ~]# vzctl exec dbms ip address add 192.168.199.3/24 dev eth0 [root@m1 ~]# vzctl exec dbms ip link set eth0 up
Объединяем концы veth-интерфейсов со стороны физического сервера в бридж:
[root@m1 ~]# ip link set veth101.0 up [root@m1 ~]# ip link set veth102.0 up [root@m1 ~]# ip link set veth103.0 up [root@m1 ~]# brctl addbr br0 [root@m1 ~]# brctl addif br0 veth101.0 [root@m1 ~]# brctl addif br0 veth102.0 [root@m1 ~]# brctl addif br0 veth103.0 [root@m1 ~]# ip link set br0 up
Проверяем работоспособность внутренней виртуальной сети:
[root@m1 ~]# vzctl exec router ping 192.168.199.2 PING 192.168.199.2 (192.168.199.2) 56(84) bytes of data. 64 bytes from 192.168.199.2: icmp_seq=1 ttl=64 time=15.9 ms [root@m1 ~]# vzctl exec router ping 192.168.199.3 PING 192.168.199.3 (192.168.199.3) 56(84) bytes of data. 64 bytes from 192.168.199.3: icmp_seq=1 ttl=64 time=3.71 ms
Теперь на виртуальных серверах описываем маршрут во внешнюю физическую сеть:
[root@m1 ~]# vzctl exec mail ip route add default via 192.168.199.1 [root@m1 ~]# vzctl exec dbms ip route add default via 192.168.199.1
На виртуальном маршрутизаторе включаем пересылку пакетов между физической и виртуальной сетями:
[root@m1 ~]# vzctl exec router sysctl -w net.ipv4.ip_forward=1
Теперь если на машине из физической сети 192.168.46.0/24 описать маршрут в сеть 192.168.199.0/24 (или настроить NAT на виртуальном маршрутизаторе "-- для этого потребуется в HN в файле /etc/vz/vz.conf в параметре IPTABLES указать необходимые модули), мы получим то, чего и добивались:
[root@m1 ~]# vzctl exec mail ping 192.168.46.1 PING 192.168.46.1 (192.168.46.1) 56(84) bytes of data. 64 bytes from 192.168.46.1: icmp_seq=1 ttl=63 time=0.982 ms
Желательно, чтобы все описанные выше настройки сохранялись при перезапуске виртуальных серверов, сервиса vz и ведущего узла кластера. С настройками виртуальных серверов проще всего "-- их можно сохранить в etcnet:
[root@m1 ~]# vzctl enter router [root@router /]# mkdir /etc/net/ifaces/eth0 [root@router /]# echo 192.168.199.1/24 > /etc/net/ifaces/eth0/ipv4address [root@router /]# echo "BOOTPROTO=static > ONBOOT=yes > TYPE=eth" > /etc/net/ifaces/eth0/options [root@m1 ~]# vzctl enter mail [root@mail /]# mkdir /etc/net/ifaces/eth0 [root@mail /]# echo 192.168.199.2/24 > /etc/net/ifaces/eth0/ipv4address [root@mail /]# echo default via 192.168.199.1 dev eth0 > /etc/net/ifaces/eth0/ipv4route [root@mail /]# echo "BOOTPROTO=static > ONBOOT=yes > TYPE=eth" > /etc/net/ifaces/eth0/options [root@m1 ~]# vzctl enter dbms [root@dbms /]# mkdir /etc/net/ifaces/eth0 [root@dbms /]# echo 192.168.199.3/24 > /etc/net/ifaces/eth0/ipv4address [root@dbms /]# echo default via 192.168.199.1 dev eth0 > /etc/net/ifaces/eth0/ipv4route [root@dbms /]# echo "BOOTPROTO=static > ONBOOT=yes > TYPE=eth" > /etc/net/ifaces/eth0/options
Для автоматического добавления концов veth-интерфейсов со стороны физического сервера в бридж при старте соответствующего виртуального сервера потребуется создать файл /etc/vz/vznet.conf со следующим содержимым:
EXTERNAL_SCRIPT=/etc/vz/vznet.sh
Внешний скрипт для конфигурирования veth-интерфейсов /etc/vz/vznet.sh будет выглядеть так:
#!/bin/sh brctl addif br0 $3 ip link set $3 up
Наконец, бридж тоже нужно создать, и сделать это необходимо еще до старта всех виртуальных серверов. Лучше всего добавить его создание в конфигурацию etcnet на обеих узлах кластера:
[root@m1 ~]# mkdir /etc/net/ifaces/br0 [root@m1 ~]# echo TYPE=bri > /etc/net/ifaces/br0/options
Таким образом мы добились того, чего хотели: в штатном режиме виртуальные сервера mail и dbms работают на узле m1, а в случае его отказа автоматически переезжают на узел m2, при этом с точки зрения внешнего наблюдателя из физической сети 192.168.46.0/24 наблюдается лишь кратковременный перерыв в обслуживании:
$ ping 192.168.199.2 PING 192.168.199.2 (192.168.199.2) 56(84) bytes of data. 64 bytes from 192.168.199.2: icmp_seq=1 ttl=64 time=0.549 ms ... From 192.168.46.1 icmp_seq=83 Destination Host Unreachable ... From 192.168.46.200 icmp_seq=83 Destination Host Unreachable ... 64 bytes from 192.168.199.2: icmp_seq=179 ttl=64 time=1.05 ms --- 192.168.46.200 ping statistics --- 179 packets transmitted, 25 received, +93 errors, 86% packet loss, time 178149ms rtt min/avg/max/mdev = 0.298/193.970/1702.783/397.285 ms, pipe 3