Предисловие
В рамках IPv4 и IPv6 есть понятие Anycast-адресов. Если упрощать, то это IP-адреса выглядящие как обычные «серые» или «белые» адреса, но которые одновременно могут работать как на одном сервере, так и на множестве. Есть мнение, что это сложно настраивается, требует много дополнительных слоев маршрутизирующего оборудования и т.д. Но в данной статье я попробую описать настройку Anycast-адреса где угодно и с минимальными затратами. В качестве тестового стенда у нас будет роутер Mikrotik hAP lite и кластер Proxmox-а на мини-компьютерах RockPi (аналог Raspberry Pi) с виртуальными машинами на базе дистриутива Debian.
Зачем именно кластер Proxmox-а? Да просто так :)
Можно было бы обойтись виртуальными машинами на компьютере/ноутбуке созданных с помощью VirtualBox или одним мини-компьютером с Proxmox-ом, но у меня есть вот такая штука для домашних экспериментов, поэтому я использовал её.
Всем привет! Меня зовут Артём Друзь, я работаю старшим инженером в компании Контур, где занимаюсь настройкой и обслуживанием цифровой телефонии на базе Asterisk и OpenSIPS. Для цифровой телефонии в «классическом виде» используется UDP транспорт, и соответственно Anycast-адресация. Для создания отказоустойчивой телефонии, это прям то, что доктор прописал. Кто-то может возразить, что использование UDP – это прошлый век, и сейчас в моде WebSocket/WebRTC или даже QUIC. Но если вы включите WireShark и попробуете найти в огромном потоке вашего трафика обмен голосовыми пакетами в вашем любимом месенджере, то с большой долей вероятности вы найдете UDP трафик. Именно по этой причине настройка отказоустойчивости сервисов, использующих UDP транспорт, при помощи «старых методов и технологий» не теряет актуальности.
Проектируем сеть
Прежде чем начать настройку, накидаем схему того, что мы хотим увидеть в результате. В рамках имеющегося стенда есть ограничение в виде MikroTik hAP lite: из-за чипа на архитектуре smips нам недоступно использование протокола BGP, который рекомендуется для подобных штук. Поэтому возьмем протокол OSPF для анонсов IP-адреса с виртуальных машин. Для сурового продакшена с сотнями тысяч запросов в секунду, где важен каждый пакет данных, это, конечно, не подходит. Но в рамках тестового стенда таких нагрузок не планируется ;)
Для проекта сети этих вводных достаточно, так как остальная часть схемы будет реализована на уровне софта.
Настраиваем OSPF на MikroTik-е
Чтобы настроить в MikroTik-е прием анонсов нам нужна связка из трех элементов:
OSPF Instance – здесь задаем имя для нашей OSPF инсталляции
OSPF Area – описание OSPF зоны, которая привязывается к OSPF Instance
OSPF Interface Template – шаблон, по которому будет происходить аутентификация анонсов от виртуальных машин и создание интерфейсов в привязке к OSPF Area. В нем мы прописываем интерфейсы, в рамках которых нужно работать с анонсами (в моем случаем это общий мост bridge-lan). Здесь же задаются таймеры, согласно которым будут выполняться и обрабатываться анонсы, а отсутствие анонсов в течение Dead Interval будет трактоваться как триггер для удаления анонсирующего сервера из таблицы маршрутизации. У этих интервалов есть взаимосвязь между собой, поэтому нельзя везде назначить 1 секунду для ускорения сходимости при выходе анонсера из строя.
Ниже скриншот с настройками моего стенда.
Настраиваем анонсирование адреса на виртуальных машинах
Сначала создадим dummy-интерфейс на каждой из виртуальных машин и запустим его.
В файл /etc/network/interfaces
добавляем вот такую конструкцию:
auto dummy0
iface dummy0 inet static
address 172.18.0.64/32
pre-up ip link add dev dummy0 type dymmy
pre-down ip link delete dev dummy0 type dummy
Важно. IP-адрес в конфигурации интерфейса должен быть вне существующих подсетей, иначе схема не сможет корректно работать.
Далее запускаем интерфейс командой ifup dummy0
Для тех у кого дистрибутив Linux использует NetworkManager есть команда, которая делает по сути тоже самое, но одним действием:
nmcli connection add type dummy ifname dummy0 ipv4.method manual ipv4.addresses 172.18.0.64/32
Далее устанавливаем bird
apt install bird2
И вносим правки в /etc/bird/bird.conf
log syslog all;
protocol device {
}
protocol kernel {
ipv4 {
import none;
export all;
};
}
protocol static {
ipv4;
}
protocol ospf myAnycast { # myAnycast - любое произвольное имя для инстанса OSPF на уровне виртуальной машины
ipv4 {
import all;
export all;
};
area 0 {
stubnet 172.18.0.64/32 { # 172.18.0.64 - Anycast-адрес не входящий в существующие подсети в локальной сети
};
interface "enp0s11" { # enp0s11 - имя сетевого интерфейса с которого должны производиться анонсы Anycast-адреса
cost 1;
type broadcast;
hello 3; # Hello Interval из шаблона в MikroTik
retransmit 2; # Retransmit Interval из шаблона в MikroTik
wait 2;
dead 4; # Dead Interval из шаблона в MikroTik
authentication simple; # Authentication из шаблона в MikroTik
password "myOSPFpassword"; # Auth. Key из шаблона в MikroTik
};
interface "dummy0" { # Имя dummy интерфейса, на котором настроен Anycast-адрес
stub;
};
};
}
Теперь перезапускаем bird командой systemctl restart bird
, и через несколько секунд в интерфейсе MikroTik-а (при условии, что всё настроено правильно) мы должны увидеть что-то такое:
Проверяем работу Anycast-адреса...
... со стороны роутера
Здесь обойдемся простым ping-ом из консоли:
Есть контакт! На этом можно было бы остановиться, но хочется более живой пример :)
... со стороны других виртуальных машин
В данной проверке я решил проверить работу сервиса телефонии при схеме, когда 4 Asterisk-а с разных адресов подключаются к Anycast-адресу, которым пользуются OpenSIPS-ы (по одному на каждой из виртуальных машин, где настроен Anycast-адрес).
Читатель для проверки может использовать вместо SIP-серверов и программных АТС-ок какой-нибудь голосовой сервис работающий через UDP транспорт. На моем скриншоте tmux-а с запущенным sngrep-ом на двух виртуальных машинах (третью на время проверки выключил, чтобы получился читабельный снимок экрана). Видно, что:
Asterisk с адресом 172.18.0.24 распределился MiroTik-ом на первый OpenSIPS
Asterisk-и с адресами 172.18.0.22, 172.18.0.23 и 172.18.0.25 распределились на второй OpenSIPS
Как сделать другую стратегию распределения трафика (например, чтобы каждый пакет распределялся на анонсеров Anycast-адреса по стратегии round-robin) на MikroTik-е – это отдельная тема, и в данной статье мы её затрагивать не будем.
Таким образом, цель можно считать достигнутой и можно начинать экспериментировать с собственным Anycast-адресом ;)
Заключение
В статье я не упоминал ничего, что привязывало бы читателя к Proxmox-у в целом или к его конкретной реализации на мини-компьютерах с процессором ARM в частности. Статья является инструкцией по настройке Anycast-адреса на своем компьютере или в некой локальной сети, чтобы попробовать реализовать сервис использующий фишки этого вида адресов. В моем примере Proxmox нужен был только как общая среда создания виртуальных машин.
Как итог – у нас теперь есть свой Anycast-адрес, анонсирующийся через OSPF, с которым мы можем экспериментировать и проверять гипотезы. Безусловно, у данной схемы есть недоработки (например, маршрутизация исходящих пакетов через интерфейсы виртуальных машин выполняющих анонсирование). Но для того, чтобы начать разбираться с этой темой, данного трамплина, на мой взгляд, достаточно.
Важные оговорки, про которые выше по тексту в том или ином виде уже упоминались:
Описанное в статье решение не для сурового продакшена. Оно может быть использовано для малого бизнеса или задач саморазвития, но точно не для систем с тысячами RPS. Как минимум, для быстрой сходимости маршрутизации при отказе одной из нод вместо OSPF нужно использовать BGP.
Anycast-адресация это про UDP трафик, в котором нет понятия гарантированного подключения и доставки данных (анекдот). Если у вас TCP трафик (web-сайты, REST API, подключения к базам данных и прочее), то вам для отказоустойчивости и/или высокой доступности сервисов нужны балансировщики, которые обрабатывают такой трафик или специализируются под конкретный сервис (HAProxy, PgBouncer, Galera Cluster, Redis Sentinel и прочие).
На этом всё. Спасибо, что дочитали статью до конца.