Вместо вступления
За основу взята более ранняя прочитанная мной статья на Хабре, которой лично мне оказалось достаточно для понимания механизма policy routing в целом — и катастрофически мало для реализации этого типа маршрутизации на сервере компании. Было 2 серьезных подводных камня, над которыми пришлось работать самостоятельно, и которые нельзя оставить без внимания:
- Сохранение настроек в целом
- Перебивание настроек утилитой Network Manager
Свою статью я напишу в виде той инструкции, которую написал для будущих поколений айтишников в своей фирме — так что некоторые пункты из основной статьи буду приводить либо в неизменном, либо в пересказанном для себя виде. Их буду выделять курсивом. Для полного понимания того, что здесь написано, рекомендую ознакомиться с ней полностью.
Немного практики, или чего мы хотим
А хотим мы получить маршрутизацию, которая:
- будет отправлять данные на тот же шлюз, с которого пришел запрос
- будет контролируемо балансировать нагрузку между шлюзами, используя т.н. «вес» (weight) шлюзов
Для этих целей будем использовать утилиту iproute2, входящую в стандартную поставку всех дистрибутивов Linux.
Выдаем IP-адреса:
ip a a 11.11.11.11/22 dev eth6
ip a a 22.22.22.22/28 dev eth5
Определяем таблицы:
Для использования более чем одного маршрута, статической маршрутизации уже недостаточно. Для OSPF наша схема слишком проста, поэтому остановимся на динамической маршрутизации с использованием таблиц.
ip route add default via 22.22.22.17 table 101
ip route add default via 11.11.8.1 table 102
Заворачиваем исходящий трафик, на шлюзы, с которых пришел входящий:
ip rule add from 22.22.22.17 table 101
ip rule add from 11.11.8.1 table 102
Думаю теперь уже объяснять смысл этих строк не надо. Аналогичным образом можно сделать доступность сервера по более чем двум шлюзам.
Балансировка трафика между аплинками
Делается одной элегантной командой:
ip route replace default scope global
nexthop via 22.22.22.17 dev eth5 weight 3
nexthop via 11.11.8.1 dev eth6 weight 7
Эта запись заменит существующий default-роутинг в таблице main. При этом маршрут будет выбираться в зависимости от веса шлюза (weight). Например, при указании весов 7 и 3, через первый шлюз будет уходить 70% соединений, а через второй – 30%. Есть один момент, который при этом надо учитывать: ядро кэширует маршруты, и маршрут для какого-либо хоста через определенный шлюз будет висеть в таблице еще некоторое время после последнего обращения к этой записи. А маршрут до часто используемых хостов может не успевать сбрасываться и будет все время обновляться в кэше, оставаясь на одном и том же шлюзе. Если это проблема, то можно иногда очищать кэш вручную командой ip route flush cache.
Результат
После выполнения данной команды можно проверять доступность сервера. В принципе, можно было сказать, что на этом наша работа закончилась. Однако есть одна проблема — после перезагрузки все настройки сбросятся.
Сохранение настроек в целом
Теперь необходимо заставить систему применять полученные настройки после перезагрузки.
IP-адреса
Для начала выясняем, какой mac-address какому интерфейсу принадлежит. Выполняем команду:
ip a
2: eth6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether aa:aa:aa:aa:aa:aa brd ff:ff:ff:ff:ff:ff
inet 11.11.11.11/22 brd 11.11.11.255 scope global eth6
3: eth5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether bb:bb:bb:bb:bb:bb brd ff:ff:ff:ff:ff:ff
inet 22.22.22.22/28 brd 22.22.22.31 scope global eth5
Далее создаем конфигурационные файлы настроек ifconfig с использованием полученных mac-адресов. Для этого создаем файлы с приставкой ifcfg и названием интерфейса в папке
# cat /etc/sysconfig/network-scripts/ifcfg-eth5
DEVICE=eth5
TYPE=Ethernet
ONBOOT=yes
NM_CONTROLLED=yes
BOOTPROTO=none
IPV6INIT=no
IPADDR=22.22.22.22
PREFIX=28
HWADDR=bb:bb:bb:bb:bb:bb
GATEWAY=22.22.22.17
DEFROUTE=yes
NAME=eth5
# cat /etc/sysconfig/network-scripts/ifcfg-eth6
DEVICE=eth6
TYPE=Ethernet
ONBOOT=yes
NM_CONTROLLED=yes
BOOTPROTO=none
IPV6INIT=no
IPADDR=11.11.11.11
PREFIX=22
HWADDR=aa:aa:aa:aa:aa:aa
Создаем таблицы маршрутизации
Далее необходимо создать постоянные таблицы, присвоить им имена (чтобы было проще ориентироваться) и прописать правила использования этих таблиц:
cd /etc/iproute2/
echo "101 int" >> rt_tables
echo "102 ext" >> rt_tables
Теперь возвращаемся в каталог /etc/sysconfig/network-scripts
и продолжаем работать там.
Создаем содержимое таблиц:
# cat route-eth5
default via 22.22.22.17 table ext
# cat route-eth6
default via 11.11.8.1 table int
Создаем правила обработки этих таблиц:
# cat rule-eth5
from 22.22.22.22 lookup ext
# cat rule-eth6
from 11.11.11.11 lookup int
Балансировка
Далее заменяем статику динамикой. Не обошлось без напильника, т.к. стартап-скрипты, описанные выше, привязываются к интерфейсам, а в нашем случае правило пишется сразу про 2 интерфейса. Поэтому решено было создать отдельный скрипт и прописать его в автозагрузку, используя стандартный механизм автозапуска Linux — /etc/rc.local
. Содержимое скрипта:
# cat /etc/network.sh
#!/bin/bash
/sbin/ip route replace default scope global nexthop via 11.11.8.1 dev eth6 weight 7 nexthop via 22.22.22.17 dev eth5 weight 3
exit 0
Его путь в автозагрузке:
# cat /etc/rc.local
#!/bin/sh
touch /var/lock/subsys/local
/bin/bash /etc/network.sh
В результате после перезагрузки мы получаем рабочую систему с использованием 2 независимых аплинков, трафик между которыми балансируется с помощью weight. А теперь печальная новость: ничего этого работать не будет.
Перебивание настроек утилитой Network Manager
Меньшая проблема из тех, что были на моем пути, но которая тем не менее, изрядно попортила мне нервы. Проблема данной утилиты в том, что она сохраняет и использует настройки не из основных конфигурационных файлов системы, а из своих внутренних. Поскольку стартует она вместе с X11, то есть в самую последнюю очередь, когда сеть уже запущена, она перезаписывает настройки сети, и каких-то сложных конфигураций на ней построить не получится.
Чтобы ее отключить, необходимо выполнить в консоли:
sudo /etc/init.d/NetworkManager stop
chkconfig NetworkManager off
Результат
И вот после выполнения этого действия и перезагрузки мы получаем рабочую систему с использованием 2 независимых аплинков, трафик между которыми балансируется с помощью weight.
Автор: Hanggard