Миграция PostgreSQL в Kubernetes

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Все больше компаний внедряют Kubernetes как из интереса к передовым технологиям, так и в рамках стратегии по трансформации бизнеса. Когда дело касается переноса приложений в контейнеры и инфраструктуру Kubernetes, перед разработчиками и специалистами по эксплуатации встают непростые задачи, если приложения изначально не ориентированы на облако.

Миграция баз данных всегда сопряжена с рисками и простоями для бизнеса. Сегодня я продемонстрирую, насколько легко можно перенести базу данных PostgreSQL в Kubernetes с минимальными простоями. В этом мне поможет дистрибутив Percona для PostgreSQL Operator.

Цель

Для выполнения миграции я буду использовать следующую конфигурацию:

  1. База данных PostgreSQL, развернутая локально или где-то в облаке. Эту базу данных будем называть источником.

  2. Кластер Google Kubernetes Engine (GKE), на котором будет развернуто решение Percona Operator для управления целевым кластером PostgreSQL и подом pgBackRest.

  3. Резервные копии и журналы предзаписи PostgreSQL загружаются в какой-либо бакет объектного хранилища (в моем случае — GCS).

  4. Данные из бакета считываются с помощью пода pgBackRest.

  5. Этот же под непрерывно восстанавливает данные в кластер PostgreSQL в Kubernetes.

Данные должны непрерывно синхронизироваться. По завершении процесса я хочу отключить локальный экземпляр PostgreSQL и оставить только кластер в GKE.

Миграция

Предварительные требования

Чтобы воссоздать у себя такую конфигурацию, вам понадобятся:

  • PostgreSQL версии 12 или 13 (нет разницы, где запущена СУБД);

  • установленный пакет pgBackRest;

  • Google Cloud Storage или любой другой S3-бакет (в моем случае — GCS);

  • кластер Kubernetes.

Настройка источника

В моем случае это дистрибутив Percona для PostgreSQL версии 13, установленный на несколько серверов с Linux.

1. Настройте pgBackrest.

# cat /etc/pgbackrest.conf
[global]
log-level-console=info
log-level-file=debug
start-fast=y

[db]
pg1-path=/var/lib/postgresql/13/main
repo1-type=gcs
repo1-gcs-bucket=sp-test-1
repo1-gcs-key=/tmp/gcs.key
repo1-path=/on-prem-pg
  • Значением параметра pg1-path должен быть путь к каталогу данных PostgreSQL.

  • В параметре repo1-type указано GCS, так как мы хотим сохранять резервные копии в этом хранилище.

  • В файле /tmp/gcs.key находится ключ, который можно получить через пользовательский интерфейс Google Cloud. Подробнее об этом читайте здесь.

  • Резервные копии будут сохраняться в папке on-prem-pg в бакете sp-test-1.

2. Включите в файле конфигурации postgresql.conf архивирование через pgBackrest.

archive_mode = on   
archive_command = 'pgbackrest --stanza=db archive-push %p'

После изменения конфигурации потребуется перезапуск.

3. Operator требует, чтобы в каталоге данных также находился файл с именем postgresql.conf. Будет достаточно пустого файла:

touch /var/lib/postgresql/13/main/postgresql.conf

4. На источнике необходимо создать пользователя primaryuser, чтобы обеспечить корректную настройку репликации через Operator.

# create user primaryuser with encrypted password '<PRIMARYUSER PASSWORD>' replication;

Настройка целевого кластера

1. Разверните дистрибутив Percona для PostgreSQL Operator на Kubernetes. Этот процесс подробно описан в документации.

# create the namespace
kubectl create namespace pgo

# clone the git repository
git clone -b v0.2.0 https://github.com/percona/percona-postgresql-operator/
cd percona-postgresql-operator

# deploy the operator
kubectl apply -f deploy/operator.yaml

2. Измените главный манифест настраиваемого ресурса — deploy/cr.yaml.

  • Я не стал изменять имя кластера и оставил cluster1.

  • Кластер будет функционировать в режиме ожидания, то есть он будет синхронизировать данные из бакета GCS. Задайте для параметра spec.standby значение true.

  • Настройте GCS. Раздел spec.backup должен выглядеть примерно так (параметры bucket и repoPath имеют те же значения, что и в вышеприведенной конфигурации pgBackrest):

 backup:
...
    repoPath: "/on-prem-pg"
...
    storages:
      my-s3:
        type: gcs
        endpointUrl: https://storage.googleapis.com
        region: us-central1-a
        uriStyle: path
        verifyTLS: false
        bucket: sp-test-1
    storageTypes: [
      "gcs"
    ]
  • Я хочу, чтобы в моем кластере PostgreSQL была как минимум одна реплика. Для этого параметру spec.pgReplicas.hotStandby.size нужно присвоить значение 1.

3. Для Operator необходимо обеспечить возможность аутентификации в GCS. Для этого нужно создать секретный объект под названием <ИМЯКЛАСТЕРА>-backrest-repo-config, который будет содержать ключ gcs-key. Это должен быть тот же самый ключ, который мы использовали на источнике. См. пример секрета здесь.

kubectl apply -f gcs.yaml

4. Создайте пользователей путем создания секретных объектов: postgres и primaryuser (тот же пользователь, которого мы создали на источнике). См. примеры секретов для пользователей здесь. Пароли должны быть такими же, как на источнике.

kubectl apply -f users.yaml

5. Теперь развернем кластер на Kubernetes, применив манифест cr.yaml:

kubectl apply -f deploy/cr.yaml

Проверка работоспособности и устранение неполадок

Если все сделано правильно, вы увидите в логах основного пода следующее:

kubectl -n pgo logs -f --tail=20 cluster1-5dfb96f77d-7m2rs
2021-07-30 10:41:08,286 INFO: Reaped pid=548, exit status=0
2021-07-30 10:41:08,298 INFO: establishing a new patroni connection to the postgres cluster
2021-07-30 10:41:08,359 INFO: initialized a new cluster
Fri Jul 30 10:41:09 UTC 2021 INFO: PGHA_INIT is 'true', waiting to initialize as primary
Fri Jul 30 10:41:09 UTC 2021 INFO: Node cluster1-5dfb96f77d-7m2rs fully initialized for cluster cluster1 and is ready for use
2021-07-30 10:41:18,781 INFO: Lock owner: cluster1-5dfb96f77d-7m2rs; I am cluster1-5dfb96f77d-7m2rs                                 2021-07-30 10:41:18,810 INFO: no action.  i am the standby leader with the lock                                                     2021-07-30 10:41:28,781 INFO: Lock owner: cluster1-5dfb96f77d-7m2rs; I am cluster1-5dfb96f77d-7m2rs                                 2021-07-30 10:41:28,832 INFO: no action.  i am the standby leader with the lock

Измените какие-нибудь данные на источнике и убедитесь, что они корректно синхронизируются с целевым кластером.

Типичные проблемы

Следующее сообщение об ошибке говорит о том, что вы забыли создать файл postgresql.conf в каталоге данных:

FileNotFoundError: [Errno 2] No such file or directory: '/pgdata/cluster1/postgresql.conf' -> '/pgdata/cluster1/postgresql.base.conf'

Если забыть создать пользователя primaryuser, в логах появится следующее:

psycopg2.OperationalError: FATAL:  password authentication failed for user "primaryuser"

Из-за неправильных или отсутствующих параметров доступа к объектному хранилищу возникает следующая ошибка:

WARN: repo1: [CryptoError] unable to load info file '/on-prem-pg/backup/db/backup.info' or '/on-prem-pg/backup/db/backup.info.copy':      CryptoError: raised from remote-0 protocol on 'cluster1-backrest-shared-repo': unable to read PEM: [218529960] wrong tag            HINT: is or was the repo encrypted?                                                                                                 CryptoError: raised from remote-0 protocol on 'cluster1-backrest-shared-repo': unable to read PEM: [218595386] nested asn1 error
      HINT: is or was the repo encrypted?
      HINT: backup.info cannot be opened and is required to perform a backup.
      HINT: has a stanza-create been performed?
ERROR: [075]: no backup set found to restore
Fri Jul 30 10:54:00 UTC 2021 ERROR: pgBackRest standby Creation: pgBackRest restore failed when creating standby

Переключение

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

1. Остановите исходный кластер PostgreSQL, чтобы исключить вероятность записи данных во время переключения:

systemctl stop postgresql

2. Сделайте целевой кластер основным. Для этого удалите параметр spec.backup.repoPath и измените значение параметра spec.standby на false в файле deploy/cr.yaml. Затем примените изменения:

kubectl apply -f deploy/cr.yaml

PostgreSQL автоматически перезапустится, а в логах появится следующее:

2021-07-30 11:16:20,020 INFO: updated leader lock during promote
2021-07-30 11:16:20,025 INFO: Changed archive_mode from on to True (restart might be required)
2021-07-30 11:16:20,025 INFO: Changed max_wal_senders from 10 to 6 (restart might be required)
2021-07-30 11:16:20,027 INFO: Reloading PostgreSQL configuration.
server signaled
2021-07-30 11:16:21,037 INFO: Lock owner: cluster1-5dfb96f77d-n4c79; I am cluster1-5dfb96f77d-n4c79
2021-07-30 11:16:21,132 INFO: no action.  i am the leader with the lock

Заключение

Развертывание кластеров баз данных и управление ими — непростая задача. Недавно выпущенный дистрибутив Percona для PostgreSQL Operator позволяет автоматизировать операции по настройке и вводу в эксплуатацию PostgreSQL на Kubernetes, превращая это мероприятие в слаженный процесс без лишней головной боли.

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

Рекомендуем испробовать решение Operator: см. репозиторий на GitHub и документацию.

Нашли баг или хотите предложить новую возможность для разработки? Отправьте запрос в JIRA.

Общие вопросы можно задавать на форуме сообщества.

Если вы разработчик и хотите внести вклад в проект, ознакомьтесь с инструкцией CONTRIBUTING.md и отправляйте pull-запросы.

В дистрибутиве Percona для PostgreSQL объединены наилучшие компоненты с открытым исходным кодом, необходимые для развертывания СУБД в корпоративной среде. Все компоненты протестированы с точки зрения взаимной совместимости.


Материал подготовлен в рамках курса «PostgreSQL». Если вам интересно узнать подробнее о формате обучения и программе, познакомиться с преподавателем курса — приглашаем на день открытых дверей онлайн. Регистрация здесь.

Источник: https://habr.com/ru/company/otus/blog/576730/


Интересные статьи

Интересные статьи

В прошлой части были рассмотрены рекомендации по множеству механизмов Kubernetes для оптимального деплоя высокодоступных приложений включая особенности работы планировщик...
Kubernetes отличная платформа оркестрации контейнеров и для всего остального. За последнее время Kubernetes ушёл далеко вперёд как по части функциональности так и по вопр...
Я уже как-то рассказывал про особенности вычисления условий в SQL вообще и в PostgreSQL, в частности. Сегодня продолжим тему и попробуем написать и пооптимизировать простой запрос — у ког...
Jacky Parker Photography / Getty Images Компания Robin, автор одноименного cloud-native решения для управления данными и приложениями корпоративных клиентов, например USAA, Sabre, SAP,...
Если в вашей компании хотя бы два сотрудника, отвечающих за работу со сделками в Битрикс24, рано или поздно возникает вопрос распределения лидов между ними.