Ответ
Для обновления PostgreSQL с минимальным простоем я использую логическую репликацию. Это позволяет создать новый кластер на целевой версии и синхронизировать данные в реальном времени.
Основные шаги:
- Подготовка: Устанавливаю новую версию PostgreSQL на отдельном сервере или инстансе.
- Настройка публикации: На исходном сервере (мастере) настраиваю логическую репликацию, создавая публикацию для нужных таблиц или всей БД.
-- На мастере (старая версия) CREATE PUBLICATION myapp_pub FOR ALL TABLES; - Настройка подписки: На целевом сервере (новая версия) создаю подписку, указывая соединение с мастером.
-- На реплике (новая версия) CREATE SUBSCRIPTION myapp_sub CONNECTION 'host=master_host port=5432 dbname=mydb' PUBLICATION myapp_pub; - Синхронизация и проверка: После полной синхронизации данных проверяю целостность и корректность работы приложения на тестовой нагрузке, направляя часть трафика на новую версию.
- Переключение: В запланированное окно останавливаю приложение, дожидаюсь полной синхронизации, меняю строки подключения в конфигурации приложения и переключаю трафик на новый кластер.
- Откат: Старый кластер оставляю работающим на короткое время как горячую резервную копию на случай быстрого отката.
Ключевые моменты:
- Тестирование: Всегда тестирую процедуру обновления и отката на staging-окружении, идентичном production.
- Резервная копия: Перед началом обязательно создаю полный физический бэкап с помощью
pg_basebackup. - Даунтайм: Финальное переключение связано с кратковременным даунтаймом (минуты), но основная синхронизация данных происходит онлайн.
- Для Docker/K8s: В контейнеризованной среде разворачиваю новый StatefulSet с образом новой версии, настраиваю репликацию между подами, а затем обновляю сервис, указывающий на новый набор подов.