Как я делал upgrade PosgreSQL 12 -> 16

от автора

Сложилось так исторически, что мы долго не обновляли PostgreSQL и застряли на версии 12. Но пришло время обновлять зависимости проекта и оказалось, что Django 5.1 версию 12 PostgreSQL уже не поддерживает и это мотивировало меня провести обновление до новейшей 16 версии.

На момент написания у нас всё организовано достаточно просто — все необходимые компоненты запускаются в Docker-контейнерах через Docker Compose.

У меня было два варианта, как произвести миграцию:

  1. Сделать полный дамп, загрузить новый образ postgres:16 и накатить дамп

  2. Использовать утилиту pg_upgrade, которая позволяет мигрировать данные между версиями PostgreSQL

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

Сначала было непонятно как применить pg_upgrade в docker, но после непродолжительного гуглежа я нашёл решение: https://github.com/tianon/docker-postgres-upgrade

По ходу изучения того, как работать с docker-postgres-upgrade был составлен такой план:

  1. остановить сервисы, зависимые от БД

  2. сделать бэкап БД

  3. остановить БД

  4. произвести миграцию

  5. запустить и проверить БД на новой версии PostgreSQL

  6. запустить сервисы

  7. обновить docker-compose.yml

Примечание: хотя pg_upgrade и позволяет произвести миграцию на горячую, но я решил не рисковать и сделать это на холодную

Ниже я кратко опишу процесс миграции.

Для начала нужно понять какой volume используется нашим PostgreSQL

% cat docker-compose.yml
services: ... postgres: image: postgres:12 container_name: postgres command: postgres -c "config_file=/etc/postgresql/postgresql.conf" environment: POSTGRES_PASSWORD: xxxxxx volumes: - ./postgresql/postgresql.conf:/etc/postgresql/postgresql.conf - postgres:/var/lib/postgresql/data ports: - "5432:5432" ...  volumes: postgres:
% docker volume ls DRIVER    VOLUME NAME local     1b7ffcbd614f280ab577370912c625135ef84fe8cf721953206ba0142bed8cad local     6b82aa6ecc19fbea9eb91b8d68af0d6a18d04911717953935cff006a4220e123 local     7c2b74aa668a47d2fe15615b8f4a614ebcf3065ab101cdaf487da6b5e1c95ffd local     16ea96ec68eeb0134f0eebd27ec983143e9bdd43d527d3c6e1d3f1cd2bacc516 local     180aeeeadba249e991c22bb77c53c9b2a50612a3d181598a8014b667d920762d local     625ebc83103e8c223395fb7b5e7e31a714110400f6f70f499bee13f3d9b86bce local     803c056ecb2c83b31e5d0dbb089689ae1b44996fb84aee1e12c8d224b583f8e7 local     a1ccdb17c4cc50333ec2c417cf24553e89e4f5aa1e402c1985a8fec2f52c00dd local     a40c9d1b958169dda6db47e7493dacf7c05e6e0acd678954ea87f7ac3ffb8a16 local     backend_media local     backend_postgres local     backend_postgres-14 local     backend_postgres-16 local     backend_static local     c73a013579341af8a05646a501f4b4a9595a3e2b1167543889d1c26a21e4fda3 local     cebd974e3e2f2a5bd0b2cf16a4ef293696e30d547ccfd59bad44d155541da16b local     d393b6d74083d4ac5a679a7ed62cf364663a66fa41f113e1b60395ec369e26bb local     dev_badger local     dev_media local     dev_postgres local     dev_static local     edb6be7221e82a9f9c4ba47ac1cae104765bc8d4d29020fef1397aa4d22e9472 local     minikube local     minikube-m02 local     postgres local     postgres16 local     qa-automation_badger local     qa-automation_media local     qa-automation_postgres local     qa-automation_static 

Нам нужен volume backend_postgres, потому что Docker Compose по умолчанию именует volumes в формате «имя проекта + имя volume». Поскольку проект называется backend (по-умолчанию имя каталога, где запускается Docker Compose, если не задано другое ключом -p), наш целевой volume будет называться backend_postgres. Для новой версии PostgreSQL volume будет называться backend_postgres16.

миграция

% docker run --platform linux/amd64 --rm -v backend_postgres:/var/lib/postgresql/12/data -v backend_postgres16:/var/lib/postgresql/16/data tianon/postgres-upgrade:12-to-16

На MacOS с архитектурой Apple Silicon (M1/M2/M3) возникла необходимость добавить флаг --platform linux/amd64, так как образ tianon/postgres-upgrade по умолчанию не поддерживает ARM-архитектуру. Это позволяет принудительно использовать x86_64-образ для успешного запуска.

После завершения процедуры миграции делаем пробный запуск:

% docker run -dit --name postgres16 -p 5432:5432 -e POSTGRESS_PASSWORD=postgres -v backend_postgres16:/var/lib/postgresql/data -v ./postgresql/postgresql.conf:/var/lib/postgresql/data/postgresql.conf -v ./postgresql/pg_hba.conf:/var/lib/postgresql/data/pg_hba.conf  postgres:16

У меня кастомные postgresql.conf и pg_hba.conf поэтому прокидываем их внутрь контейнера.

И проверяем по логам, что всё хорошо

% docker logs -f postgres16

Нужно проверить логи на наличие ошибок или предупреждений. Особое внимание стоит уделить сообщениям о несовместимости версий или проблемах с доступом к данным.

Если тестовый запуск прошёл успешно, можно закрепить изменения в основном файле docker-compose.yml, заменив старую версию PostgreSQL на новую. Важно убедиться, что все зависимости обновлены и настроены правильно перед запуском в продакшн.

Новый docker-compose.yml

services: ...     postgres:         image: postgres:16         container_name: postgres         environment:             POSTGRES_PASSWORD: xxxxxx         volumes:             - ./postgresql/postgresql.conf:/var/lib/postgresql/data/postgresql.conf             - ./postgresql/pg_hba.conf:/var/lib/postgresql/data/pg_hba.conf             - postgres16:/var/lib/postgresql/data         ports:             - "5432:5432" ...  volumes:     postgres16: 

Заключение

Благодаря docker-postgres-upgrade процесс миграции на новую версию PostgreSQL прошёл быстро и гладко. Это отличное решение для тех, кто ищет простой и надёжный способ обновления PostgreSQL в Docker-среде. Рекомендую!


ссылка на оригинал статьи https://habr.com/ru/articles/837994/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *