PostgreSQL с 10-й версии на 17-ю за одно окно

Что было

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

Ситуация обычная для системы, которая выросла из стартапа: база работает, трогать страшно, а список причин перестать откладывать копится:

  • версия давно без обновлений безопасности;
  • новые возможности планировщика и мониторинга недоступны;
  • инструменты вокруг базы постепенно перестают поддерживать старую ветку;
  • разница между десятой и семнадцатой версиями — семь мажорных выпусков, то есть накопленные несовместимости в правах, ролях и умолчаниях.

Требование бизнеса: простой не дольше трёх часов, ночью, с гарантией возврата назад, если что-то пойдёт не так.

Как делали

Метод — логическая репликация. Новый сервер поднимается рядом на семнадцатой версии, данные едут на него заранее и держатся в актуальном состоянии. В окно остаётся только догнать последние изменения и переключить приложения на новый адрес. Обновление на месте отпадало сразу: оно требует остановки на всё время конвертации и не оставляет пути назад.

Сверка структуры до окна. Пересчитали и сравнили таблицы, колонки, ограничения, счётчики идентификаторов, права и роли. Разница между версиями вылезает именно здесь: то, что в десятой было умолчанием, в семнадцатой требует явной выдачи прав.

Репетиция на тестовом контуре. Прогнали окно целиком, по командам, как в бою. Репетиция вскрыла три ошибки в готовых командах, каждая из которых сорвала бы работы: не срабатывал разрыв пользовательских соединений, команда остановки сервисов не работала в оболочке инженера, а критерий готовности приложений давал ложное «готово». Все три исправлены и перепроверены до боевого окна.

Заранее написанные команды. К окну готовится файл, где каждый шаг — готовая строка с проверкой результата. В три часа ночи никто ничего не сочиняет и не вспоминает синтаксис.

Точка принятия решения. Перед самим переключением — формальная проверка «идём или не идём»: лаг подписки, состояние копий, готовность отката. Не сошлось — расходимся и переносим, потери минимальные.

Логическая репликация PostgreSQL 10 в 17, проверка готовности и фактическое окно 1 час 47 минут

Результат

Что Итог
Окно работ 1 час 47 минут при заявленных бизнесу трёх часах
Данные перенесены полностью, подписчик дошёл до финальной LSN
Структура 199 таблиц, 1 593 колонки, 189 счётчиков, 409 ограничений — сошлось до единицы
Счётчики идентификаторов 168 расхождений найдено и исправлено до открытия
Сервисы все 16 подняты в штатном числе копий
Проверка действием чтение и запись боевых данных прошли до открытия входа
Ошибки в журнале после открытия ноль за четыре часа наблюдения
Откат не потребовался

Три сбоя в окне всё-таки случились: подвисшие приложения на одном узле, отказ того же узла запускать новые копии и заглушка технических работ, мешавшая внутренним вызовам при приёмке. Все три разобраны на месте и уложились в окно — именно на такие случаи в плане и закладывается запас.

Что было после

Работы не заканчиваются переключением. Дальше — пересборка резервной реплики уже на новой версии, первая полная копия новой базы, настройка сбора метрик под новый сервер и наблюдение за первыми сутками.

Что забрал заказчик

Базу, которая снова получает обновления безопасности, и описанную процедуру: как готовились, как переключали, что проверяли и по каким признакам решали, что можно открывать пользователей. Следующее такое обновление будет уже не приключением, а рутиной по инструкции.