Резервирование резервирования. Как я наш интернет труба шатал
Syn-Ack Хабр! Меня зовут Сергей Минаев, я руководитель направления администрирования веб-сервисов в компании «Спортмастер».
В преддверии наступающего Нового года хочется, чтобы было спокойно и тихо, можно было кушать оливье, спокойно отдыхать, а не вот это вот все: пожар, караул, 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-балансировке быть, хотя бы в продолжительном пилотном режиме.
- Чтобы не настроить подпорок и улучшить доступность, вторую точку входа (балансировщик) мы будем размещать в облаке
- На начальном этапе — пропускаем трафик на наши площадки, если они не отвечают — отдаем заглушку < — Мы где-то здесь
- Доработка наших систем для работы без доступности всех макро- и микросервисов. Например, можно показывать каталог товаров, но отключать корзину.
- Доработка наших систем для работы в распределенном режиме: синхронизации, блокировки и весь остальной набор головной боли. Это поможет нам балансировать трафик и направлять на «локальную» площадку относительно пользователя. В идеале — балансировка на удаленную, если локальная недоступна.