Стройке в Одинцове меняли провайдера, и вместе с ним менялся весь адресный план — включая почтовый сервер. Мы вышли в ночь на субботу с планом на два часа, а закончили в 07:20 субботы. Причина простая: старую запись в DNS убрали на двадцать минут раньше, чем следовало.
Переезд Zimbra на новый IP и hostname: zmsetservername целиком
Когда провайдер меняется, а почта остаётся
Смена провайдера в небольшой компании выглядит безобидно. Приходят монтажники, тянут новый кабель, отдают блок адресов, старый канал держат ещё пару недель для верности. Сайт переезжает за час, VPN — за вечер. И где-то в конце списка стоит строчка «почтовый сервер», которую все считают такой же простой задачей.
Она не простая. Zimbra не хранит своё имя в одном месте. Оно вписано в конфигурацию каждой службы, в объект сервера в каталоге LDAP, в сертификат, в карту логгера, в записи домена. Пока имя резолвится в старый адрес, всё работает. Как только перестаёт — половина служб не поднимается, и разбираться приходится с каждой по отдельности.
Если у вас на почте висит внешний IP, который вот-вот перестанет быть вашим, у задачи есть неприятное свойство: она не откладывается. Старый канал отключат по договору, а не когда вам удобно.
Ниже — как это делается целиком, что именно пошло не так у меня и почему порядок шагов важнее самих шагов.
Август 2019, Одинцово: 37 рабочих мест и новый блок адресов
Строительная компания, офис и производственная база в Одинцове, 37 рабочих мест. Уходили от провайдера, который поднял тариф вдвое, к другому — с блоком из восьми адресов вместо одного. Меняли всё: внешний адрес, шлюз, внутреннюю адресацию за роутером тоже решили привести в порядок заодно.
Почтовый сервер на тот момент:
- Zimbra 8.8.15 Open Source Edition, CentOS 7, физический сервер в серверной — до 8.8.15 их дотянули весной того же года, как раз перед историей с переездом;
- однохостовая инсталляция — LDAP, MTA, mailstore и прокси на одной машине;
- 37 ящиков, store 190 ГБ, самый большой ящик — 21 ГБ у главного инженера;
- имя
mail.old-domain.ru, оно же в сертификате Let's Encrypt.
Заказчик хотел заодно поменять и имя: почта переезжала на домен, который компания использовала как основной, — то есть менялся не только адрес, но и полное имя хоста. Это, кстати, ровно тот случай, когда работы нельзя разбить на два вечера: имя и адрес завязаны друг на друга, и половинчатое состояние хуже обоих крайних.
План был на 2 часа в ночь с пятницы на субботу. Технически он был правильный. Ошибка обнаружилась не в плане, а в том, кто и когда нажимает кнопки.
Готовиться начали за сутки. Первое, что сделали в четверг днём, — снизили TTL всех записей почтового домена с 3600 до 300 секунд. Это единственное действие подготовки, которое нельзя пропускать: с часовым TTL переключение растянется на полдня, и вы не поймёте, сломалось у вас что-то или просто кэш.
Полная процедура: порядок, который отработал
Последовательность ниже я с тех пор не менял. Она выглядит скучно, и в этом её достоинство.
Шаг 1. Зафиксировать, что есть сейчас. До любых правок снимаем текущее состояние — потом будет с чем сверять:
$ su - zimbra
$ zmhostname
mail.old-domain.ru
$ zmprov gs $(zmhostname) | grep -iE 'zimbraServiceHostname|zimbraServiceEnabled|zimbraMtaMyNetworks'
$ zmprov gd old-domain.ru | grep -iE 'zimbraDomainName|zimbraPublicServiceHostname'
$ zmlocalconfig -s zimbra_server_hostname ldap_master_url ldap_url
Шаг 2. Остановить Zimbra полностью. Не отдельные службы — всё:
$ zmcontrol stop
$ ps -u zimbra | wc -l
Вторая команда нужна, чтобы убедиться: процессов не осталось. Пустой вывод zmcontrol stop ещё ничего не гарантирует.
Шаг 3. Поменять имя на уровне операционной системы. Сначала /etc/hosts, потом /etc/hostname. В /etc/hosts новое имя обязано разрешаться в локальный адрес сервера, и никак иначе:
# /etc/hosts
192.168.30.10 mail.new-domain.ru mail
127.0.0.1 localhost localhost.localdomain
# /etc/hostname
mail.new-domain.ru
Шаг 4. Собственно смена имени внутри Zimbra:
# я запускаю от root, после чего обязательно проверяю владельцев файлов
/opt/zimbra/libexec/zmsetservername -n mail.new-domain.ru
ls -l /opt/zimbra/conf/localconfig.xml
Утилита проходит по объектам каталога и переписывает имя сервера везде, где оно встречается. Работает не мгновенно: у нас на 37 ящиках заняла около десяти минут.
Шаг 5. Почистить карту логгера. Она хранит соответствие «имя хоста — сервер» и остаётся со старым значением:
$ su - zimbra
$ zmloggerhostmap
Шаг 6. Ещё раз остановить и перезагрузить машину. Именно перезагрузить, а не перезапустить службы: имя хоста подхватывается на старте, и часть демонов иначе останется со старым.
Шаг 7. После загрузки — поднимать и смотреть в лог, а не в статус:
$ su - zimbra -c 'zmcontrol start'
$ tail -f /opt/zimbra/log/mailbox.logГде мы легли: A-запись убрали на двадцать минут раньше
Ошибка вышла бытовая. Пока я занимался сервером, коллега на другом конце офиса переносил зону к новому регистратору. В списке дел у него стояло «убрать старые записи» — и он их убрал. В том числе A-запись mail.old-domain.ru. В этот момент zmsetservername у меня ещё крутился.
Через несколько минут после старта служб мы получили вот это:
Unable to contact ldap://mail.old-domain.ru:389: Invalid argument
Дальше я потратил час не туда. Логика была такая: раз не удаётся соединиться с LDAP по порту 389, значит новый провайдер что-то фильтрует или заработали новые правила на роутере. Полез в iptables, поднял tcpdump, проверил, что порт слушается локально. Всё было в порядке. Соединения просто не начинались.
Понял я это, когда сделал самую очевидную вещь, до которой почему-то дошёл не сразу:
$ dig +short mail.old-domain.ru
$ echo $?
0
Пустой ответ. Имя, на которое всё ещё ссылалась часть конфигурации, перестало существовать в природе. Порт был ни при чём — до порта дело не доходило, соединение падало на разрешении имени.
Механика здесь простая, и о неё бьются регулярно. zmsetservername не переписывает конфигурацию мгновенно и атомарно: пока он не закончил и пока службы не подтвердили новое имя, часть ссылок ведёт на старое. Если старое имя в этот момент не резолвится — процесс остаётся в наполовину переписанном состоянии, и LDAP-клиент внутри Zimbra уходит в ошибку.
Лечится в лоб: возвращаем A-запись на место и доводим процедуру до конца. Мы вернули её в 03:40, запись разошлась благодаря заранее сниженному TTL за пять минут, и дальше всё пошло по плану. Без сниженного TTL мы бы сидели до утра.
Проверьте у себя за две минуты
Эта проверка полезна не только перед переездом. Она показывает, согласовано ли у вас имя сервера прямо сейчас — а расхождение случается и само по себе, например после восстановления виртуалки из снимка или переустановки ОС «поверх».
$ hostname -f
$ su - zimbra -c 'zmhostname'
$ su - zimbra -c 'zmprov gs $(zmhostname) zimbraServiceHostname'
$ dig +short $(hostname -f)
$ dig +short -x $(hostname -I | awk '{print $1}')
Все пять строк должны говорить об одном и том же имени и одном адресе. Что означают расхождения:
| Что увидели | Что это значит | Насколько срочно |
|---|---|---|
hostname -f и zmhostname различаются | Имя меняли в системе, но не внутри Zimbra. Часть служб работает на старом | До ближайшей перезагрузки — она вскроет проблему |
dig по имени не отдаёт ничего | Записи нет либо она внутри, а сервер смотрит наружу. Классика после смены DNS | Сегодня |
dig отдаёт адрес, которого нет на сервере | Имя ведёт на старый или чужой хост | Сегодня |
| Обратная запись пустая или чужая | PTR не переехал вместе с адресом — почта пойдёт в спам | В первый же день после смены IP |
| TTL записей 3600 и выше, а переезд на этой неделе | Переключение растянется на часы, диагностика станет невозможной | Снизить за сутки до работ |
В /etc/hosts имени нет вовсе | Сервер зависит от внешнего DNS даже для самого себя | Добавить до любых работ |
Последняя строчка выглядит мелочью, но именно она превращает пятиминутный сбой DNS в получасовой отказ почты.
Что доделывали после: сертификат, PTR и сети MTA
Службы поднялись в 04:15. Работа на этом не кончилась — сменилось имя, а вместе с ним стало неверным ещё несколько вещей.
Сертификат. Старый был выписан на mail.old-domain.ru. Браузеры и почтовые клиенты честно ругались. Выпустили новый и проверили цепочку до установки:
$ su - zimbra
$ /opt/zimbra/bin/zmcertmgr verifycrt comm /opt/zimbra/ssl/zimbra/commercial/commercial.key \
/tmp/new/cert.pem /tmp/new/chain.pem
$ /opt/zimbra/bin/zmcertmgr deploycrt comm /tmp/new/cert.pem /tmp/new/chain.pem
$ zmcontrol restart
Сети MTA. Внутренняя адресация тоже поменялась, а в параметре доверенных сетей остались старые подсети. Симптом был бы отложенный и неприятный: часть внутренних систем перестала бы отправлять уведомления через сервер:
$ zmprov ms $(zmhostname) zimbraMtaMyNetworks '127.0.0.0/8 192.168.30.0/24'
Обратная запись. Новый провайдер прописал PTR на свой шаблон вида host-93-x-x-x.provider.ru. С таким PTR письма отправляются, но принимающие стороны относятся к ним настороженно. Заявку на нужную запись подали в пятницу утром, сделали её только во вторник — четверо суток почта уходила с чужим именем в обратной зоне. Это надо закладывать в план заранее, потому что от вас тут ничего не зависит.
MX и SPF. MX переключили последним, уже утром субботы, когда сервер устойчиво отвечал на новом адресе. В SPF добавили новый адрес, а старый оставили ещё на две недели — на время, пока старый канал был жив, и на всякий случай.
Ещё одна мелочь, стоившая нам двадцати минут: после перезагрузки службы не поднялись с первого раза, и zmcontrol ругнулся на нечисловой идентификатор процесса. В /opt/zimbra/log остались PID-файлы от аварийно завершённых демонов. Убрали, стартовали заново, поднялось.
Итоги ночи в цифрах и во что это встало
Хронология получилась такая:
| Время | Что происходило |
|---|---|
| чт, 14:00 | TTL записей снижен с 3600 до 300 секунд |
| сб, 01:30 | zmcontrol stop, правка /etc/hosts и /etc/hostname |
| сб, 01:48 | Запущен zmsetservername |
| сб, 01:55 | Коллега удалил старую A-запись |
| сб, 02:10 | Первое Unable to contact ldap://mail.old-domain.ru:389 |
| сб, 02:10–03:35 | Час двадцать я искал проблему в файрволе. Не там |
| сб, 03:40 | Запись возвращена в зону |
| сб, 04:15 | Все службы поднялись на новом имени |
| сб, 06:05 | Развёрнут новый сертификат, переключён MX |
| сб, 07:20 | Проверка приёма и отправки, работы закрыты |
Пять часов пятьдесят минут вместо запланированных двух. Из них час двадцать — чистая потеря на ложном следе, ещё около часа — на то, что делалось бы всё равно, но не ночью.
Писем при этом не потеряли ни одного, и вот почему: MX всё это время указывал на старый адрес, который оставался живым. Отправители, которые не смогли достучаться, получали временную ошибку и повторяли попытку — это штатное поведение, письма не пропадают, а откладываются. Мы разгребли очередь утром: в отложенных лежало 173 письма, все доехали.
Цена вопроса, если бы мы пошли по короткому пути и сделали это в рабочий день. Тридцать семь человек без почты — а с учётом того, что стройка живёт заявками и согласованиями по почте, это остановка работы отдела снабжения и сметчиков. Считали грубо: 5 часов 50 минут × 37 человек ≈ 216 человеко-часов. При 500 рублях за час — 108 тысяч рублей упущенной работы, не считая сорванных сроков по двум тендерам с дедлайном в понедельник. Ночное окно обошлось им в 33 000 рублей: шесть часов по ночной ставке 5 500 рублей за час.
33 тысячи против 108 — больше чем втрое, и это без тендеров. Вот этот счёт на двух строчках — единственный аргумент, который в таких разговорах работает.
Что стоит унести из этой истории
Короткий список, который я теперь проговариваю с заказчиком до начала работ.
- Старое имя живёт до последнего. Не удаляйте
A-запись, пока службы на новом имени не отработали хотя бы час. Она вам ничего не стоит, а без неё вы застрянете. - TTL снижается за сутки. Не за час до работ — за сутки, иначе снижение само не успеет разойтись.
- Кнопки нажимает один человек. Наша ошибка была не технической: два специалиста делали части одной задачи параллельно и по своим спискам.
- Проверять надо в логе, а не в статусе.
zmcontrol statusв такие моменты — плохой советчик; смотритеmailbox.log, там причина написана словами. - PTR не зависит от вас. Заявку провайдеру подавайте одновременно с планированием работ, а не после.
И про совет, который часто дают в форумах: «проще поставить новый сервер и перенести на него ящики, чем менять имя старому». Для крупной инсталляции — возможно. Для тридцати семи ящиков это подмена одной ночной работы многодневной миграцией с переносом почты, паролей, календарей и общих папок. Мы посчитали оба варианта: смена имени — одна ночь, полный перенос — три ночных окна и неделя разбора хвостов. Прыгать в миграцию имеет смысл, когда есть вторая причина: старая версия, мёртвая ОС под сервером, железо на грани.
Собираетесь менять провайдера или адресацию и не уверены, что почта переживёт? Выполните пять команд из раздела «Проверьте у себя за две минуты» и пришлите вывод — я за день скажу, согласовано ли у вас имя сейчас, что придётся править и уложится ли переезд в одно ночное окно. Если увижу, что нужен не переезд имени, а что-то другое, напишу прямо.
Частые вопросы
Можно ли поменять только IP, не трогая hostname?
Можно, и это заметно проще. Тогда достаточно поправить адрес в /etc/hosts, обновить A-запись и доверенные сети MTA через zmprov ms $(zmhostname) zimbraMtaMyNetworks, а также заказать у провайдера обратную запись на новый адрес. zmsetservername в этом случае не нужен вовсе — имя не меняется, а вся конфигурация Zimbra завязана именно на имя, а не на адрес. Одна оговорка: если у вас в конфигурации где-то прописан голый IP вместо имени, найдите эти места заранее, иначе они всплывут через неделю в самый неудобный момент.
Сколько по времени работает zmsetservername?
На однохостовой инсталляции с 37 ящиками у меня заняло около десяти минут. Время зависит не от объёма почты, а от количества объектов в каталоге — доменов, учётных записей, списков рассылки, классов обслуживания. На двух-трёх сотнях ящиков закладывайте 10–15 минут. Главное правило: не прерывать. Если процесс остановить на середине, конфигурация останется наполовину переписанной, и разбирать её потом придётся руками через zmprov, сверяя объекты по одному. Запускайте в screen или tmux, чтобы обрыв сессии ничего не сломал.
После смены имени служба не стартует и ругается на нечисловой идентификатор процесса. Что это?
Это осиротевшие PID-файлы в /opt/zimbra/log, оставшиеся от процессов, которые завершились нештатно — например, при перезагрузке в середине процедуры. Скрипт управления читает файл, находит там мусор вместо номера и падает. Порядок действий: убедиться командой ps -u zimbra, что живых процессов действительно нет, удалить файлы *.pid и стартовать заново. Если процессы есть — сначала завершить их, иначе получите два экземпляра одной службы. И запускайте управление строго из-под пользователя zimbra, а не от root.
Потеряются ли письма, пока сервер недоступен?
Нет, если вы не трогали MX раньше времени. Отправляющий сервер, не сумев доставить письмо, получает временную ошибку и складывает письмо в свою очередь, повторяя попытки несколько суток. У нас за ночь накопилось 173 отложенных письма, и все они доехали в течение получаса после того, как сервер поднялся. Опасны здесь два сценария: MX переключили на адрес, который ещё не принимает почту, — тогда письма будут отбиваться постоянной ошибкой; либо работы затянулись дольше срока жизни очереди у отправителей. Поэтому MX я переключаю последним действием, а не первым.
Обязательно ли ночное окно, или можно сделать это днём за пару часов?
Технически — можно, процедура одинаковая. Экономически — считайте сами. У клиента в Одинцове работы заняли пять часов пятьдесят минут против плановых двух, и это при подготовке и снятом заранее TTL. Днём это означало бы 37 человек без почты на большую часть рабочего дня, около 216 человеко-часов и два тендера с дедлайном в понедельник под угрозой. Даже идеально прошедшая процедура требует перезагрузки сервера и повторного старта служб — это минимум двадцать минут полного простоя, которые невозможно сократить.
Оставить комментарий