В преддверии наступающего Нового года хочется, чтобы было спокойно и тихо, можно было кушать оливье, спокойно отдыхать, а не вот это вот все: пожар, караул, SRE взбунтовались! Говорят, резервирование — ненастоящее!
За уходящий год у нас накопилось достаточно много статистики по нашим инцидентам. Мы решили провести небольшое ретро года и заодно подумать, как можно улучшить наш сервис.
Данная статья — не более чем повествование и рассуждение о возможности инженерной мысли, заключенной в рисование котиков красными линиями. Все совпадения реальные, герои – не выдуманные, все происходило взаправду.
Какая у нас задача и какая проблематика
Из всего списка рассмотренных нами проблем выбивается баг прошивки пограничных коммутаторов.
Мы получили зависание пограничных коммутаторов и как следствие полную недоступность всех наших сервисов, включая DNS-серверы. Перестал работать резолв почти всех наших доменных имен.
И если Split-Brain или локальные проблемы (например, залипание ARP) наши сетевые администраторы решают просто подняв бровь, то при недоступности всей площадки нужно думать как-то иначе.
Видел чудеса техники, но такого!
С этапом постановки проблематики и цели мы закончили, теперь переходим ко второму этапу – осмотримся. ИТ-инфраструктура у нас построено достаточно канонична, с соблюдением бест-практисов и “здравого смысла”:
- Две площадки или еще одна маленькая площадочка
- Разные каналы от разных провайдеров
- SDN
- Дублирующее оборудование
Для доступа из интернета мы используем балансировщики. Это несколько парных кластеров серверов, которые располагаются на разных площадках, подключены в разные коммутаторы по LACP, внешняя сеть растянута между площадками, IP резервируются по VRRP (keepalived).
Вполне себе джентльменский набор техник, а не простое “авось”. Но, возвращаясь к опыту: на Деда Мороза надейся, а сам не плошай.
А какие вообще варианты? Огласите весь список, пожалуйста
Если посмотреть по сторонам, крупными блоками можно попробовать выделить два направления улучшения доступности:
- Несколько площадок с резервированием “уровня инфраструктуры”
- Резервирование на уровне ПО
С первого взгляда, никакого rocket science нет: делаем несколько независимых точек присутствия, репликация данных, независимая обработка данных и глобальная блокировка.
Чтобы сделать несколько точек присутствия, для начала нужно как-то направить к ним трафик клиентов. Если делать “глобальный” балансировщик – он тоже может стать недоступным. Значит, нужно переходить немного вбок и на другой уровень.
Самое простое, что приходит в голову – эта балансировка на уровне DNS. Никаких особых настроек она не требует, добавляй только адреса и дополнительные DNS серверы на разных площадках.
Заманчивая по своей простоте идея, да и к тому же с кажущейся легкой реализацией. Знай себе только звезды на погоны вешай.
Но, не все так просто, как кажется… — закон Мерфи.
Что мы делаем? Тестируем!
Мы собрали небольшой локальный тестовый стенд в корпоративной сети, этого вполне достаточно, технология-то нетребовательная. Стенд – два сервера с Nginx, да настройка двух IP-адресов на одно имя, TTL занижен. Все готово, приступаем.
Вооружившись литературой, мы пропустили шаг тестирования “пингами”. Все равно подобные инструменты выбирают один из двух IP-адресов, и это никак не регламентируется. Сразу приступаем к натурным испытаниям при помощи curl с настройками по умолчанию (IP-адреса изменены):
curl -v 'https://dnsrr.test.local'
* Trying 5.6.7.300:443...
* connect to 5.6.7.300 port 443 failed: Время ожидания соединения истекло
* Trying 1.2.3.256:443...
* Connected to dnsrr.test.local (1.2.3.256) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* CAfile: /etc/ssl/certs/ca-certificates.crt
* CApath: none
Ну, какое-то переключение есть. Вот только тайм-аут по умолчанию – 1 минута. Можно его, конечно, скрутить вниз, но ведь никто не будет менять параметры у себя. Но давайте ради эксперимента все же попробуем:
curl --connect-timeout 2 -vs 'https://dnsrr.test.local' -o /dev/null
* Trying 5.6.7.300:443...
* After 998ms connect time, move on!
* connect to 5.6.7.300 port 443 failed: Время ожидания соединения истекло
* Trying 1.2.3.256:443...
* Connected to dnsrr.test.local (1.2.3.256) port 443 (#0)
* ALPN, offering h2
Ну, в принципе, оно работает, пускай и в очень лабораторных условиях. А вот Postman отказался воспринимать DNS RR. Хорошо, попробуем подключиться “реальными приложениями” – Chrome, Firefox. Все становится несколько интереснее:
- Если один из балансировщиков полностью недоступен, Chrome требуется около 15 секунд на переключение, Firefox – около 5
- Если на одном из серверов не отвечает порт 80/443, оба браузера переключаются за 2-3 секунды
На мобильных устройствах Safari и Chrome (Android) могут “залипнуть” на достаточно продолжительно время, вплоть до 20–30 секунд. Клиенты в приложениях мы не тестировали, предполагаем, что нам придется дописывать логику для резолва всех IP из записей и обработку доступности-недоступности балансировщиков.
Сыровато, но хоть какой-то результат.
Вместо заключения
DNS Round Robin используется большинством интернет-гигантов, так что она, конечно же, имеет право на жизнь. Скорее всего, мы чего-то не учитываем.
Из плюсов технологии: можно делать две технически независимые точки для подключения, есть шанс, что падение одной точки не заденет другую.
Без минусов никуда: веса настроить нельзя, распределение клиентов как повезет
Опосля всех рассуждений и мысленных экспериментов, подкрепленных натурными проверками, мы остановились на следующем:
- Все новое – хорошо забытое старое, чем проще – тем лучше, минус на минус дает плюс. DNS-балансировке быть, хотя бы в продолжительном пилотном режиме.
- Чтобы не настроить подпорок и улучшить доступность, вторую точку входа (балансировщик) мы будем размещать в облаке
- На начальном этапе – пропускаем трафик на наши площадки, если они не отвечают – отдаем заглушку < — Мы где-то здесь
- Доработка наших систем для работы без доступности всех макро- и микросервисов. Например, можно показывать каталог товаров, но отключать корзину.
- Доработка наших систем для работы в распределенном режиме: синхронизации, блокировки и весь остальной набор головной боли. Это поможет нам балансировать трафик и направлять на “локальную“ площадку относительно пользователя. В идеале – балансировка на удаленную, если локальная недоступна.
Комментарии (8)
lexore
23.12.2021 18:18+1Попробуйте BGP балансировку. Она гораздо более управляемая, чем DNS.
Одна и та же /24 подсеть анонсируется с обоих площадок в интернет. ip адрес сайта входит в эту /24 сеть. Дальше ваши сетевые инженеры уже подкрутят распределение трафика между площадками. Хоть active/standby, хоть 50/50.
Можно настроить одну площадку, как active, а вторую, как standby. Это удобно с точки зрения того, где держать мастер БД.
Кстати, правильная DNS балансировка - это когда какой-то сервис чекает доступность площадки. И отдает ее IP адрес, только если она живая. Как в кубере, например.
myz0ne
23.12.2021 21:44Как с bgp-балансировкой и вышеуказанной схемой предлагаете обрабатывать перестроение машрутов у клиентов? Судя по ripestat это довольно часто происходит. Представьте что посередине tcp-сессии у кого-то на пути трафика поменялись приоритеты и трафик клиента полетел на другую площадку на другой сервер, которому это tcp-соединение совершенно незнакомо.
Я примерно представляю как это решается, но в вашей схеме с "ip адрес сайта входит в эту /24 сеть" это не особо очевидно.
lexore
24.12.2021 15:07Судя по ripestat это довольно часто происходит.
Смотря что считать "часто". Например, раз в сутки или раз в неделю - это часто или нет?) На ровном месте маршруты не меняются так, чтобы трафик всея рунета стал течь в другой ДЦ. Это какие-то изменения или аварии. А они происходят не так часто. Кроме того, у сетевых инженеров огромные возможности для управления анонсами для разных сетей.
С другой стороны, web - это на 99% короткие tcp сессии. Время их жизни измеряются секундами, не минутами. Браузер умеет в переповторы. Поэтому, клиенты почти не чувствуют результатов перестроений.
Я это рассказываю, имея опыт нескольких лет работы в ivi.ru. Там годами используются и несколько ДЦ, и CDN в десятках городах. И все работает не основе анонсов сетей по BGP.
myz0ne
24.12.2021 16:51Ну вот сейчас посмотрел для https://stat.ripe.net/widget/bgplay#w.resource=91.233.218.122 и это 242 события за два дня. Понятно что не все приведут к тому что трафик полетит в другой ДЦ и если не мониторить те же rst-пакеты, то про проблему можно и не заметить. Опять же если это статика, наверное даже клиенты не всегда её замечают или просто перезагружают страницу. Для statefull клиентов она заметна сильнее.
Что самое плохое - чтобы заметить её надо знать что она моет проявиться и кто в группе риска. В основном это клиенты, которые находятся где-то посередине между двумя ДЦ. Более того, подобную проблему находил и репортил гуглу с их глобальными ип-адресами.
Dzzzen
24.12.2021 09:45+1Google DNS 8.8.8.8 больше не поддерживает DNS RR
https://habr.com/ru/company/southbridge/blog/282638/
DNS Round Robin has never been an effective means of load-balancing, and is less so today, as applications switch from gethostbyname to getaddrinfo for IPv6 support
minaevsergei Автор
24.12.2021 18:48Перепроверили резолв на 8.8.8.8 - на нашей внешней тестовой среде отдает два IP адреса для одной A записи.
Cloudflare DNS тоже отдает два IP.
Dzzzen
25.12.2021 12:33DNS-сервер не только должен отдавать два IP-адреса, но еще и менять их местами. Можно несколько раз запустить nslookup и проверить, что порядок меняется.
Кстати, сейчас проверил, но 8.8.8.8 опять поддерживает RoundRobin. Наверное, почили по просьбам трудящихся
amarao
У "гигантов" DNS в RR - это эникаст адреса, которые в первую очередь делают шардирование, а не резервирование. Т.е. они отдают пачку адресов, которые ведут на пачку серверов, чтобы если конкретный сервер воспламенился, то это задело не всех, а только запросы части клиентов.
Нормальное резервирование высокого уровня делают с участием сети. Например, делают ibgp на пачку серверов, у которых med разный. Как только предыдущий победитель сдох, автоматически есть следующий, и переключение занимает единицы секунд (или даже меньше).