авария

Ходят слухи, что да, налили ошибочную конфигурацию на роутеры. Починить трудно, потому что люди, имеющие физический доступ к железу (сотрудники дата-центров) не имеют ключей доступа, а те, у кого есть ключи — находятся далеко от дата-центров.

Жуткая ситуация, когда сам себе отключаешь доступ к удалённому серверу. Каждый сисадмин хоть раз в ней был.

Представляю, какой ад там сейчас творится.

Половина сайтов в интернете не работают, потому что сломался один из крупнейших CDN — fastly.

Задело Амазон, Нетфликс, Бибиси, сайты правительств и многих других.

Через этот сервис сайты отдают статические картинки, файлы стилей и жаваскрипты.

Удивительная на самом деле ситуация: основные сервера всех сайтов кроме fastly работают отлично, но без картинок, стилей и скриптов, подгружаемых через fastly, пользоваться сайтами невозможно.

Отдаём мы эти файлы через fastly для того, чтобы они загружались у пользователей максимально быстро. У фастли тысячи серверов по всему миру, так что обычно, картинки через них отдавать в разы быстрее, чем самому.

В Fastly работают настоящие профи, так что будет очень интересно почитать, почему они так капитально сломались.

3 минуты назад написали, что нашли причину и чинят. Ждём.

Текущий статус тут https://status.fastly.com/incidents/vpk0ssybt3bj

Один из крупнейших интернет-маркетплейсов страны Wildberries не работает вторые сутки и не называет ни причину падения, ни сроки, когда проблемы будут исправлены.

Главная страница открывается, но пропали все данные о прошлых заказах, нельзя оформить новый заказ, в личном кабинете не отображается даже имя пользователя.

Учитывая, что сами они ничего не говорят, предположу, что компания потеряла большую часть базы данных из-за аварии или хакерской атаки и пытается восстановить данные из бэкапов.

Проверяйте бэкапы, это дешево, могу помочь! И зовите меня с Федей, если вдруг авария, в которой не можете разобраться, у нас есть опыт тушения пожаров (дорого).

Отдельно обращу внимание на отвратительную внешнюю коммуникацию. Берите пример с Cloudflare, они хорошо объясняются, когда что-то идет не так.

Гугл опубликовал пост-мортем по позавчерашнему падению. Обычные ошибки, только на инфраструктуре планетарного масштаба.

У них есть внутренний сервис, который проверяет доступы (бабки, квоты и т. д.) перед тем, как API запрос доходит до любого продукта.

Эта программа берет из специальной глобальной базы данных правила, по которым проверяет каждый запрос и отвечает, пропускать его или нет.

В эту программу добавили поддержку нового типа квот. Программист допустил небрежность в новом коде и не проверял, насколько корректно записано это правило в базе, перед тем, как пытаться положить его в память. Обращение к несуществующей памяти — смертный грех, за такое программа мгновенно завершается (если программист не предусмотрел, что такое может случиться, а это не наш случай). При этом я бы не назвал это ошибкой, все мы люди, мы не идеальны и поэтому придумываем механизмы защиты от своей природы. В этом суть инженерного подхода.

Экземпляр этой программы работает в каждом регионе Гугла. Так как это серьезный, ключевой сервис, его выкатывают не во все регионы сразу, а по одному, внимательно отслеживая, не внесли ли программисты новые ошибки.

Более того, весь новый функционал специально помечают и сначала запускают только для внутреннего пользования, чтобы, даже при наличии ошибки, она не задела внешних клиентов. Этот механизм называется фича-флагами.

К сожалению, программист забыл настроить фича-флаги для этого кода. Кусочек программы с ошибкой запустился на всех пользователей сразу. Удивительно, что это не заметили на этапе code review!

Итак, проходит время, и вот программа с ошибкой запущена во всех регионах для всех пользователей. Кто-то добавляет в базу данных новое правило с новым типом квот, с пустым полем. Эта запись в течение десятков миллисекунд копируется во все регионы, и в каждом регионе программа проверки считывает новое правило, пытается обратиться к несуществующей памяти, падает, перезапускается и снова падает.

Тут в дело вступает, на мой взгляд, первая ошибка (а не просто человеческая небрежность) инженеров — система контроля доступа настроена так, что при отсутствии ответа от программы проверок она отклоняет запрос. Так называемый fail closed. Хорошо для замков на банковских сейфах, плохо для пожарных выходов.
В нашем случае система не пропускает ни один запрос.

Дежурные инженеры замечают проблему в течение 2 минут, за 10 минут находят причину (дежурная система и дежурные инженеры у Гугла достойны восхищения) и нажимают большую красную кнопку, которая должна выключить эту часть программы (ее программисты сделали). Ее включение занимает еще 30 минут. (Не понятно, почему этот механизм занимает 30 минут, а не 20 миллисекунд, но движемся дальше).

Система заработала, но из-за того, что она лежала 40 минут, накопилось много желающих отправить запрос еще раз, и они создали эффект толпы, которая набежала и перегрузила остальные соседние сервисы через наш сервис проверок. Оказалось, что он не ждет какое-то время, если нужный сервис отказывается ответить на запрос (для этого есть красивая схема exponential back off), а долбит до упаду, тем самым не давая системе возможности восстановиться. Пришлось руками ограничивать число запросов. На постепенную, ручную разгрузку очередей ушло еще 2 часа.

Ко всему прочему, Гугл час не мог опубликовать уведомление о проблеме, потому что сервис публикации статус-страниц зависит от системы, которая упала.

Как вывод, Гугл обещает пройтись по всем сервисам и убедиться, что они, во-первых, fail open, то есть пропускают запросы, когда падают, во-вторых, реализуют exponential back off, если на их запрос не отвечают, а не добивают лежачего, и, наконец, в-третьих, что даже глобальные добавления правил должны прилетать во все регионы не сразу, а с некоторыми задержками. Ещё обещают добавить эти проверки в свои статические анализаторы кода, завидую!

Первые два пункта можно и нужно использовать в каждом проекте, даже если ты не Гугл.

Обрыв двух независимых 20kV линии питания и всей оптики до основных площадок обмена трафиком в Европе — не очень частая ситуация. Тем более хороший повод повторить основные правила.

Идеальная схема — когда запросы идут параллельно на две площадки у двух не-аффилированных провайдеров (не два ДЦ у одного и того же провайдера, а прямо разные компании). Админ в Букмейте был из старой гвардии Яндекса и поддерживал такое. В таком сетапе падение одного провайдера проходит незаметно для читателей. Это обычно сложно технически и стоит денег по ресурсам.

Чуть похуже — горячая замена (опять же у отдельного провайдера). Это когда есть копия полностью рабочего сервиса, которая стоит ждет своего времени. В этом случае вы упадете, но минут на 10. Это проще технически, но стоит денег — половина железа «простаивает».

Уровень пониже – иметь систему, позволяющую быстро развернуть сетап у другого провайдера. Договор или аккаунт с нормальными лимитами, система управления конфигами типа ansible и тд и тп. Ну и свежие бэкапы, конечно же. В этом случае ожидаемый простой — часы.

В противном случае – молимся, постимся и слушаем радио Радонеж при каждом падении.

Сервис общего редактирования документов и командной работы Notion упал из-за DNS. Что происходит пока не понятно, но 3 минуты назад они попросили у себя в твиттере «у кого есть контакты name.com». 😲

Текущая оценка Notion — 2 миллиарда долларов.

Upd: починили, ждем постмортем 🍿

Мы в iGooods лежали почти полдня. Стыдно! Зря я угорал вчера над утконосом, что они упали. Поделюсь честно, от чего мы лежали. Это подробный постмортем аварии с техническими подробностями, мама, извини.

Из-за коронавируса к нам начали приходить в 2-3 раза больше клиентов, чем обычно. Плюс у нас на днях запускается два новых партнерства — с Joom и с магазинами Лента. Серверы работали на 40-60 процентах емкости и мы решили «добавить железа». В 6 вечера мы налили пару новых машин в кластер приложений, в час ночи по Москве — перетащили базу на новую, ультра мощную тачку. Обе операции — необычные для iGooods, множество вещей делалось руками. Ошибка №0 — мы сделали 2 крупных изменения близко друг с другом

В 7 утра по Москве, сервер базы данных начал плавиться от нагрузки в процессор. Это компьютер с 70 ядрами, но базе нужно было минимум 300. Запросов было вроде бы не сильно больше, чем обычно, но занимали они всё больше времени. Люди просыпались у себя дома и начинали делать заказы — сервера умирали, сайт не открывался, приложения выдавали ошибки. Самое опасное — курьеры и сборщики заказов выходили на работу и не могли работать.

Мы, конечно, думали, что сможем быстро починить проблему. Через час стало понятно, что нужно хотя бы временное решение. Мы выключили все пользовательские интерфейсы iGooods, оставив рабочей только админку и внутренние приложения курьеров и пикеров (сборщиков заказов). Ошибка №1 — в случае аварии не нужно пытаться «сделать хорошо», нужно определить критичные сервисы и восстановить их первым делом.

Мы решили, что проблема в новой базе данных. Мало ли, конфигурация, железо, да хоть драйверы. Попытались вернуться на старый сервер. Мы не сохранили WAL логи между переездами, так что вместо 3 минут эта операция заняла 40 минут — пришлось перегнать всю базу данных между серверами. Мы планировали откат для приложений, но не для переноса базы — он нам казался довольно безопасной операцией. Ошибка №2 — мы решили, что «уж тут-то не взорвется», на самом деле вместе с любым изменением нужно продумывать пути отката.

Возвращение на старый сервер базы данных не помогло. Каждый раз, когда мы включали пользовательские приложения — база данных мгновенно уходила в несознанку и работа бэкофиса парализовалась. Сайт и мобильные приложения к тому моменту лежали уже больше нескольких часов. Самое страшное — мы всё ещё не были уверены, что проблема не в базе данных.

В конце концов, Женя случайно заметили ошибку, что наше rails приложение не может записать в redis-кеш. BINGO! Вот тут всё наконец-то встало на свои места. В нашем приложении есть много страниц, которые собираются очень долго. Все они кешируются rails'ами в redis. И вот этот редис кеш у нас отвалился на запись на части серверов приложений из-за кривых настроек окружения (душераздирающие подробности приложены картинкой). Кеш протухал постепенно и с каждой потерянной записью все больше тяжелых запросов грузили Postgres. Ошибки №3, 4 и 5: настройка тачек производится руками, не кодом; логи переполнены, так что сложно заметить новую ошибку; не все важные сервисы (redis, rails cache) включены в мониторинг.

Как вы можете видеть, всё довольно банально. Будь у нас настроена нормальная рабочая среда — не было бы такой аварии.

Итак, чего нам не хватило и что мы приведем в порядок:
- инфраструктура в коде (полный ansible вместо хождения руками на серверы);
- хороший, чистый мониторинг всех ключевых метрик приложения, APM — за день до аварии мы включили Datadog, но ещё не было нормальных дэшбордов и исторических данных;
- сообщения об ошибках (у нас bugsnag) засраны нерелевантными сообщеними — их нужно почистить.

Мы с Федей обозначили проблемы в первые же дни, но не успели решить их — были вещи поважнее. Знал бы прикуп — жил бы в Сочи.

Если у вас похожая ситуация — рекомендую навести порядок заранее, не ждать форс-мажора.

Ну и делать много сложных правок вместе — чревато. Стоило разнести перенос базы и деплой новых машин на день — тогда бы мы не потратили так много времени на ложный след тормозной базы.

Fin.