Все больше компаний внедряют Kubernetes как из интереса к передовым технологиям, так и в рамках стратегии по трансформации бизнеса. Когда дело касается переноса приложений в контейнеры и инфраструктуру Kubernetes, перед разработчиками и специалистами по эксплуатации встают непростые задачи, если приложения изначально не ориентированы на облако.
Миграция баз данных всегда сопряжена с рисками и простоями для бизнеса. Сегодня я продемонстрирую, насколько легко можно перенести базу данных PostgreSQL в Kubernetes с минимальными простоями. В этом мне поможет дистрибутив Percona для PostgreSQL Operator.
Цель
Для выполнения миграции я буду использовать следующую конфигурацию:
База данных PostgreSQL, развернутая локально или где-то в облаке. Эту базу данных будем называть источником.
Кластер Google Kubernetes Engine (GKE), на котором будет развернуто решение Percona Operator для управления целевым кластером PostgreSQL и подом pgBackRest.
Резервные копии и журналы предзаписи PostgreSQL загружаются в какой-либо бакет объектного хранилища (в моем случае — GCS).
Данные из бакета считываются с помощью пода pgBackRest.
Этот же под непрерывно восстанавливает данные в кластер 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». Если вам интересно узнать подробнее о формате обучения и программе, познакомиться с преподавателем курса — приглашаем на день открытых дверей онлайн. Регистрация здесь.