Про бэкапы, черную пятницу и коммуникации между людьми: как мы накосячили и научились больше так не делать

Про бэкапы, черную пятницу и коммуникации между людьми: как мы накосячили и научились больше так не делать

13 октября мы провели вторую конференцию сообщества Uptime. В этот раз дата проведения выпала на пятницу 13-е, поэтому основная тема — аварии, и как с ними справляться. Это первый из серии постов про доклады с прошедшей конференции.

У меня есть три страшные истории о том, как по нашей вине все сломалось, как мы это чинили, и что мы делаем теперь, чтобы это не повторилось.

Масштаб: количество алертов

Мы работаем с 2008 года, нас сейчас 75 человек (Иркутск, Питер, Москва), мы занимаемся круглосуточной технической поддержкой, системным администрированием и девопсом для веб сайтов по всему миру. У нас 300 клиентов и 2000 серверов на поддержке.

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

В 2010 году было порядка 450 алертов в месяц в пике.

Эта маленькая красная линия — это то, сколько алертов у нас было до конца 2012 года. В 2015 году — в пике доходило до 100 000 алертов в месяц. Сейчас их приблизительно 130 000 — 140 000.

На наших дежурных приходит около 400 алертов в час. То есть 400 сообщений от системы мониторинга, которые нужно расследовать. Это может быть что-то довольно простое: к примеру, заканчивается место на диске; а может быть что-то сложное: все упало и ничего не работает, и нужно понять, что вообще случилось.

В «черную пятницу» у нас доходит до 900 алертов в час, хотя интернет магазины готовятся к этому событию и предупреждают администраторов. Три года назад «черная пятница» проходила в пятницу. Два года назад магазины решили обхитрить друг друга и сделали «черную пятницу» в четверг, все вместе. В прошлом году это была среда, очевидно, что эта «черная пятница» будет во вторник и, в конечном счете, все пройдет по кругу. Магазины не любят говорить, когда именно это произойдет, поэтому хорошие магазины готовятся к нагрузочному тестированию, а другие хорошие магазины не говорят об этом вообще, а после приходят и говорят: «Здравствуйте, мы только что сделали рассылку на 300 000 человек, пожалуйста, подготовьте сервер к нагрузке».

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

Аварии

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

Мы разделяем наши ошибки на три категории:

  1. Отсутствие процесса: случилась что-то, с чем мы раньше не сталкивались, что именно делать непонятно, пытаемся исправить на ходу — становится хуже.
  2. Ошибки в уже отлаженном процессе: с проблемой уже вроде бы знакомы, вроде бы понятно что надо делать, но не были предусмотрены все возможные варианты.
  3. Ошибки взаимодействия: вроде бы процесс отлажен, но есть проблема коммуникации между людьми.

И у меня есть страшная история по каждому пункту.

Отсутствие процесса

Первая — одна из самых страшных историй, которые с нами происходили. Она случилась 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-дампом. Поэтому следующие двое суток мы дампали потаблично всю базу, и надеялись, что все заработает. Заработало.

Мы решили, что отныне мы будем проводить анализ инцидентов.

Эмоций было очень много, но давайте рассмотрим все чуть более отстраненно.

📎📎📎📎📎📎📎📎📎📎