13 октября мы провели вторую конференцию сообщества Uptime. В этот раз дата проведения выпала на пятницу 13-е, поэтому основная тема — аварии, и как с ними справляться. Это первый из серии постов про доклады с прошедшей конференции.
У меня есть три страшные истории о том, как по нашей вине все сломалось, как мы это чинили, и что мы делаем теперь, чтобы это не повторилось.
Масштаб: количество алертов
Мы работаем с 2008 года, нас сейчас 75 человек (Иркутск, Питер, Москва), мы занимаемся круглосуточной технической поддержкой, системным администрированием и девопсом для веб сайтов по всему миру. У нас 300 клиентов и 2000 серверов на поддержке.
Основная наша работа заключается в том, что если происходит какая-то проблема, мы должны за 15 минут прийти и исправить ее.
В 2010 году было порядка 450 алертов в месяц в пике.
Эта маленькая красная линия — это то, сколько алертов у нас было до конца 2012 года.
В 2015 году — в пике доходило до 100 000 алертов в месяц.
Сейчас их приблизительно 130 000 — 140 000.
На наших дежурных приходит около 400 алертов в час. То есть 400 сообщений от системы мониторинга, которые нужно расследовать. Это может быть что-то довольно простое: к примеру, заканчивается место на диске; а может быть что-то сложное: все упало и ничего не работает, и нужно понять, что вообще случилось.
В «черную пятницу» у нас доходит до 900 алертов в час, хотя интернет магазины готовятся к этому событию и предупреждают администраторов. Три года назад «черная пятница» проходила в пятницу. Два года назад магазины решили обхитрить друг друга и сделали «черную пятницу» в четверг, все вместе. В прошлом году это была среда, очевидно, что эта «черная пятница» будет во вторник и, в конечном счете, все пройдет по кругу. Магазины не любят говорить, когда именно это произойдет, поэтому хорошие магазины готовятся к нагрузочному тестированию, а другие хорошие магазины не говорят об этом вообще, а после приходят и говорят: «Здравствуйте, мы только что сделали рассылку на 300 000 человек, пожалуйста, подготовьте сервер к нагрузке».
Если готовить сервер к нагрузке второпях, то возникает куча проблем. Уметь быстро соображать в таких условиях — особое умение. Обычно люди хотят работать по плану, им нужно хорошенько обдумать то, что они собираются сделать. Но в нашем случае это больше напоминает хирургическое отделение на поле боя.
Аварии
Алертов много, поэтому ошибки неизбежны. И иногда в процессе исправления одной проблемы, можно создать гораздо большую.
Мы разделяем наши ошибки на три категории:
- Отсутствие процесса: случилась что-то, с чем мы раньше не сталкивались, что именно делать непонятно, пытаемся исправить на ходу — становится хуже.
- Ошибки в уже отлаженном процессе: с проблемой уже вроде бы знакомы, вроде бы понятно что надо делать, но не были предусмотрены все возможные варианты.
- Ошибки взаимодействия: вроде бы процесс отлажен, но есть проблема коммуникации между людьми.
И у меня есть страшная история по каждому пункту.
Отсутствие процесса
Первая — одна из самых страшных историй, которые с нами происходили. Она случилась 31 марта 2016 года. К нам пришел клиент на поддержку, с 2 ТБ базой данных в MySQL без единого бэкапа, с 70 сотрудниками, которые работали на этой базе. Она была довольно сложной: где-то 300 ГБ на одну таблицу, сотни миллионов записей в таблицах. Вся компания работает только потому, что эта база существует.
Отдельная проблема — предыдущие администраторы строили flashcache на диске и иногда файлы удалялись, иногда нет, происходило что-то странное.
Первой и самой главной задачей было создать бэкап базы, потому что если с ней случится хоть что-нибудь, то компания просто перестанет работать.
У базы нет слейва и люди работают с 9 до 18 с этой базой очень плотно — работу останавливать нельзя. В базе есть 300 ГБ MyISAM таблиц и xtrabackup, который хорошо бэкапит InnoDB, но лочит все на моменте бэкапа MyISAM. То есть мы сначала пытались запустить xtrabackup и посмотреть что будет. Xtrabackup заблочил MyISAM таблицы, сайт лег, все перестало работать.
Мы отменили запуск xtrabackup и стали думать что делать. У нас есть xtrabackup, который хорошо работает с InnoDB и который плохо работает с MyISAM. Но MyISAM в данном случае оказался не так уж и нужен в самом бэкапе. План был такой: мы запустим xtrabackup вручную без MyISAM части. Перенесем данные на слейв, со слейва поднимем еще один слейв, который будем просто дампать копированием.
Мы коллективно обсудили такой вариант действий, но никак не могли решиться. Все звучало разумно, кроме того, что мы так никогда не делали.
В два ночи я сам запустил xbackup, распотрошив бэкап так, чтобы он не делал ничего связанного с MyISAM и просто переливал данные. Но, к сожалению, в тот момент не все наши администраторы знали, что когда xtrabackup работает (по сути, это такой дампер MySQL), он создает временный лог, и довольно хитро – он создает его как файл, который открывает на чтение и запись, и немедленно удаляет. На диске этот файл найти нельзя, но он растет и растет. При этом xtrabackup его не стримит на другой сервер. Соответственно, если записей очень много, то место на диске быстро кончается. Об этом к нам в 16 часов пришел алерт.
На сервере стало мало свободного места, и админ пошел разбираться, что происходит. Он увидел, что место заканчивается, а чем оно забито – непонятно. Зато есть xtrabackup, у которого есть «deleted file», который имеет к этому какое-то отношение. И решил, что это удаленный лог, случайно открытый xtrabackup’ом и нужно бы его занулить.
Админ написал скрипт, который читал файлы-дескрипторы, открытые xtrabackup’ом, и занулял все файлы с пометкой «deleted». Запустил скрипт в 18:00, и сайт немедленно упал.
К 18:30 мы понимали, что MySQL не поднимается и не отвечает. В это время я ехал на машине из Новосибирска, где я был на конференции, к друзьям в Барнаул. С друзьями я посидел буквально пять минут, потому что мне позвонил клиент и сказал, что в результате безобидной вроде бы операции, внезапно лег сайт. Я заглянул в чат админов. И увидел там фразу: «Ну, мы же не убили им базу». Ответ был: «Да, убили. И возможно с концами».
Админ, запуская скрипт, зануляющий уже предписанные файловые дескрипторы, запустил его по pid MySQL и убил ibdata, которая весила 200—300 ГБ.
После небольшой паники я пришел к клиентам и сказал что произошло. Это был трудный разговор. К 19 часам мы поняли, что xtrabackup успел перелить ibdata.
В MySQL есть старая структура данных, когда все лежит в одном файле в ibdata, и есть отдельная новая структура InnoDB, где таблицы лежат в отдельных файлах. В ibdata, к сожалению, по-прежнему лежат «last sequence numbers», то есть MySQL запускается, смотрит в каких позициях в файлах лежат данные, идет туда и тогда все хорошо, если ibdata нет – MySQL не запускается. Вообще.
У нас была перелитая на горячую ibdata, мы пытались просто подсунуть ее, но MySQL data recovery с этой таблицей работать отказался. Понятно было что наверное что-то сделать можно, но что именно – непонятно.
Мы позвонили в известную компанию, которая связана с MySQL, и, в том числе, занимается восстановлением данных. Мы сказали, что у замечательная ситуация: есть 2ТБ база с 300GB таблицами и убитой ibdata. Есть еще отдельная ibdata, которая скопирована на горячую и мы бы очень хотели, чтобы они попытались восстановить эту базу. Нам ответили, что посмотреть можно, но это стоит $5 000. Поскольку косяк был страшный, я спросил, куда платить, после чего оказалось, что $5 000 — это fuck off money этой компании, работать они все равно отказались. Как я потом узнал, когда мы описали всю проблему, ребята из этой компании долго спорили, сможем ли мы восстановить эту базу.
К 21 часу мы нашли блог человека по имени Александр Кузьминский, который до этого тоже работал в компании, куда мы обратились. Он очень крутой, я его недавно видел, 50 раз сказал ему спасибо. В его блоге было написано, что если вы случайно удалили ibdata, и при этом у вас есть скопированная на горячую ibdata, вы можете ее поставить на место, запустить MySQL под gdb, и во время запуска оперативно в памяти менять неправильные значения «last sequence numbers» на правильные.
Нам очень хотелось вернуть базу, потому что все предыдущее время до этого я думал, что мы только что уничтожили компанию, в которой работает 70 человек. В итоге мы попробовали сделать как было написано, и оно запустилось. К сожалению, MySQL запускается в recovery mode и туда, естественно, ничего нельзя писать, да и вообще страшно. Поэтому мы решили, что базу надо задампать. На этот раз мы делали это MySQL-дампом. Поэтому следующие двое суток мы дампали потаблично всю базу, и надеялись, что все заработает. Заработало.
Мы решили, что отныне мы будем проводить анализ инцидентов.
Эмоций было очень много, но давайте рассмотрим все чуть более отстраненно.
Что именно случилось?
Дано:
2016-03-31
- Клиент пришел на поддержку без бэкапов БД
- Размер БД (MySQL) — 2ТБ, около 300гб на таблицу
- Нет слейва, работу останавливать нельзя
- 300гб MyISAM (лок xtrabackup)
План:
2016-03-31
- Запускаем xtrabackup вручную, без MyISAM части
- Переносим данные на слейв, поднимаем слейв со слейва
- Последующие бэкапы – остановка второго слейва
Жизнь:
2016-03-31 02:00 запуск xtrabackup
2016-03-31 02:00 — 2016-04-01 16:00 рост (deleted) redo-log-а
2016-04-01 16:00 алерт «мало места на диске»
2016-04-01 17:00 ответственный администратор не знает о redo-log-е, решает чистить (deleted) xtrabackup, создает скрипт для зануления file-handler-а с (deleted)
2016-04-01 18:00 ответственный администратор запускает скрипт
2016-04-01 18:00 сайт недоступен
Спасение:
2016-04-01 18:00 — 18:30 MySQL упал и не запускается
2016-04-01 18:30 зануленный file handler был ibdata процесса MySQL
2016-04-01 19:00 остался скопированный нагорячую ibdata в куске xtrabackup дампа
2016-04-01 20:00 компания data recovery MySQL отказывается работать в такой ситуации
2016-04-01 21:00 пост в блоге Кузьминского о восстановлении через gdb
2016-04-01 21:00 — 2016-04-02 03:00 попытки запуска, успешный запуск в recovery mode
2016-04-02 03:00 — 2016-04-03 06:00 MySQLdump
Почему это случилось?
Админ не понимал как работает xtrabackup, что создается TMP-файл, который может расти.
Не было чек-листа. Пытались сделать все, что приходило в голову, без всякого плана, потому что было уже не до этого. Я вмешивался и спрашивал почему до сих пор не готово.
Нестандартные операции, о которых не были проинформированы сотрудники. Кто-то запустил xtrabackup, а дежурный админ считает, что это работает какая-то базовая штука и почему-то заканчивается место.
Выводы
- Избегать нестандартных операций.
Если они происходят, то мы работаем только одной группой, и люди внутри группы должны знать, что именно происходит. - Непонятная проблема -— доложить менеджеру. Раньше, если возникала непонятная проблема на сервере, админы сами пытались с ней разобраться. Теперь, если почему-то заканчивается место, то админ должен сообщить менеджеру, что по неизвестной причине заканчивается место. Поскольку менеджер, возможно, проинформирован почему это происходит, возможно, знает, кто лучше справится с этой проблемой, или скажет, что админ может попробовать сам ее решить. Любая рискованная операция теперь требует двойного контроля: человек, который собирается что-то сделать, сначала говорит об этом, и только потом делает. Как второй пилот в самолете.
Проблемы, связанные с нарушением отлаженного процесса
В январе 2017 года был «кибер вторник». Это был наш второй большой косяк, не такой страшный, но тоже приятного мало.
Для подготовки к «кибер вторнику» один большой магазин утром решил прямо на продакшене устроить нагрузочное тестирование, чтобы узнать, где реально могут возникнуть проблемы. Это была хорошая идея — мы будем знать, где самое уязвимое место и проект будет готов к серьезным нагрузкам.
Дежурный админ в процессе утреннего и дневного тестирования сделал заметку к алертам, что страницы могут тормозить, страницы могут не отвечать, все нормально, это идет тест. И так и передал это следующей смене, которая пришла уже к вечеру «кибер вторника». В момент рассылки кэш страницы акции оказался отключен, туда повалил трафик, вечер и ночь сайт не отвечал.
Что именно случилось?
Весь «кибер вторник» магазин не работал.
Интересно, что тут очень сложно кого-то обвинить. Каждый по отдельности всё сделал правильно: первый админ отметил, что алерты летят потому, что идет нагрузочное тестирование, другой админ прочитал об этом и не стал ничего чинить, когда полетели алерты. Все было правильно, все соблюли процесс, все было хорошо. Но все в итоге оказалось плохо.
Почему это случилось и какие выводы надо сделать?
Админы передавали сообщения друг другу. Сейчас мы делаем так, что админы передают сообщения при подтверждении менеджера. Если есть какая-то причина не реагировать на критические оповещения — требуется подтверждение менеджера. При этом дежурный менеджер подтверждает все текущие сообщения системы мониторинга при передаче админской смены.
Ошибки процесса взаимодействия
5 октября 2017 года – третий наш большой косяк.
Сотрудник отдела разработки мониторинга попросил дежурного администратора выключить модуль на продакшн-сервере клиента. Продажи в мобильном приложении не шли шесть часов.
Что именно случилось?
Все было по протоколу, но теперь возникла ошибка взаимодействия.
Когда разработчик пришел и сказал выключить модуль на продакшене, админ решил, что если разработчик так уверенно это говорит, то, видимо, он уже спросил разрешения и у менеджера, и у клиента.
Разработчик решил, что админ — человек ответственный, можно его попросить выключить, а он спросит у менеджера и у клиента, и, если все нормально, то выключит.
В итоге этот модуль просто рубанули, никого не спрашивая. Все было довольно плохо.
Почему это случилось и какие выводы надо сделать?
Дежурный админ ожидал, что отключение согласовал разработчик, а сам разработчик думал, что отключение согласует админ.
Любое ожидаемое действие должно быть подтверждено. Не стоит надеяться, что кто-то другой спросит. Разработчику надо было свою просьбу направить через менеджера, менеджер подтвердил бы у клиента и передал админу.
Заключение
Ошибки неизбежны, любой может ошибиться. У нас очень плотный поток задач, между которыми, к тому же, надо постоянно переключаться. Мы стараемся учиться на своих ошибках и ни в коем случае их не повторять.
Большинство проблем уже случались раньше и для них есть готовые решения, но иногда происходит что-то непредвиденное. Чтобы лучше с этим справляться, в отделе поддержки мы выделили четырех тимлидов. Они давно работают, и мы знаем, что они совершают меньше ошибок. Все стандартные ситуации дежурная группа админов решает по стандартным протоколам, а если происходит что-то совсем непонятное, сообщают тимлидам, и они уже решают на ходу, вместе с клиентом.