Учебный центр на Дмитровском шоссе, 13 рабочих мест, почта на Zimbra с 2019 года. Бэкап у них шёл каждую ночь и ни разу не падал. В апреле 2023 я предложил проверить его единственным честным способом: взять чистую машину, поднять на ней почту из архива и засечь секундомер. Мы уложились в 6 часов 12 минут вместо ожидаемых двух. Рассказываю, куда ушла разница.
Учение по восстановлению Zimbra: развернуть с нуля за шесть часов
Спросите админа, когда он последний раз восстанавливался
Задайте своему администратору один вопрос. Не «делаешь ли ты бэкап», а «когда ты в последний раз поднимал из него почту». На отдельной машине. С секундомером. До момента, когда в браузере открылась чужая входящая с письмами за позапрошлый год.
Ответ почти всегда один: «бэкап идёт каждую ночь, ошибок нет». Это ответ на другой вопрос. Ночная задача проверяет, что архив пишется. Она ничего не говорит о том, соберётся ли из этого архива работающий почтовый сервер и сколько часов на это уйдёт. Между «файлы лежат» и «люди читают почту» помещается целый рабочий день, о котором никто не знает заранее.
Я не люблю пугать. Поэтому предлагаю клиентам не разговор, а процедуру: раз в год берём виртуалку, поднимаем на ней почту из вчерашнего архива и записываем время. Час работы моего инженера против неизвестности — по-моему, честный обмен.
Дальше — журнал одного такого учения, минута в минуту.
Апрель 2023, учебный центр на Дмитровке: что было в схеме и правила учения
Клиент — учебный центр дополнительного образования на Дмитровском шоссе. 13 рабочих мест в офисе, ещё десяток преподавателей приходят на занятия. Почта на Zimbra 8.8.15 Open Source, CentOS 7.9, виртуалка на своём гипервизоре. Сервер поставили в 2019 году, с тех пор он ни разу не падал — и именно поэтому его никто не проверял.
Хозяйство небольшое:
- 19 ящиков, из них четыре общих:
info@,kursy@,buh@,hr@; - store — 174 ГБ, индекс — 11 ГБ, база — 3,2 ГБ;
- бэкап: ночной
rsyncвсего каталога/opt/zimbraна отдельный NAS плюс еженедельный tar-архив; - журнал заданий чистый за 14 месяцев подряд.
Заявки на курсы у них приходят на info@. За день — 10–14 писем, из них примерно каждое четвёртое доходит до оплаченного курса со средним чеком около 26 000 ₽. Сутки без почты стоят им порядка 70–90 тысяч рублей, и это без учёта преподавателей, которые не получат расписание. Цифру мне назвал сам директор, я её только поделил на дни.
Схема выглядела прилично. Дальше выяснилось, чего в ней не хватало.
Правила, которые я не нарушаю
Учение имеет смысл только тогда, когда оно похоже на аварию. Поэтому правила я задаю жёсткие и сам их не нарушаю.
- Новая виртуалка, пустой диск. Ничего с боевой машины не подсматриваем.
- Работает инженер, который этот сервер не ставил. Автор установки может подсказывать только на разборе, после финиша.
- Пользуемся ровно тем, что лежит в бэкапе. Если чего-то там нет — значит, в аварии этого тоже не будет.
- Секундомер запускается в момент, когда инженер получает доступ к архиву. Останавливается, когда в веб-почте открывается ящик
buh@и в нём видно письмо годичной давности.
Последний пункт важнее, чем кажется. «Служба запустилась» и «человек читает почту» — разные события, между ними обычно ещё минут сорок.
Старт — 10:00, четверг. Инженер получил адрес NAS и учётку на чтение. Больше ничего.
10:00–11:35. Та же версия на той же ОС
Перенос Zimbra на другой сервер работает по простому правилу: целевая машина должна получить ту же версию продукта и ту же операционную систему. Попытка сменить дистрибутив или мажорную ветку «в лоб» ломает установку — проверено многократно, и не мной первым.
Инсталлятор ставится без мастера конфигурации, флагом -s: конфиг всё равно приедет из архива, спрашивать нечего.
# целевая машина, root
hostnamectl set-hostname mail.example.ru
vi /etc/hosts # 10.20.0.61 mail.example.ru mail
tar xzf zcs-8.8.15_GA.tgz
cd zcs-8.8.15_GA
./install.sh -sИ здесь учение сразу дало первый результат. Точной версии в бэкапе не было. Нигде: ни файла, ни записи в вики клиента, ни комментария в задании. Инженер полез в скопированный /opt/zimbra, нашёл версию в служебных файлах установки и только после этого пошёл искать дистрибутив. Двадцать две минуты на то, чтобы выяснить, что именно мы восстанавливаем.
В настоящей аварии эти двадцать две минуты были бы дороже: искать пришлось бы под телефонные звонки.
11:35–12:57. rsync, права и то, чего я не угадал
До учения я был уверен, что узким местом окажется копирование. 174 ГБ по гигабитной сети, NAS не самый быстрый — думал, часа полтора-два, и это будет основная строка расхода.
Копирование заняло 53 минуты — с ночного зеркала, каталог которого назван вчерашним числом: rsync у них стартует в 23:20, до полуночи.
Моя версия оказалась неверной, причём с запасом. Всё интересное было дальше.
su - zimbra -c '/opt/zimbra/bin/zmcontrol stop'
rsync -avr --numeric-ids /mnt/nas/zimbra-2023-04-12/zimbra /opt
# от root, обязательно после переноса
/opt/zimbra/libexec/zmfixpermsПро --numeric-ids я добавил уже по опыту: UID и GID пользователя zimbra на старой и новой машине совпадают далеко не всегда, а при расхождении права на файлы приезжают неверными и служба потом ведёт себя необъяснимо. zmfixperms лечит многое, но не подменяет проверку. Пятнадцать секунд на id zimbra с обеих сторон экономят вечер.
Дальше — установка поверх перенесённых данных. Инсталлятор видит существующий каталог и предлагает не установку, а обновление. На это надо соглашаться: именно этот шаг сшивает конфиги с данными.
К 12:57 служба стартовала. Почти вся.
12:57. Каталог не поднялся
LDAP не запустился. В логе — вот это:
slapd[3184]: mdb_db_open: database "": mdb_env_open failed,
MDB_CORRUPTED: Located page was wrong type (-30796)
slapd[3184]: backend_startup_one (type=mdb, suffix=""): bi_db_open failed! (-30796)
zmconfigd: Unable to determine enabled services from ldap.Причина скучная и типовая. Ночной rsync копировал каталог целиком, вместе с директорией mdb, — то есть таскал файлы живой базы на работающем сервере. Иногда так везёт, иногда нет. В этот раз не повезло.
Главное здесь: база mdb не чинится на месте. Никаким инструментом. Единственный рабочий путь — выгрузить содержимое в LDIF, создать новую пустую базу и залить дамп обратно. Инструменты Zimbra для этого свои:
# на учебной машине: смотрим, что с базой каталога
su - zimbra
ldap stop
mdb_stat -e /opt/zimbra/data/ldap/mdb/db
exit
# на боевом сервере: снимаем LDIF
su - zimbra -c '/opt/zimbra/libexec/zmslapcat /tmp/ldapdump'
# от root: убираем битую базу, создаём чистую
mv /opt/zimbra/data/ldap/mdb /opt/zimbra/data/ldap/mdb.broken
mkdir -p /opt/zimbra/data/ldap/mdb/db
chown -R zimbra:zimbra /opt/zimbra/data/ldap/mdb
su - zimbra
/opt/zimbra/libexec/zmslapadd /tmp/ldapdump/ldap.bak
ldap startИ вот здесь я нарушил собственное правило — то самое, про «пользуемся ровно тем, что лежит в бэкапе». Скопированная база каталога не отдалась ни в каком виде: zmslapcat на ней падал там же, где падал slapd. Дамп мы в итоге сняли с боевого сервера, который стоял живой в соседней стойке. Полминуты работы — и LDIF на руках.
Это отдельный урок учения, и он неприятнее всех остальных. В настоящей аварии боевой машины не будет: именно её отсутствие и есть авария. Значит, формально учение мы в этом месте провалили, а секундомер показал заниженное время. Если бы каталог пришлось собирать руками — 19 ящиков, домены, алиасы, классы обслуживания и права, — это ещё часов пять и почти гарантированные расхождения. Оговариваю это прямо, потому что журнал, в котором подчищены неудобные места, не стоит ничего. И первая из трёх правок в схеме появилась вечером именно из-за этого эпизода.
Где я потерял пятьдесят минут
Теперь про мою собственную ошибку, потому что учение — это в первую очередь про неё. К этому моменту за клавиатурой сидел уже я: инженер, который вёл разворот, уехал на другой выезд, и загрузку каталога я взял на себя.
Загрузку LDIF я запустил из обычной ssh-сессии. Не в screen, не в tmux — просто в терминале ноутбука. Через двенадцать минут Wi-Fi в переговорке моргнул, сессия отвалилась, процесс получил SIGHUP и умер на середине.
Полбазы залито, полбазы нет. Продолжить нельзя — нужно сносить и начинать заново. Плюс проверка, что после обрыва не осталось мусора. Пятьдесят минут в мусорку, и виноват тут только я.
screen -S restore
/opt/zimbra/libexec/zmslapadd /tmp/ldapdump/ldap.bak
# Ctrl+A, D — отцепиться; screen -r restore — вернутьсяПрерванный импорт способен оставить базу в состоянии, из которого её уже не поднять. Это касается не только каталога: длинный импорт ящиков ведёт себя так же. Правило простое до глупости — всё, что идёт дольше пяти минут, запускается в отсоединяемой сессии. Я это правило знал. И всё равно нарушил, потому что «тут же на двенадцать минут».
Финиш — 16:12. Ящик buh@ открылся, письмо от марта 2022-го на месте.
Проверьте у себя за 2 минуты
Три команды. Выполнять на боевом сервере, ничего не меняют.
su - zimbra -c 'zmcontrol -v'
ls -lah /путь/к/бэкапу/ | tail -6
su - zimbra -c 'zmlocalconfig -s zimbra_uid zimbra_gid'И один вопрос без команды: какого числа вы последний раз поднимали из этого архива работающий сервер?
| Что получилось | Что это значит |
|---|---|
| Версию продукта пришлось искать дольше минуты | В аварии вы будете искать её же, только под звонки. Положите строку вывода zmcontrol -v текстовым файлом рядом с архивом. |
В бэкапе только каталог /opt/zimbra, снятый на живой службе | Ровно наш случай. Файлы базы каталога скопированы в движении, шанс получить MDB_CORRUPTED при развороте — реальный. |
| Отдельной выгрузки каталога в LDIF нет | Учётки, домены, алиасы и права держатся на одной копии. Резервной у вас нет. |
UID/GID пользователя zimbra нигде не записаны | При развороте на новой машине права приедут чужие. Лечится, но времени стоит. |
| На вопрос про дату восстановления ответа нет | Срок восстановления вашей почты сейчас — неизвестная величина. Не «шесть часов», а именно неизвестная. |
План против факта и три правки, которые появились в тот же вечер
Директор до учения называл цифру «часа два». Я сам ставил три с половиной. Секундомер показал 6 часов 12 минут.
| Этап | Ждали | Вышло |
|---|---|---|
| Поиск версии и подготовка ОС | 20 мин | 1 ч 35 мин |
| Копирование 174 ГБ | 1 ч 30 мин | 53 мин |
| Права и обновление поверх данных | 20 мин | 29 мин |
| Каталог: выгрузка и загрузка LDIF | 0 | 1 ч 25 мин |
| Мой оборванный импорт | 0 | 50 мин |
| Проверка ящиков и почты | 30 мин | 1 ч |
Три вещи мы поменяли в схеме в тот же вечер, до конца рабочего дня.
Первое. Ежесуточная выгрузка каталога в LDIF отдельным файлом, рядом с архивом. Она весит 9 МБ и читается любой версией — это самая дешёвая страховка во всей схеме.
# в crontab пользователя zimbra, 03:10
10 3 * * * /opt/zimbra/libexec/zmslapcat /backup/ldap/$(date +\%F) >/dev/null 2>&1Второе. Текстовый файл RESTORE.txt в корне архива: версия продукта и ОС, hostname, IP, UID и GID пользователя zimbra, где лежит дистрибутив, порядок шагов. Половина страницы. Она снимает те самые двадцать две минуты.
Третье. Ночной rsync теперь идёт после короткой остановки службы — 4 минуты в 03:00. За полтора года ни один человек этого не заметил.
Что это стоило и что я предлагаю
Учение обошлось клиенту в один рабочий день инженера и виртуалку, которую потом снесли. Взамен он получил число: 6 часов 12 минут — и это при живом боевом сервере, с которого можно было доснять каталог. В настоящей аварии, без исходной машины, я бы закладывал 11–13 часов, а с ручным восстановлением учёток — полтора рабочих дня.
Сутки простоя у них стоят 70–90 тысяч рублей упущенных заявок. Полтора дня — больше сотни. Три правки, которые мы внесли вечером, заняли час и сократили расчётное время до трёх с небольшим часов.
Дальше я повторяю это учение раз в год. Второй прогон, весной 2024-го, дал 3 часа 40 минут. Третий — 3 часа 5 минут, и там уже не было ни одной неожиданности, только скучная работа по списку. Это и есть цель: чтобы в аварии не осталось ни одного вопроса, на который никто не знает ответа.
Если хотите понять, где вы сейчас, — не нужно ничего заказывать. Пришлите мне вывод трёх команд из блока выше и одной строкой ответ на вопрос про дату последнего восстановления. За день напишу, что у вас реально в архиве, чего в нём не хватает и сколько часов займёт разворот, если сервер исчезнет сегодня ночью.
Частые вопросы
Можно ли проверить бэкап, не поднимая отдельный сервер?
Частично — да, и это лучше, чем ничего. Разверните один ящик среднего размера из архива во временную учётку и посмотрите, всё ли на месте: папки, вложения, даты писем. Это полчаса и почти не требует ресурсов. Но такая проверка отвечает только на вопрос «читаются ли данные». Она ничего не скажет про каталог, про права, про то, найдёте ли вы нужную версию дистрибутива и сколько времени уйдёт на сборку машины. У учебного центра на Дмитровке проверка ящиков проходила исправно, а на полном развороте мы встали на LDAP через три часа после старта. Так что поящичная проверка — ежемесячная рутина, полное учение — раз в год.
Почему нельзя просто восстановить снапшот виртуальной машины?
Можно, и это самый быстрый путь — если у вас цел гипервизор и хранилище снапшотов. Проблема в том, что снапшот лечит ровно один сценарий: «мы сломали сервер, железо живо». Он не помогает, когда хранилище повреждено, когда виртуалку зашифровали вместе с бэкапами на том же массиве или когда нужно поднять почту на другой площадке. Плюс снапшот живой машины несогласован сам с собой: база на диске, письма на диске и то, что в этот момент было в памяти, относятся к разным моментам времени. Я держу снапшоты как быстрый откат и отдельно — файловый архив с LDIF, дампом базы и ящиками. Это разные инструменты для разных аварий.
Обязательно ли ставить ту же версию Zimbra, что была на старом сервере?
Для разворота из архива — да. Инсталлятор поверх перенесённых данных умеет обновляться вперёд, но не назад и не через несколько веток сразу. Если поставить более свежую версию и положить под неё старые данные, вы получите либо отказ на старте, либо длинную миграцию схемы в самый неподходящий момент. Порядок такой: сначала поднять точно ту же версию и убедиться, что почта работает, и только потом отдельным окном работ обновляться. И операционная система тоже должна совпадать — перенос между дистрибутивами делается не копированием каталога, а через выгрузку ящиков.
Сколько времени занимает такое учение и когда его лучше проводить?
У нас получилось 6 часов 12 минут на 19 ящиков и 174 ГБ, из них полтора часа — потери на вещах, которых можно было избежать. На парке в 50–60 ящиков и терабайт с небольшим я закладываю полный рабочий день. Проводить лучше в будний день утром, а не в выходные: должен быть доступен человек, который отвечает на вопросы «а это письмо у вас точно было?». Боевой сервер при этом не останавливается, пользователи ничего не замечают. Единственное ограничение — нужна свободная виртуалка и место под копию store.
Что положить в архив, кроме самих писем?
Минимальный набор, который я считаю обязательным: выгрузка каталога в LDIF отдельным файлом, дамп базы, снятый на остановленной службе, локальная конфигурация, ключи DKIM, сертификаты и файл с версией продукта, версией ОС, hostname, IP и UID/GID пользователя zimbra. Плюс сам дистрибутив нужной версии — его через три года может уже не оказаться в открытом доступе, и это отдельный неприятный сюрприз. Всё вместе занимает считанные десятки мегабайт рядом с сотнями гигабайт писем, а разницу во времени разворота даёт в разы.
Оставить комментарий