Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
Примечание: Bunny CDN — сеть доставки контента и облачный хостинг со своими серверами DNS
Если в bunny.net есть что-то важнее производительности, то это надёжность. Всё продумано. Избыточный мониторинг, система автоматического восстановления, auto-healing на нескольких уровнях, три резервные сети DNS и система, которая связывает всё это вместе и гарантирует аптайм.
Но в нашей ситуации ничего не помогло. 22 июня 2021 года после почти двух лет безупречной работы из-за сбоя DNS произошло полное отключение почти всех систем. 750 000 сайтов частично ушли в офлайн более чем на два часа. В мгновение ока мы потеряли более 60% трафика и сотни гигабит пропускной способности. Несмотря на все резервные системы, глобальный сбой вызвало простое обновление одного файла.
Нас крайне расстроило это происшествие. Но мы надеемся извлечь урок, чтобы построить ещё более надёжную платформу. В духе прозрачности мы хотим рассказать о подробностях инцидента и о том, как собираемся решать подобные проблемы в будущем. Возможно, эта история станет уроком не только для нас, но и ещё для кого-нибудь.
Всё началось с простого обновления
Скажу сразу: история банальная. Всё началось с обычного, стандартного обновления. Мы проводим масштабный апгрейд для повышения надёжности и производительности всей платформы. Часть процесса — повышение производительности системы маршрутизации SmartEdge. Эта система пропускает большой объём данных, которые периодически синхронизируются с нашими узлами DNS. Для оптимальной синхронизации задействуется наша платформа Edge Storage, которая раздаёт большие файлы БД по всему миру через Bunny CDN.
Чтобы уменьшить потребление RAM, трафик и нагрузку на сборщик мусора, недавно мы перешли с JSON на библиотеку бинарной сериализации BinaryPack. Несколько недель она прекрасно работала. Сократилось использование памяти, время ожидания GC, использование CPU… пока всё не сломалось.
22 июня в 8:25 UTC мы выпустили обновление, чтобы уменьшить размер БД оптимизации. К сожалению, это привело к тому, что повреждённый файл загрузился в Edge Storage. Сам по себе повреждённый файл не проблема, ведь DNS разработан для работы с данными или без них. И он грациозно игнорирует любые исключения. Точнее, мы так думали.
Оказалось, что повреждённый файл заставил библиотеку BinaryPack немедленно выполниться с переполнением стека, обойдя любую обработку исключений, просто завершив процесс. В течение нескольких минут глобальная сеть из сотни DNS-серверов вышла из строя практически полностью.
График работы DNS-серверов: время приведено к UTC+7
Потом сложнее...
Чтобы осознать происходящее, потребовалось некоторое время. Через десять минут мы поняли, что DNS-серверы не вернуть в исходное состояние — они постоянно перезапускаются и падают.
Сначала казалось, что всё под контролем. Специально для таких случаев предусмотрена возможность одним нажатием кнопки немедленно откатить любой деплой. Но вскоре стало понятно, что ситуация гораздо сложнее, чем кажется. Мы быстро откатили все обновления для SmartEdge, но было уже слишком поздно.
И SmartEdge, и системы деплоя раздают данные на физические DNS-серверы через Edge Storage и Bunny CDN, а мы только что вывели из строя основную часть глобальной CDN.
Хотя сервер DNS умеет восстанавливаться автоматически, но при этом каждый раз он пытается загрузить сломанный деплой — и просто снова падает. Как вы понимаете, DNS-серверы не могут достучаться до CDN, чтобы загрузить обновление — и круг замыкается.
В 8:35 (15:35) несколько серверов ещё пытались работать, но это не слишком помогало, так что наша пропускная способность снизилась до 100-150 Гбит/с. Нам повезло лишь в том, что всё случилось ранним утром, почти с минимальным трафиком.
График трафика CDN: время приведено к UTC+7
…и ещё сложнее
В 8:45 мы придумали план. Давайте вручную накатим обновление, которое отключит систему SmartEdge на узлах DNS! Сначала показалось, что всё работает. Но мы очень, очень сильно ошиблись. Из-за сбоя CDN серверы DNS в итоге скачали ещё и повреждённые версии баз данных GeoDNS — и внезапно все запросы ушли в Мадрид. Поскольку это один из самых маленьких наших поинтов, он мгновенно упал.
Что ещё хуже, теперь 100 серверов стали перезапускаться в цикле, что привело к сбою центрального API — и перестали запускаться даже те немногочисленные серверы, которые удалось было вернуть к жизни.
Потребовалось некоторое время, чтобы понять, что на самом деле происходит, но после многочисленных попыток мы отказались от идеи восстановить сеть.
Ситуация зашла в тупик. Отчаянно требовалось запустить сервисы, но один-единственный повреждённый файл практически убил платформу.
Возвращаем ситуацию под контроль
Поскольку все внутренние дистрибутивы теперь были повреждены и обслуживались через CDN, пришлось искать альтернативу. Примерно в 9:40 нам пришла ещё одна идея. Если можно отправлять все запросы в один регион, то давайте направим их в самый большой, в качестве временной меры. Обновление маршрутизации перенаправило все запросы во Франкфурт.
Это был первый успех — и приличная часть трафика вернулась в сеть. Но так проблему не решить. Мы вручную развернули обновление на нескольких DNS-серверах, но остальные по-прежнему направляли запросы в Мадрид. Нужно было действовать быстро.
Стало ясно: пора признать поражение. Единственный выход — полностью отказаться от собственных систем. Девопсы принялись за работу и кропотливо перенесли все системы деплоя и файлы на сторонний облачный хостинг.
В 10:15 всё было готово. Мы перенастроили систему развёртывания и софт DNS на новый хостинг и нажали кнопку Deploy. Трафик медленно, но верно возвращался — и в 10:30 система снова была в строю. Точнее, так показалось.
Понятно, что все в панике и суетились. Мы пытались как можно быстрее поднять систему, одновременно отвечая на сотни заявок в службу поддержки и объясняя ситуацию. Конечно, в спешке мы допустили кучу опечаток и ошибок. Все знают, как важно сохранять спокойствие в таких ситуациях, но это легче сказать, чем сделать.
Оказалось, что в спешке мы установили неправильную версию базы GeoDNS, поэтому кластеры DNS по-прежнему отправляли запросы в Мадрид. Ситуация стала очень раздражать, но пришло время успокоиться, перепроверить настройки и спокойно провести финальный деплой.
В 10:45 мы именно это и сделали. Через стороннее облако удалось синхронизировать БД, развернуть самые свежие наборы файлов и поднять всю систему.
Полчаса мы внимательно следили, как нарастает трафик, и дотошно проверяли системы. Хранилище забилось до предела, потому что без системы SmartEdge мы отдавали большое количество некэшированных данных. Наконец, в 11:00 всё начало стабилизироваться и bunny.net вернулся к работе.
Итак, что же пошло не так?
Все системы были спроектированы и настроены на совместную работу. Они полагались друг на друга, включая критически важные части внутренней инфраструктуры. Если вы создаёте кучу крутой инфраструктуры, то ясное дело, хочется применить её в максимальном количестве собственных продуктов.
К сожалению, из-за подобного подхода один повреждённый файл обрушил несколько уровней избыточности. Сначала вышла из строя система DNS, потом CDN, потом хранилище и, наконец, служба оптимизации сайтов.
На самом деле во время возвращения сотен серверов эффект домино вывел из строя также API и панель мониторинга, что, в свою очередь, привело к сбою службы логгирования.
Набиваем шишки, чтобы стать сильнее!
Хотя такого «фейла» можно было избежать, но мы воспринимаем его как ценный урок. Система не идеальна, но к идеалу нужно стремиться. Единственный способ — учиться на своих ошибках.
Прежде всего, хотим извиниться перед всеми пострадавшими, и заверить, что подходим к этому вопросу с особой тщательностью. У нас несколько лет не было масштабных системных сбоев, и мы полны решимости гарантировать стабильную работу в ближайшее время.
Первым и самым маленьким шагом станет постепенный отказ от библиотеки BinaryPack и более тщательное тестирование всех сторонних библиотек в будущем.
Стала очевидной и более серьёзная проблема. Создание инфраструктуры внутри собственной экосистемы может привести к тяжёлым последствиям. Мы видели эффект домино на примере Amazon и надеялись, что с нами такого не случится, но сильно просчитались…
В настоящее время планируется полная миграция внутренних API на сторонний сервис. Таким образом, если выйдет из строя их система, то мы теряем только механизм обновлений. Но если наша система выйдет из строя, то будет возможность быстро и надёжно отреагировать, избежав эффекта домино, когда инфраструктура падает кирпичик за кирпичиком.
Также следует подумать, как устранить единую точку отказа в нескольких серверных кластерах из-за единственного файла, который в других случаях считается некритичным. Мы всегда стараемся постепенно развёртывать обновления, используя метод канарейки. Но этот случай застал нас врасплох, поскольку некритичная часть инфраструктуры стала критически важной единой точкой отказа для нескольких других кластеров.
Наконец, в самой системе DNS нужно хранить локальную копию всех бэкапов с автоматическим обнаружением сбоев. Таким образом, появляется ещё один уровень избыточности — все системы максимально независимы друг от друга, чтобы в случае сбоя не возник эффект домино.
Хочу поблагодарить ребят из техподдержки, которые работали без устали и держали всех в курсе событий, а также пользователей за терпение, пока мы решали проблему.
Понятно, что это очень стрессовая ситуация для наших клиентов. Поэтому мы стараемся извлечь уроки и в результате стать ещё более надёжным CDN, чем раньше.