Предисловие
В рамках 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 и прочие).
На этом всё. Спасибо, что дочитали статью до конца.
BasilioCat
Гуглинг "tcp anycast" дает однозначный ответ на этот вопрос
Использовать OSPF вместо BGP, просто потому что его не поддерживает hAP lite.. Ну так железо подбирают под решение, а не наоборот
Для netplan в некоторых версиях Ubuntu не было предусмотрено создание dummy-интерфейсов. Да и не нужно - anycast-адреса можно добавлять алиасами к lo, или создавать bridge-интерфейсы