Скажите, сколько раз вам приходилось писать в interfaces что-то вроде
iface xxx0 inet yyy
…
iface xxx0:1 inet zzz
…
iface xxx0:31 inet bbb
…
? Ну, может, самим и не приходилось, но, наверное, хоть разочек вы с таким сталкивались.
И сполна поимели секса со всеми проблемами, которые создаёт подобное нагромождение.
Невозможно работать с трафиком алиасов в iptables на уровне интерфейсов, DHCP сервер висит на всех алиасах и никак его оттуда не выковырять, ну и так далее.
А знаете, что самое смешное?… Без всего этого головняка можно замечательно обойтись. Только одна проблема - документации по IPROUTE2 LINK категорически нет. То, что есть - не описывает даже десятой части всех возможностей режима.
Одна из возможностей - создание MAC-based VLAN - виртуальных сетей на базе MAC адреса (а не какого-то условного тега или чего ещё малопонятного и требующего дорогостоящего оборудования для поддержки).
Ядро этой возможности требует ядра не ниже 3.12 (в более старых ядрах часть функционала отсутствует, либо работает неверно), так что если у вас стоит какое-то старьё - самое время обновить. Для этого зайдите в рутовую консоль и выполните
# apt-get install linux-generic-lts-<какой там последний в вашем случае>
Для 12.04 это будет linux-generic-lts-trusty (3.13.0-49 ATM)
Для дальнейших экспериментов представим себе гипотетический сервер с одним физическим интерфейсом, подключённый к двум сетям, а так же являющийся хостом для контейнеров LXC.
Физический интерфейс сервера -
eth0.
Сети, к которым подключён сервер:
192.168.0.1/24 - локальная сеть организации, для которой хост выступает DHCP сервером;
192.168.1.1/24 - техническая сеть для устройств (свичей, камер и подобной требухи), для которой сервер является средством мониторинга и сбора статистики.
Контейнеры LXC включены в сеть организации через мост br0.
Текущая конфигурация interfaces:
auto lo
iface lo inet loopback
auto br0
iface br0 inet static
address 192.168.0.1
netmask 255.255.255.0
gateway 192.168.0.2
bridge_ports eth0
auto br0:1
iface br0:1 inet static
address 192.168.1.1
netmask 255.255.255.0
pre-up ifconfig br0 up
Ужас. Век бы не видел… ещё и тормозит жутко.
и LXC:
…
lxc.network.type = veth
lxc.network.link = br0
lxc.network.hwaddr = 00:16:3e:xx:xx:xx
lxc.network.name = eth0
Как видим, eth0 у нас уже оккупирован мостом, и пока мы этот мост оттуда не снимем, мы ничего с eth0 сделать не сможем.
Основная проблема в том, что это таки сеть, через которую вы таки сидите на сервере (если только вы не сидите на корточках перед сервером), и вы имеете все шансы на пешую эротическую прогулку к этому милому шкафчику, допусти вы малейшую ошибку в перенастройке сети.
Постараемся ошибок избежать. Для этого, во-первых, убедитесь, что у вас отключены все правила в iptables и открыт весь доступ. Лучше всего будет временно убрать скрипт, загружающий правила, и заменить его пустой "заглушкой", разрешающей всем всё.
Для пущей безопасности можно погасить опасные, но некритичные для текущей задачи сервисы (MySQL, Samba, postfix, LDAP и т.п.). Предполагается, что вы не занимаетесь этой операцией в середине рабочего дня,
ведь правда?
Во-вторых, проверьте, что нет каких-либо головоломных правил маршрутизации.
# ip rule show
# ip route show table all type unicast
Все головоломки нужно аккуратно задокументировать, а потом убедиться, что они все нафиг отключены без шанса вылезти посреди настройки и спровоцировать пешее… ну, вы поняли.
Теперь нам надо принять важное решение. Дело в том, что у macvlan есть четыре режима работы:
private - ваш обычный интерфейс с торчащим из него кабелем; пакеты, отправленные через "приватный" интерфейс, ВСЕГДА отправляются наружу, пакеты с адресом отправителя равным адресу приватного интерфейса, принятые тем же физическим интерфейсом, фильтруются. Т.е. послать через такой интерфейс сообщение другому виртуальному интерфейсу на том же физическом интерфейсе, или самому физическому интерфейсу, на котором построен виртуальный, невозможно.
vepa - Virtual Ethernet Port Aggregator. Пакеты так же ВСЕГДА отправляются наружу; послать пакет с одного виртуального интерфейса на другой, находящийся на том же физическом интерфейсе, или на сам физический интерфейс можно, но для этого нужен внешний свич, поддерживающий специальный режим (VEPA/hairpin), иначе встроенная система фильтрации в свиче запретит пересылать пакет обратно в тот же порт, с которого пакет пришёл.
bridge - ваш классический локальный мост. Все виртуальные интерфейсы, созданные в этом режиме, могут обмениваться пакетами между собой, не покидая пределов хоста. Отправить пакет с виртуального интерфейса на физический… вроде нельзя. Информации недостаточно.
passthru - какой-то специальный режим, судя по описанию призванный решить некие локальные проблемы с KVM. Информации недостаточно.
Итак, у нас есть четыре режима работы. Ээээ… Первый - private. Второй практически не поддерживается аппаратно. Третий - bridge. Четвёртый - вариант второго.
Выходит, у нас реалистично есть только два режима? Ну что же, это упрощает выбор.
Сравним характерные особенности обоих режимов.
private - отдельный интерфейс, подключённый к (виртуально) отдельному кабелю; достучаться до него с соседних интерфейсов хоста… скажем так, проблематично и требует наличия внешнего маршрутизатора.
bridge - все интерфейсы в этом режиме могут общаться между собой и с внешним миром. Но не с физическим интерфейсом, на котором они построены.
Посмотрим на требования, предъявляемые нашей оперативной средой.
Очевидно, контейнеры получают режим моста; так же нам надо как минимум один интерфейс хоста в режиме моста, чтобы иметь возможность общаться с контейнерами. Этот же интерфейс мы можем использовать для связи с локальной сетью предприятия.
Для связи с сетью вспомогательных устройств можно либо использовать сам физический интерфейс, либо создать ещё один виртуальный приватный интерфейс. Здесь есть доводы в пользу обоих вариантов, но мне больше по душе второй виртуальный интерфейс. При смене физического интерфейса будет достаточно поправить имя в одном месте, не трогая настройки тех же iptables.
Итак, окончательное решение должно выглядеть примерно следующим образом:
1. Виртуальный интерфейс mac0@eth0 - 192.168.0.1/24, режим bridge.
2. Виртуальный интерфейс mac1@eth0 - 192.168.1.1/24, режим private.
3. LXC type macvlan mode bridge.
Шаг первый. Самый простой - перенастройка LXC.
Меняем конфигурацию контейнеров на
…
lxc.network.type = macvlan
lxc.network.macvlan.mode = bridge
lxc.network.link = eth0
lxc.network.hwaddr = 00:16:3e:xx:xx:xx
lxc.network.name = eth0
Перезагружать контейнеры пока не торопимся, работать не будут. Мало того, что работать не будут, могут запуститься без сети вообще, ибо RTNETLINK answers: resource is busy.
Шаг второй. Теперь нам надо
очень аккуратно разобрать мост.
1. Убиваем вспомогательную сеть. Она нам не больно-то и нужна прямо сейчас.
# ifdown br0:1
2. Открываем /etc/network/interfaces, удаляем строчку "auto br0", удаляем ссылки на алиас, добавляем описание локальной сети на eth0:
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet static
address 192.168.0.1
netmask 255.255.255.0
gateway 192.168.0.2
iface br0 inet static
address 192.168.0.1
netmask 255.255.255.0
gateway 192.168.0.2
bridge_ports eth0
Три раза проверьте, что нигде не ошиблись. Уверены? Тогда…
# ifdown br0; ifup -a
У вас всё ещё есть сеть? Замечательно. Убивайте настройки бриджа в interfaces полностью. Он больше не нужен.
Шаг третий. Наш первый виртуальный интерфейс!
На самом деле это очень просто.
# ip link add mac1 link eth0 type macvlan
Всё! У нас есть новенький интерфейс. Можете полюбоваться на него:
# ip link show
Чтобы он заработал, не надо вообще никакой магии.
# ip address add mac1 local 192.168.1.1/24 broadcast 192.168.1.255
# ip link set mac1 up
Впрочем, сейчас лучше будет его удалить.
# ip link delete mac1 type macvlan
Можно прямо так и прописать в interfaces:
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet static
address 192.168.0.1
netmask 255.255.255.0
gateway 192.168.0.2
auto mac1
iface mac1 inet static
address 192.168.1.1
netmask 255.255.255.0
pre-up ip link set eth0 up
pre-up ip link add $IFACE link eth0 type macvlan mode private
post-down ip link delete $IFACE type macvlan
Не очень красиво, зато работает!
По аналогии настраиваем второй интерфейс:
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet manual
auto mac0
iface mac0 inet static
address 192.168.0.1
netmask 255.255.255.0
gateway 192.168.0.2
pre-up ip link set eth0 up
pre-up ip link add $IFACE link eth0 type macvlan mode bridge
post-down ip link delete $IFACE type macvlan
auto mac1
iface mac1 inet static
address 192.168.1.1
netmask 255.255.255.0
pre-up ip link set eth0 up
pre-up ip link add $IFACE link eth0 type macvlan mode private
post-down ip link delete $IFACE type macvlan
Проверьте три раза… проверили?
# ifdown eth0; ifup -a
Вы ещё с нами? И у вас даже есть сеть? Странно. Можете внимательно возвращать все правила и настройки обратно с учётом изменившихся имён интерфейсов.
Не забудьте выправить /etc/default/isc-dhcp-server !
…
Контейнеры тоже не забудьте перезагрузить…
…
Что-что? Вам не нравится лапша в interfaces? Какие вы, однако, привередливые. Ну, ладно, ладно. Ловите.