Миграция PostgreSQL в Kubernetes

Kate

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

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

Цель​

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

5ff604416d604390783c402ae4121448.png

  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 объединены наилучшие компоненты с открытым исходным кодом, необходимые для развертывания СУБД в корпоративной среде. Все компоненты протестированы с точки зрения взаимной совместимости.

 
Сверху