Учение по восстановлению Zimbra: развернуть с нуля за шесть часов

Учебный центр на Дмитровском шоссе, 13 рабочих мест, почта на Zimbra с 2019 года. Бэкап у них шёл каждую ночь и ни разу не падал. В апреле 2023 я предложил проверить его единственным честным способом: взять чистую машину, поднять на ней почту из архива и засечь секундомер. Мы уложились в 6 часов 12 минут вместо ожидаемых двух. Рассказываю, куда ушла разница.

Спросите админа, когда он последний раз восстанавливался

Задайте своему администратору один вопрос. Не «делаешь ли ты бэкап», а «когда ты в последний раз поднимал из него почту». На отдельной машине. С секундомером. До момента, когда в браузере открылась чужая входящая с письмами за позапрошлый год.

Ответ почти всегда один: «бэкап идёт каждую ночь, ошибок нет». Это ответ на другой вопрос. Ночная задача проверяет, что архив пишется. Она ничего не говорит о том, соберётся ли из этого архива работающий почтовый сервер и сколько часов на это уйдёт. Между «файлы лежат» и «люди читают почту» помещается целый рабочий день, о котором никто не знает заранее.

Я не люблю пугать. Поэтому предлагаю клиентам не разговор, а процедуру: раз в год берём виртуалку, поднимаем на ней почту из вчерашнего архива и записываем время. Час работы моего инженера против неизвестности — по-моему, честный обмен.

Дальше — журнал одного такого учения, минута в минуту.

Апрель 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 мин
Каталог: выгрузка и загрузка LDIF01 ч 25 мин
Мой оборванный импорт050 мин
Проверка ящиков и почты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. Плюс сам дистрибутив нужной версии — его через три года может уже не оказаться в открытом доступе, и это отдельный неприятный сюрприз. Всё вместе занимает считанные десятки мегабайт рядом с сотнями гигабайт писем, а разницу во времени разворота даёт в разы.

Нужна помощь с проектом?

Специалисты АйТи Фреш помогут с архитектурой, DevOps, безопасностью и разработкой — 15+ лет опыта

📞 Связаться с нами
#Zimbra#бэкап#восстановление#учения#LDAP
Комментарии 0

Оставить комментарий

загрузка...

Подпишитесь на рассылку ITfresh

Раз в неделю — практические гайды для руководителя IT и сисадмина: безопасность, 1С, миграции, резервные копии, лайфхаки из реальных проектов.

Реквизиты оператора персональных данных

ООО «АЙТИ-ФРЕШ», ИНН 7719418495, КПП 771901001. Юридический адрес: 105523, г. Москва, Щёлковское шоссе, д. 92, корп. 7. Контакт: info@itfresh.ru, +7 903 729-62-41. Оператор обрабатывает e-mail подписчика в целях рассылки информационных и рекламных материалов до момента отзыва согласия.