Миграция с Bitnami на CloudNative-PG в Kubernetes

Почему стоит уйти от чартов Bitnami?

Если вы запускаете PostgreSQL на Kubernetes, скорее всего, вы уже пользовались популярными Helm-чартами от Bitnami. Долгое время они были первым выбором для многих, однако на горизонте назревают серьёзные перемены. Как описано в этом GitHub-issue, Bitnami переводит свои production-ready чарты и образы на коммерческую модель. Для тех, кто опирается на открытые решения и продвигает их, это сигнал: пора искать надёжную альтернативу.

Именно здесь на сцену выходит CloudNative-PG.

Знакомство с CloudNative-PG

CloudNative-PG — это Kubernetes-оператор (operator), созданный для управления полным жизненным циклом кластеров PostgreSQL. В основе его философии лежит декларативный, облачно-нативный (cloud-native) подход к управлению базами данных. В марте 2024 года проект был принят в CNCF на стадии incubating, что подтверждает его зрелость и поддержку со стороны сообщества.

Среди ключевых возможностей оператора:

  • Декларативное управление: весь кластер PostgreSQL — роли, базы данных, конфигурации — описывается в одном YAML-файле.

  • Высокая доступность и самовосстановление: автоматический failover и восстановление гарантируют работоспособность базы данных без ручного вмешательства.

  • Встроенный мониторинг: поставляется с экспортером для Prometheus, что упрощает интеграцию в существующий стек наблюдаемости (observability).

  • Удобный импорт данных: предоставляет простой механизм переноса данных из существующей базы PostgreSQL — именно то, что нужно для миграции.

В этом руководстве мы пройдём весь путь: развернём новый кластер PostgreSQL с помощью CloudNative-PG и импортируем данные из базы, ранее управлявшейся Helm-чартом Bitnami.

Шаг 1: Установка оператора CloudNative-PG

Для начала нужно установить оператор в кластер Kubernetes. Оператор включает в себя определения пользовательских ресурсов (Custom Resource Definitions, CRDs), с помощью которых мы будем описывать наши кластеры баз данных.

Следующая команда устанавливает последнюю версию оператора:

kubectl apply --server-side -f \
https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-1.27/releases/cnpg-1.27.0.yaml

Небольшой совет: флаг --server-side здесь рекомендован. Манифест оператора довольно объёмный, и этот флаг помогает избежать проблем с инструментами вроде ArgoCD, которые могут не справляться с большими ресурсами.

Шаг 2: Настройка кластера и импорт данных

Теперь самое интересное. Мы опишем новый кластер PostgreSQL с помощью ресурса Cluster. В том же манифесте будет указана конфигурация для импорта данных из старой базы под управлением Bitnami.

Ниже приведён полный манифест, который мы разберём по частям. Он содержит три основных ресурса:

  • Cluster: сам кластер PostgreSQL.

  • Pooler: пул соединений PgBouncer для обеспечения высокой доступности.

  • PodMonitor: ресурс для сбора метрик Prometheus.

Ресурс Cluster

Это центральный ресурс нашей базы данных PostgreSQL. Рассмотрим ключевые параметры:

  • .spec.instances: создаём кластер из трёх узлов для высокой доступности. CloudNative-PG обеспечит, что один узел будет первичным (primary), а остальные — репликами с потоковой репликацией (streaming replication standbys).

  • .spec.managed.roles: роль пользователя test объявляется прямо в манифесте — пример декларативного управления ролями.

  • .spec.externalClusters: ключ к нашей миграции. Здесь мы описываем ссылку на старую базу данных, которую оператор использует для подключения и организации импорта данных. В поле host нужно указать сервис существующего PostgreSQL.

  • .spec.bootstrap.initdb.import: эта секция указывает оператору инициализировать новый кластер, импортировав данные из указанного externalCluster. Параметр type: microservice используется для импорта одной базы данных.

  • .spec.storage: здесь задаётся хранилище для базы данных — 8 Гб из storage class gp3.

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: postgres
spec:
managed:
roles:
- name: test
ensure: present
instances: 3
imageName: ghcr.io/cloudnative-pg/postgresql:17.5
externalClusters: # Create the reference for the external cluster
- name: source-db
connectionParameters:
host: test-postgresql-ha-pgpool.test.svc.cluster.local # Using K8s DNS
user: postgres
sslmode: disable
dbname: test
password: # Use the password located in my secret test-postgresql
name: test-postgresql
key: PASSWORD
bootstrap:
initdb: # Automatic migration
database: test
owner: test
import:
type: microservice # Only that database for the postgresql
databases:
- test
source:
externalCluster: source-db
enableSuperuserAccess: true
storage:
size: 8Gi
storageClass: gp3
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 1000m
memory: 1Gi
---

Пул соединений (Connection Pooler)

Пул соединений, такой как PgBouncer, необходим для управления подключениями в конфигурации с высокой доступностью. Он защищает первичную базу данных от шторма соединений (connection storm), особенно во время failover.

  • .spec.cluster.name: привязывает пулер к нашему кластеру postgres.

  • .spec.instances: запускаем две реплики пулера для отказоустойчивости.

  • .spec.pgbouncer.poolMode: режим session — распространённый и безопасный выбор, при котором клиент удерживает соединение на протяжении всей сессии.

  • .spec.type: rw: настраивает пулер на работу с первичным экземпляром кластера в режиме чтения-записи (read-write).

apiVersion: postgresql.cnpg.io/v1
kind: Pooler # Because I'm going to use it in HA
metadata:
name: "pooler-postgres"
spec:
cluster:
name: postgres
instances: 2
pgbouncer:
poolMode: session
type: rw
---

Ресурс PodMonitor

CloudNative-PG поставляется со встроенным экспортером метрик для Prometheus. Ресурс PodMonitor, входящий в API Prometheus Operator, сообщает Prometheus, как обнаруживать и собирать метрики с подов PostgreSQL.

  • .spec.selector.matchLabels: этот селектор выбирает поды, принадлежащие нашему кластеру postgres.

  • .metadata.labels: метка release: kube-prometheus-stack важна — она часто используется Prometheus Operator для обнаружения нужных PodMonitor-ресурсов. В вашей среде может потребоваться другая метка.

apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
annotations:
cnpg.io/operatorVersion: 1.27.0
labels:
cnpg.io/cluster: postgres
release: kube-prometheus-stack # I need this label to allow Prometheus scrape metrics.
name: postgres
spec:
namespaceSelector: {}
podMetricsEndpoints:
- bearerTokenSecret:
key: ""
name: ""
port: metrics
selector:
matchLabels:
cnpg.io/cluster: postgres
cnpg.io/podRole: instance

Шаг 3: Проверка миграции

После применения манифеста CloudNative-PG начнёт подготовку кластера. Следить за прогрессом можно с помощью команды kubectl get cluster postgres -w.

Через несколько минут кластер должен быть готов. Главный вопрос: был ли импорт данных выполнен корректно?

Проверим это. Сначала найдём имя сервиса нового пулера:

kubectl get svc -l cnpg.io/cluster=postgres,cnpg.io/podRole=pooler -o name

Затем запустим временный под с PostgreSQL, подключимся к сервису пулера и воспользуемся psql для проверки базы данных. Оператор создаёт секрет для суперпользователя postgres; по умолчанию он называется postgres-superuser.

# Note: The secret name might be different based on your cluster name.
# It follows the pattern <cluster-name>-superuser.
PGPASSWORD=$(kubectl get secret postgres-superuser --template={{.data.password}} | base64 -d)
# Now connect to the database
kubectl run psql-client --rm -it --image=postgres --command -- psql "postgresql://postgres:${PGPASSWORD}@pooler-postgres-rw:5432/test" -c "\dt"

Эта команда выводит список таблиц в базе данных test. Если вы видите таблицы из исходной базы — поздравляем, импорт прошёл успешно!

Важные замечания

Несколько моментов, о которых стоит помнить:

  • Метки PodMonitor: чтобы ресурс PodMonitor был обнаружен Prometheus, необходимо задать правильные метки. В большинстве стандартных установок kube-prometheus-stack требуется метка release: kube-prometheus-stack, однако в вашей конфигурации может быть иначе. Всегда проверяйте настройки Prometheus.

  • Управление внешними секретами: при указании секретов для внешних кластеров документация CloudNative-PG явно регламентирует ожидаемые ключи (username, password). Использование других ключей не допускается.

Данное руководство охватывает первоначальный импорт данных — наиболее критичный этап. Для полного переключения в production также потребуется спланировать время простоя приложения, обновить деплойменты приложений, указав новый сервис базы данных (pooler-postgres-rw), и вывести из эксплуатации старый деплой Bitnami.

Заключение

Экосистема облачно-нативных инструментов постоянно развивается, и изменения в каталоге Bitnami лишний раз напоминают о важности опоры на проекты, движимые сообществом. CloudNative-PG — зрелое и мощное решение для запуска PostgreSQL на Kubernetes.

Декларативный API, встроенная высокая доступность и тесная интеграция с экосистемой Kubernetes делают его отличной альтернативой для инженеров платформы (platform engineers), которые ценят гибкость и контроль. Миграция требует тщательного планирования, но результатом становится современная, масштабируемая и удобная в обслуживании инфраструктура базы данных — по-настоящему cloud-native.

Об авторе

Я архитектор платформенной инженерии (Platform Engineer Architect), специализирующийся на облачно-нативных технологиях и инженерном лидерстве. Я фокусируюсь на построении эффективных совместных инженерных процессов и документации. Являюсь Golden Kubestronaut и увлечён Cloud Native технологиями.

Свяжитесь со мной в LinkedIn или напишите мне для получения дополнительной информации.

© 2026 meganuke