История не запланированного переноса сайта в другой ДЦ

в 8:18, , рубрики: nginx, восстановление, Песочница, сисадмин, хостинг, метки: , , ,

Однажды, в один из первых теплых весенних дней, по независящим от нас обстоятельствам, мы остались без доступа к нашим серверам в ДЦ, на неопределенный срок. Не беда, мы были в категории тех, кто уже делает бекапы. Но, к сожалению, еще не выросли до тех размеров, когда у нас есть резервный кластер в другом ДЦ. Я хочу поделиться личным опытом, не запланированного переезда большого проекта. Должно быть интересно, тем у кого более одного выделенного сервера на проект в одном ДЦ. В статье нет подробных конфигов или технический решений, но присутствует здравый смысл. И надеюсь на обсуждение в комментариях, как бы вы поступили, в подобной ситуации.

Входные данные
1. В данном проекте используется 10 серверов, которые стоят в одном ДЦ. Сервера с nginx, PHP, MySQL. Без полноценного почтового сервера и других каких-либо сервисов, достойных упоминания.
2. Также имеется 1 сервер в другом ДЦ, для резервной копии, куда синхронизируем файлы, а также настроена репликация для базы данных.
3. На сайте больше 2-х миллионов просмотров страниц в день. Ждать восстановления работы сложа руки мы не могли.

В момент сбоя, у нас было:
1. Резервный сервер настроен для проверки работоспособности, а конфигурационные файлы под репозиторием, с актуальным состоянием базы. А отставание синхронизации файлов, согласно мониторингу, никогда не было больше 20 минут;
2. Настроенную SOA запись DNS зоны, что позволяет в течении 1 часа, почти для всех пользователей в Интернет сменить настройки DNS зоны. Не считай проблем с Windows машинами, которые кэшируют DNS записи сами, а также DNS провайдеров и офисов, которые иногда кэшируют записи по своим таймаутам.

План действий
Восстановить работу сайта, только для чтения, кэшируя все и на «вечно». Заказывать новые сервера, чтобы восстановить работу сайта в полном объеме. Пока получим сервера, сайт не потеряет в выдаче, а посетители смогут просмотреть содержимое, без возможности оставлять комментарии, залогиниться и другого.

«Минусов» получилось больше, но наличие бекапов многое перекрывает. Как мы думали, вероятность остаться без 10 серверов сразу, мизерна. Так, что через час мы не заработали стабильно. Сейчас перечислю список не учтенных моментов, а после как их можно было избежать:
1. Конфиги nginx. Рабочие конфиги резервного сервера, не обновлялись так же регулярно как на главном. В результате получили часть URL с ошибками, а часть страниц не кэшировались;
2. Кэш, пустить на 1 сервер вместо 10, «голодных» посетителей без кэша, смертельно. Особенно в сумме с предыдущим пунктом;
3. В процессе переключение, может оказаться, что и проект не совсем готов к режиму «только чтение». Страницы, что уже в кэше нужно исправить, а после исправлений программиста нужно почистить кэш, не в коем случае не соглашайтесь удалять весь кэш, созданный с таким трудом. Каждую минуту, все больше пользователей получают новый IP и количество посетителей на сайте только растет. Чистка кэша спустя час, после смены DNS, положить сервер.
4. Вряд ли какой-либо ДЦ сможет предоставить мощные выделенные сервера, тем более больше одного, за несколько часов. Так что при наличии всех резервных копий, вы все равно, не сможете оперативно начать восстанавливать сайт в полном объеме, если не позаботитесь об этом заранее.

Что можно было сделать лучше и раньше, а мы делали на лету
К первому пункту. Вторая истина про резервные копии, если вы делаете резервные копии, это не значит, что они полностью рабочие. В данном случае эта проблема была с конфигами nginx. Анализ логов, и быстрые правки конфигов, для режима «только чтение». Отдавать пользователям культурное сообщение, о невозможности авторизоваться, оставить комментарий и прочие действия на запись, на уровне nginx, не пуская пользователей до PHP. В данном случае return 503 в необходимых местах. И error_page 503 = /trouble.html. Также исправили ошибки, чтобы кэшировать все остальные страницы.

По 2 и 3 пункту, возникло следующее решение. Сделать так, чтобы мой IP, был в приоритете и каждый запрос вместо 504 ошибки, гарантировано создавал страницу в кэше. А при необходимости, обновлял страницу в кэше. Не переживая за производительность nginx, так как нужно было, хоть немного оживить сайт, смело использовал Evil If, чтобы для нашего IP, кэш генерировался в обход остальных посетителей. В моем случае это выглядело так
fastcgi_pass unix:/var/run/php-fpm/fpm-all.sock;
if ( $remote_addr = 8.8.8.8 ) {
#if ( $remote_addr ~ (8.8.8.8|127.0.0.1) ) {
fastcgi_pass unix:/var/run/php-fpm/fpm-private.sock;
#set $nocache 1;
#fastcgi_cache_bypass $nocache;
}

Вместо 8.8.8.8 подставляем свой IP. Кроме этого, у меня было два пула PHP-FPM, fpm-private — для меня, fpm-all для остальных.
Для обновления кэша использовал директиву fastcgi_cache_bypass.
Для создания кэша запустил wget -r -l0 -np — example.com. Для обновления кэша, раскомментировал строчки с $nocache. Таким образом я получил рабочий сайт для себя. С возможностью генерировать кэш и обновлять его при необходимости со своего IP. После несколько часов работы, было уже пару десятков гигабайт кэша.

Вопрос оптимизации настроек сервера почти не затрагиваю, подобные темы открыты в отдельных статьях. В данном случае запросы к базе были только на чтение, так что тюнинг MySQL был прост, и база не была узким местом. Настройка nginx, свелась к корректировке таймаутов и буферов для обработки всех подключений. Была хорошая нагрузка на сеть, так как не было больше CDN. Но слабым местом был PHP. Даже после генерации большого кэша, страниц которых там не было отдавались по 20 секунд, так как была очередь в PHP-FPM.

Касательно последнего пункта, руководитель решал вопросы насчет получения новых серверов, поэтому мы занимались целиком резервным сервером, так как развернуть полноценно сайт, банально не было где. Решить эту проблему нам не удалось. Все ДЦ, максимум предлагали простые сервера с core i3, 8Гб ОЗУ на борту, и это на следующие сутки — «постараемся сделать завтра, как можно раньше». Из вариантов, нужно заранее договариваться с резервным ДЦ о возможном предоставлении дополнительных серверов в случае выхода из строя основного. Или поступать еще мудрее и масштабировать сайт более чем на один ДЦ, что мы теперь и собираемся сделать.

Подводя итоги
1. Без резервных копий жить нельзя, проверять их стоит регулярно мониторингом, руками и чем угодно. Тут лишней осторожности не бывает.
2. Проверка резервной копии должна быть в полном объеме. В нашем случае не хватало нагрузочного тестирования, опять же по причине, что мы не верили в подобную ситуацию.
3. Найдите время, чтобы собраться с командой проекта или архитектором и админами, чтобы смоделировать самую маловероятную ситуацию — взрыв, пожар другие обстоятельства в ДЦ, когда вы в момент лишаетесь доступа к серверам. Разбор, а в результате документация для такого случая, и подготовка реальных конфигов с тестированием их работы, позволить покрыть, большинство, даже более вероятных сбоев. И в случае прилетевшего НЛО за вашими серверами, вы не будете говорить, что не ожидали такого и сможете восстановить работу проекта.
4. Сайт был полностью недоступен чуть более часа. Еще несколько часов были большие перебои. Подготовка к подобной ситуации позволила бы потратить первый час на генерацию кэша, чтобы встретить нормально первых посетителей и в дальнейшем не ложится намертво под нагрузкой.

P.S. В нашем случае ДЦ восстановил работу чуть больше чем через сутки. Учитывая, что мы работали в режиме только чтение, никаких данных обратно переносить не пришлось. После проверки серверов, мы перевели обратно домен. Я специально, старался не акцентировать внимания на ДЦ и причины нашей поломки, как и названия ДЦ, дабы не отвлекаться от темы.
Жду ваших комментариев.

Автор: saharchuk


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js