21
Апр

OpenVZ и routing tables

Написал Максим Крентовский в Деятельность

По роду текущей деятельности занимаюсь настройкой серверов с контейнерами на базе OpenVZ, стал свидетелем очень интересного явления. Так, если, допустим, на один интерфейс назначено более двух IP-адресов и есть желание задействовать оба, в Linux-е есть механизм таблиц маршрутизации, который позволяет выдавать разные таблицы маршрутов для разных классов соединений согласно правилам. Собственно, принцип там очень простой — мы смотрим на входящие соединения, и если они поступают с нужного нам интерфейса, то подсовываем им таблицу маршрутизации, где маршрутом по умолчанию будет следующий хоп этого самого интерфейса. Таким образом хост начинает нормально отвечать по обоим IP несмотря на их разные подсети и разные шлюзы.

Для реализации этого безобразия добавляем в /etc/network/interfaces следующий альяс:

1
2
3
4
5
6
7
auto eth0:1
iface eth0:1 inet static
        address xx.xx.10.80
        netmask 244.255.248.0
        post-up echo "10 reserve" >> /etc/iproute2/rt_tables
        post-up ip route add default via xx.xx.15.254 table reserve
        post-up ip rule add from xx.xx.10.80/23 table reserve

где через post-up добавляется соответствующая таблица, маршрут по умолчанию для нее и правило применения. Все достаточно просто.

Проблемы начинаются после перезагрузки. Я не зря упомянул OpenVZ — после рестарта контейнеры, расположенные на данном хосте «внезапно» потеряли связь по сети с этим самым хостом. Достучаться с соседей до них было без проблем, но вот ping-и с самого хоста на них категорически отказывались идти. Это было крайне удивительно, поскольку я уже много лет использую OpenVZ и такого безобразия за ним не наблюдал. Ситуация отягощалась еще тем, что на хосте находился сетевой сервис, который проксировал соединения к приложениям, расположенным внутри контейнеров и он тоже благополучно не работал из-за сетевой недоступности последних.

Проблема решилась пристальным вглядыванием в конфигурацию хоста. Единственное место, которое отличало его от типовой инсталляции было как раз наличие альяса со вторым адресом. На интуиции было осуществлено «подергивание» (выключение и включение) интерфейса eth0:1, после чего все контейнеры стали снова доступны и ситуация нормализовалась. По всей видимости, сервис vz, который стартовал после конфигурации интерфейсов и инициализировал механизмы сетевого взаимодействия с контейнерами, очень переживал от такого поведения до поднятия собственного интерфейса, но вполне толерантно к нему относился, если подобные операции произвести позже. В результате строчки инициации таблицы переехали в /etc/rc.local и теперь перезагрузка не приносит никаких проблем на этот счет.