постмортем

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Мы в 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.

ФБ рассказал, почему они упали в понедельник.

Началось все с человеческой ошибки. В ходе обычной работы, кто-то дал системе команду, которая отключила все дата-центры Фейсбука от ее скоростной внутренней сети, которая связывает дата-центры Фейсбук друг-с-другом и со внешним интернетом.

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

В этот момент все сервера Фейсбука пропали с радаров интернета, Фейсбук для внешнего мира сломался.

Все было бы ничего, инженеры могли бы быстро включить все обратно, но у фейсбука есть специальная автоматизированная система, которая проверяет связность DNS серверов с дата-центрами компании и в случае проблем — отключает эти серверы от интернета. В понедельник, эта система отключила все DNS-серверы компании от интернета.

DNS — адресная книга интернета. Эта система переводит человеческий адрес Facebook.com в машинный айпи-адрес 157.240.224.35. Формально, интернет может работать и без DNS, в реальности на работе DNS завязано почти ВСЁ. Например, внутренние сервисы — инструменты, которыми пользуются инженеры фейсбука для решения проблем. Да что там сервисы, сотрудники фб в офисы не могли попасть, потому что автоматической системе контроля дверей тоже нужна DNS.

Дополнительная вишенка на торте — сломалась не только основная сеть фейсбука, но и запасная, которая построена специально для доступа к управлению сетевым железом в случае аварии основной сети. В общем, инженерам пришлось ножками топать в дата-центр и подключаться к сетевому оборудованию напрямую, буквально проводочком. Это непросто, потому что современные дата-центры — это крепости, попасть в них кому-то сверх обычного персонала — то ещё приключение. А теперь попробуйте это сделать, когда все корпоративные IT-системы недоступны. Подозреваю, что высшему руководству буквально по телефону приходилось подтверждать личность инженеров. Да и современное железо в ДЦ построено так, чтобы даже наличие физического доступа не дает контроля над ним — придется доказать, что ты не верблюд.

В общем, горячие были 6 часов у инженеров. Респект фб, что так быстро описали суть произошедшего и жаль, что подробный отчет, по которому, безусловно, можно снять боевик — мы вряд ли увидим.

Конкретно от этой проблемы фб вряд ли пострадает во второй раз — программу проверки команд теперь будут тестировать на порядок лучше, да и DNS в будущем, вряд ли будет отключаться так легко. При этом, мы говорим об очень сложных системах и в них рано или поздно что-то пойдет не так. Такие крупные аварии, «идеальные штормы» происходят каждые несколько лет. Этот — не последний.

Нам же, простым смертным, это очередное напоминание, что стоит подстелить соломки и сделать так, чтобы наши сервисы, наши бизнесы продолжали работать, не теряли клиентов, даже если сломался такой гранд, как вацап или фейсбук. Когда все твои конкуренты вне доступа из-за крупной аварии — это шанс получить много новых клиентов, если ты продолжаешь работать. Хоть и баян, но: кризис — время возможностей.

Помните, на прошлой неделе Cloudflare упал и уронил половину интернета?

Они пишут одни из лучших post-mortem’ов в индустрии. Последний — не исключение.

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

Но самое впечатляющее для меня в этой истории — вот этот комментарий пользователя eastdakota на форуме hacker news.

Это Мэтью Принс, основатель и генеральный директор компании, которая обслуживает 20% всего интернет-трафика, рассказывает, как он сначала сидел на созвоне по починке аварии, а потом пригласил к себе домой бывшего техдира (тот захватил сына, показать, какая у папы работа) и главного юриста компании и они на троих сообразили текст в гугл-доке. Задали в нем вопросы технарям компании. Заказали еды. Включили ответы на вопросы в текст. Дали вычитать технарям. И опубликовали. И получился пост-мортем. ❤️

Поведение при факапе - отдельное искусство.

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

Твит про это капитально бомбанул, на ситуацию обратил внимание основатель компании и вот Digitalocean публикует образцовый постмортем.

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

5/5

P.S. Ещё одно напоминание об опасности держать все яйца в одной корзине. Как минимум бэкапы должны быть у второго провайдера.

Очередной шедевр от Cloudflare — подробный отчет об аварии 2 июля.

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

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

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

Basecamp уже несколько часов в read-only. У чуваков переполнились первичные ключи в таблице в базе (были в int, нужно было bigint).

Работы всё ещё идут, но они ведут идеальный status report и уже написали два детальных объяснения (сначала покороче и потом подлиннее), что идет не так, почему так получилось и что они делают для починки. ИДЕАЛЬНО.

У Амазона лежал сайт сразу после начала дня скидок Prime Day. Тонны денег вложены в рекламу, за 40 часов Амазон планирует продать товаров на 4 миллиарда долларов и сайт сломался. Не боги горшки обжигают.

Жаль, что post mortem вряд ли появится в публичном доступе :(

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

Не забывают по пути объяснять, какие они молодцы и как у них все правильно устроено. Качественный PR.

Яндекс выкатил пресс-релиз на Роеме. В таймлайне не указано, когда они уведомили пользователей о проишествии, а ведь поддержка — один из параметров, по которому мы выбираем хостинг.

«Мы уже работаем над формированием мер для предотвращения повторения подобного инцидента в будущем и в ближайшее время проинформируем о дальнейших шагах всех пользователей.»

Интересно, будет ли более подробный post mortem в этом информировании?

P.S. А ведь было время, когда Яндекс говорил отличным русским языком; помню, студентом мечтал там работать в том числе из-за языка на сайте (древнегреческое «красивый не может быть плохим»). Эх.

Upd: ну наконец-то приличный текст от руководителя Яндекс.Облака. Был бы я журналистом — продолжил бы долбить про «считаете ли вы нормальным писать пользователям об удалении их сервера через 6 часа, а не сразу же», но думаю, что эта история и так заняла слишком много внимания и нечего так напрыгивать на национальное достояние. ❤️ спокойной ночи