Управляемый сервис PostgreSQL
PostgreSQL в настоящее время является лидирующим выбором среди реляционных баз данных и известен своей надёжной функциональностью и производительностью. Управляемый сервис PostgreSQL использует реализацию на стороне платформы для предоставления самовосстанавливающегося реплицируемого кластера. Этот кластер эффективно управляется с помощью широко признанного оператора CloudNativePG, получившего популярность в сообществе.
Детали развёртывания
Этот управляемый сервис контролируется оператором CloudNativePG, обеспечивающим эффективное управление и бесперебойную работу.
- Документация: https://cloudnative-pg.io/docs/
- Github: https://github.com/cloudnative-pg/cloudnative-pg
Операции
Резервное копирование PostgreSQL имеет два уровня, и в рекомендуемой конфигурации используются оба уровня вместе, а не один из них:
| Слой | Что делает | Настраивается через |
|---|---|---|
| Архивная инфраструктура (чарт, устаревший вариант) | Формирует spec.plugins (со ссылкой на barman-cloud ObjectStore) в ресурсе Cluster cnpg.io начиная с helm-install. CNPG запускает плагин barman-cloud как сайдкар-архиватор WAL: каждое переключение WAL отправляется в объектное хранилище, и любой драйвер резервного копирования получает полную цепочку WAL для начала воспроизведения. Формируется только когда backup.enabled=true, useSystemBucket=false, destinationPath не пусто И заданы встроенные или внешние учётные данные. Пропускается в платформенном режиме useSystemBucket=true — драйвер резервного копирования CNPG применяет ObjectStore через SSA и патчит spec.plugins на живом Cluster в момент первого BackupJob; до этого момента архивирование WAL через плагин не активно, и WAL накапливается на PVC. Запустите разовый BackupJob сразу после включения флага на существующих релизах. | Устаревший вариант: backup.enabled=true плюс backup.destinationPath, backup.endpointURL, и либо backup.s3AccessKey+backup.s3SecretKey, либо backup.s3CredentialsSecret. Платформенный: backup.enabled=true плюс backup.useSystemBucket=true — без полей S3. |
| Оркестрация резервного копирования (рекомендуется) | Управляет разовыми и плановыми резервными копиями, политикой хранения и восстановлениями на основе ресурсов backups.cozystack.io, которые могут охватывать несколько приложений Postgres в тенанте. Драйвер применяет собственный barman-cloud ObjectStore через SSA и патчит spec.plugins с ForceOwnership (так что настройки сжатия/цели берутся из шаблона стратегии, при этом serverName живого Cluster — его префикс S3 для архива WAL — всегда сохраняется); значения, управляемые чартом, покрывают тот же пункт назначения, поэтому конфликта на живом Cluster не возникает. | strategy.backups.cozystack.io/CNPG + BackupClass + Plan (регулярное) или BackupJob (разовое), восстановление через RestoreJob |
| Устаревшее плановое резервное копирование, формируемое чартом | Чарт также может напрямую формировать cnpg.io/ScheduledBackup. Заменён путём BackupClass + Plan, оставлен для кластеров, которые не были мигрированы. Отключён по умолчанию — формируется только когда заданы одновременно backup.enabled и backup.schedule. При backup.schedule="" архивирование WAL через плагин продолжает работать; отключается только формируемое чартом плановое резервное копирование. | backup.enabled=true плюс backup.schedule (cron в формате CNPG из 6 полей, например "0 2 * * * *") |
Канонический вариант настройки зависит от того, поставляется ли в кластере платформенный BackupClass cozy-default.
Платформенный вариант (рекомендуется для новых кластеров) — включается через backup.useSystemBucket: true со ссылкой на cozy-default в BackupJob/Plan/RestoreJob. Чарт оставляет координаты S3 пустыми; драйвер CNPG применяет barman-cloud ObjectStore через SSA и патчит spec.plugins координатами управляемого платформой бакета в момент первого BackupJob.
spec:
backup:
enabled: true
useSystemBucket: true # platform projects cozy-backups-creds + driver SSA-applies ObjectStore + patches spec.plugins
Устаревший вариант, управляемый чартом — для кластеров, созданных до появления платформенного BackupClass, или использующих настроенный нестандартный бакет. Укажите все координаты S3 напрямую (или через s3CredentialsSecret.name); spec.plugins и barman-cloud ObjectStore формируются начиная с helm-install.
spec:
backup:
enabled: true # архивировать WAL в объектное хранилище
destinationPath: s3://my-bucket/pg-src/
endpointURL: https://seaweedfs-s3.tenant-foo:8333
s3CredentialsSecret:
name: pg-src-cnpg-backup-creds
endpointCA:
name: pg-src-cnpg-backup-ca
# backup.schedule намеренно оставлен пустым — BackupClass / Plan
# ниже управляют повторяющимся резервным копированием; никакой
# формируемый чартом ScheduledBackup не должен конкурировать с этим расписанием.
в паре со strategy.backups.cozystack.io/CNPG + BackupClass + Plan
в том же тенанте. Сквозной e2e-фикстур в
examples/backups/postgres/ служит
каноническим примером (05-postgres-src.yaml показывает сторону чарта,
10-cnpg-strategy.yaml и 15-backupclass.yaml показывают сторону
оркестрации, 25-backupjob-adhoc.yaml и 40-restorejob-to-copy.yaml показывают
разовое резервное копирование и восстановление).
Почему нужны оба уровня, а не один? Архивирование WAL выполняется сайдкар-архиватором плагина barman-cloud — CNPG может подключать или отключать плагин во время работы, но любой WAL, закрытый до начала архивирования плагином, теряется безвозвратно. В резервной копии, снятой с такого кластера, отсутствует WAL, на который указывает её
begin_wal, и последующее восстановление завершается ошибкойWAL not found. Если чарт подключает плагин с момента helm-install, эта гонка исключается.
Как включить резервное копирование (предпочтительно: BackupClass + Plan)
Сквозные манифесты находятся в
examples/backups/postgres/.
Кратко, задействованные компоненты:
strategy.backups.cozystack.io/CNPGописывает целевой бакет и шаблонизирует barman-cloudObjectStore(включая ссылку на Secret с учётными данными S3 — эти учётные данные никогда не появляются в.specCR Postgres; см. примечание о безопасности ниже).backups.cozystack.io/BackupClassназывает стратегию и выбирается черезapplicationRef, соответствующийKind/Nameприложения Postgres.backups.cozystack.io/Plan(регулярный) илиBackupJob(разовый), ссылающийся на BackupClass. Контроллер материализует артефактBackup, когда завершается Backup cnpg.io; восстановления затем ссылаются на этот Backup черезRestoreJob.
Поддерживаются как восстановление на месте (перезапись данных исходного приложения), так и
восстановление в копию (восстановление в отдельное целевое приложение Postgres в том же
пространстве имён) через поле
RestoreJob.spec.targetApplicationRef.
Безопасность: при использовании пути BackupClass учётные данные S3 хранятся в доступном тенанту Secret, на который ссылается шаблон стратегии. Драйвер CNPG передаёт эту ссылку на Secret в поле
spec.backup.s3CredentialsSecretприложения Postgres при восстановлении, поэтому ключи доступа никогда не попадают в.specCR Postgres, объектное хранилище etcd или выводkubectl get -o yaml. Предпочитайте этот путь управляемому чартом варианту, когда это возможно.
Как включить управляемые чартом плановые резервные копии (устаревший вариант)
Чарт также может напрямую формировать cnpg.io/ScheduledBackup без
BackupClass. Заменён путём BackupClass + Plan выше и оставлен
для кластеров, которые не были мигрированы. По умолчанию не работает —
backup.schedule по умолчанию является пустой строкой, что отключает
шаблон ScheduledBackup чарта. Чтобы включить, укажите cron-выражение
CNPG из 6 полей:
## @param backup.enabled Включить архивирование WAL через плагин + сформировать управляемый чартом ScheduledBackup
## @param backup.schedule Cron-расписание (формат CNPG из 6 полей). Пусто означает отсутствие управляемого чартом ScheduledBackup
## @param backup.retentionPolicy Политика хранения
## @param backup.destinationPath Путь для хранения резервной копии (например, s3://bucket/path/to/folder)
## @param backup.endpointURL Конечная точка S3, используемая для загрузки данных в облако
## @param backup.s3AccessKey Ключ доступа для S3, используемый для аутентификации
## @param backup.s3SecretKey Секретный ключ для S3, используемый для аутентификации
backup:
enabled: true
retentionPolicy: 30d
destinationPath: s3://bucket/path/to/folder/
endpointURL: http://minio-gateway-service:9000
schedule: "0 2 * * * *" # включение — пусто (по умолчанию) означает отсутствие управляемого чартом расписания
s3AccessKey: oobaiRus9pah8PhohL1ThaeTa4UVa7gu
s3SecretKey: ju3eum4dekeich9ahM1te8waeGai0oog
Как восстановить из резервной копии (предпочтительно: RestoreJob)
Для резервных копий, управляемых через BackupClass, создайте backups.cozystack.io/RestoreJob,
ссылающийся на нужный Backup. См.
examples/backups/postgres/35-restorejob-in-place.yaml
и
examples/backups/postgres/40-restorejob-to-copy.yaml.
При восстановлении в копию контроллер заменяет spec.databases и spec.users
целевого приложения снимком исходного spec, сохранённым
в Backup.status.underlyingResources, так что post-install init-job чарта
не теряет восстановленные роли или базы данных.
Покрытие e2e: восстановление в копию в том же пространстве имён (шаги 0-7) оставляет исходное приложение работающим и служит детерминированным сквозным сигналом; остаётся ручным / dev-cluster эталонным сценарием, не входящим в автоматизированный набор e2e-тестов. Кросс-тенантный вариант (целевой Postgres в другом тенанте, отличном от seaweedfs источника) остаётся ручным / dev-cluster упражнением — доступность заблокирована политикой исходящего трафика Cilium на уровне тенанта. Кодовый путь восстановления на месте поставляется и покрыт на уровне модульных тестов
TestClusterHasRecoveryBootstrap_TerminatingCluster,TestCNPGBackupWALArchived,TestCNPGPurgeNeededи остальными тестами набораinternal/backupcontroller/cnpgstrategy_controller_test.go.
Как восстановить резервную копию (управляемая чартом начальная загрузка)
CloudNativePG поддерживает восстановление на момент времени (point-in-time-recovery). Восстановление резервной копии выполняется путём создания нового экземпляра базы данных и восстановления в него данных.
Создайте новое приложение PostgreSQL с другим именем, но идентичной конфигурацией.
Установите bootstrap.enabled в true и укажите имя экземпляра базы данных, из которого нужно восстановиться, и время восстановления:
## @param bootstrap.enabled Восстановить кластер базы данных из резервной копии
## @param bootstrap.recoveryTime Метка времени (PITR), до которой будет выполнено восстановление, в формате RFC 3339. Если оставить пустым, будет восстановлена последняя
## @param bootstrap.oldName Имя кластера базы данных до удаления
##
bootstrap:
enabled: false
recoveryTime: "" # оставьте пустым для последней или укажите точную метку времени; пример: 2020-11-26 15:22:00.00000+00
oldName: "<previous-postgres-instance>"
Как переключить первичную/вторичную реплику
См.:
storageClassпомечен как неизменяемый (immutable) в схеме чарта — см.docs/storage-immutability.md, где описан этот контракт и какие потребители его обеспечивают.
TLS для серверных подключений
CNPG управляет цепочкой сертификатов сквозным образом. Оператор автоматически генерирует самоподписанный CA, подписывает им конечные (leaf) сертификаты сервера, клиента и репликации и ротирует их по мере необходимости. Чарт не формирует никаких объектов Issuer/Certificate cert-manager — этот путь взаимоисключающий с управляемой оператором цепочкой на admission webhook CNPG.
Что добавляет чарт: когда TLS включён и external: true, чарт устанавливает spec.certificates.serverAltDNSNames в ресурсе CNPG Cluster CR, чтобы внедрить внешнее имя хоста <release>.<_namespace.host> в список SAN автоматически сгенерированного серверного сертификата. Стандартное покрытие SAN в CNPG уже включает три встроенных сервиса ClusterIP (-rw, -r, -ro) во всех четырёх формах DNS (<svc>, <svc>.<ns>, <svc>.<ns>.svc, <svc>.<ns>.svc.<cluster-domain>); требуется добавить только внешнее имя хоста.
Трёхпозиционный параметр tls.enabled определяет, внедряет ли чарт serverAltDNSNames:
tls.enabled: null(по умолчанию) — режим TLS наследуется отexternal. Приexternal: trueчарт внедряет внешнее имя хоста в управляемый оператором сертификат.tls.enabled: trueприexternal: true— эффект тот же, что и по умолчанию.tls.enabled: trueприexternal: false— внедрениеserverAltDNSNamesне требуется (внешнего имени хоста для добавления нет); автоматически сгенерированный сертификат CNPG покрывает внутренние сервисы.tls.enabled: false— чарт пропускает внедрениеserverAltDNSNames. Примечание: CNPG сохраняет встроенный TLS на уровне соединения независимо от этого флага; данный переключатель управляет лишь тем, добавляется ли внешнее имя хоста в сертификат. Чтобы полностью отключить TLS в PostgreSQL, потребовалось бы установитьpostgresql.parameters.ssl = "off"на уровне CNPG, что выходит за рамки этого флага.
Получение CA-бандла для проверки на стороне клиента:
CNPG включает сертификат CA в каждый создаваемый им Secret с учётными данными пользователя под ключом ca.crt. Получите его из Secret <release>-credentials, который уже доступен тенантам через RBAC дашборда:
kubectl --context <ctx> --namespace <tenant> \
get secret <release>-credentials \
--output jsonpath='{.data.ca\.crt}' | base64 --decode
Подключение с полной проверкой (пример psql):
psql "host=<host> port=5432 dbname=app user=app \
sslmode=verify-full sslrootcert=ca.crt"
Чтобы sslmode=verify-full работал, полученный выше CA-бандл должен быть сохранён в ca.crt. Без него используйте sslmode=require (шифрует, но не проверяет серверный сертификат).
Параметры
Общие параметры
| Имя | Описание | Тип | Значение |
|---|---|---|---|
replicas | Количество реплик Postgres. | int | 2 |
resources | Явная конфигурация CPU и памяти для каждой реплики PostgreSQL. Если не задано, применяется пресет, указанный в resourcesPreset. | object | {} |
resources.cpu | CPU, доступный каждой реплике. | quantity | "" |
resources.memory | Память (RAM), доступная каждой реплике. | quantity | "" |
resourcesPreset | Пресет размера по умолчанию, используемый, когда resources не задан. | string | t1.micro |
size | Размер Persistent Volume Claim, доступный для данных приложения. | quantity | 10Gi |
storageClass | StorageClass, используемый для хранения данных. | string | "" |
external | Включить внешний доступ извне кластера. | bool | false |
version | Мажорная версия PostgreSQL для развёртывания | string | v18 |
Конфигурация TLS
| Имя | Описание | Тип | Значение |
|---|---|---|---|
tls | Конфигурация TLS для серверных подключений. | object | {} |
tls.enabled | Трёхпозиционный переключатель, определяющий, внедряет ли чарт внешнее имя хоста в управляемый оператором сертификат CNPG через spec.certificates.serverAltDNSNames. Если не задан, чарт внедряет SAN при external: true и пропускает в противном случае. Установите явно в true, чтобы внедрять независимо от external (не имеет эффекта при external: false, так как внешнего имени хоста для добавления нет). Установите в false, чтобы пропустить внедрение. Учтите, что CNPG сохраняет встроенный TLS на уровне соединения независимо от этого флага — данный переключатель управляет лишь внедрением SAN на стороне чарта; чтобы полностью отключить TLS в PostgreSQL, установите postgresql.parameters.ssl = "off" на уровне CNPG. | *bool | null |
Параметры, специфичные для приложения
| Имя | Описание | Тип | Значение |
|---|---|---|---|
postgresql | Конфигурация сервера PostgreSQL. | object | {} |
postgresql.parameters | Параметры сервера PostgreSQL. Значения могут быть строками или целыми числами; целые числа приводятся к строкам шаблоном (например, принимаются и max_connections: 100, и max_connections: "100"). ЗАБЛОКИРОВАНЫ (позволяют выполнение произвольного кода): archive_command, restore_command, ssl_passphrase_command, archive_cleanup_command, recovery_end_command, dynamic_library_path, local_preload_libraries, session_preload_libraries, shared_preload_libraries. НЕ переопределяйте параметры, управляемые CloudNativePG: archive_mode, primary_conninfo, wal_level, max_replication_slots. | map[string]intOrString | {} |
Синхронная репликация на основе кворума
| Имя | Описание | Тип | Значение |
|---|---|---|---|
quorum | Конфигурация кворума для синхронной репликации. | object | {} |
quorum.minSyncReplicas | Минимальное число синхронных реплик, необходимое для фиксации (commit). | int | 0 |
quorum.maxSyncReplicas | Максимально допустимое число синхронных реплик (должно быть меньше общего числа реплик). | int | 0 |
Конфигурация пользователей
| Имя | Описание | Тип | Значение |
|---|---|---|---|
users | Карта конфигурации пользователей. | map[string]object | {} |
users[name].password | Пароль пользователя. | string | "" |
users[name].replication | Имеет ли пользователь привилегии репликации. | bool | false |
Конфигурация баз данных
| Имя | Описание | Тип | Значение |
|---|---|---|---|
databases | Карта конфигурации баз данных. | map[string]object | {} |
databases[name].roles | Роли, назначенные пользователям. | object | {} |
databases[name].roles.admin | Список пользователей с правами администратора. | []string | [] |
databases[name].roles.readonly | Список пользователей с правами только на чтение. | []string | [] |
databases[name].extensions | Список включённых расширений PostgreSQL. | []string | [] |
Параметры резервного копирования
| Имя | Описание | Тип | Значение |
|---|---|---|---|
backup | Конфигурация резервного копирования. | object | {} |
backup.enabled | Включить регулярное резервное копирование. | bool | false |
backup.useSystemBucket | Опциональная функция: при true пропускается формируемый чартом Secret <release>-s3-creds, И spec.plugins (а также barman-cloud ObjectStore) остаётся НЕ ЗАДАННЫМ в формируемом чартом Cluster — драйвер BackupClass cozy-default применяет ObjectStore через SSA (с destinationPath/endpointURL/учётными данными) и патчит spec.plugins на живом Cluster при запуске первого BackupJob. Следствие: архивирование WAL через плагин НЕ активно до момента срабатывания этого первого BackupJob; тем временем WAL накапливается на PVC, поэтому запустите разовый BackupJob сразу после включения флага на существующих релизах. Используйте вместе с платформенным BackupClass cozy-default — тенантам не нужно заполнять s3AccessKey/s3SecretKey или destinationPath/endpointURL. Путь назначения автоматически ограничивается s3://cozy-backups/<namespace>/<release>/. | bool | false |
backup.schedule | Устаревшее. Cron-расписание (формат CNPG из 6 полей) для формируемого чартом ScheduledBackup. Пусто означает отсутствие управляемого чартом расписания, что является рекомендуемой настройкой, когда BackupClass из backups.cozystack.io уже управляет оркестрацией резервного копирования. В устаревшем управляемом чартом варианте spec.plugins вместе с barman-cloud ObjectStore формируется, когда backup.enabled=true И useSystemBucket=false И destinationPath не пусто И заданы встроенные или внешние учётные данные; в платформенном варианте useSystemBucket=true чарт пропускает формирование spec.plugins, а драйвер CNPG применяет ObjectStore через SSA и патчит spec.plugins на живом Cluster в момент первого BackupJob. | string | "" |
backup.retentionPolicy | Политика хранения (например, “30d”). | string | 30d |
backup.destinationPath | УСТАРЕЛО. Настройка S3 на уровне тенанта заменена управляемым платформой BackupClass cozy-default и системным бакетом cozy-backups. Оставьте пустым для новых установок; драйвер BackupClass использует управляемые системой координаты. Сохранено для совместимости при обновлении на месте. | string | s3://bucket/path/to/folder/ |
backup.endpointURL | УСТАРЕЛО. См. destinationPath. | string | http://minio-gateway-service:9000 |
backup.s3AccessKey | УСТАРЕЛО. Тенанты больше не предоставляют ключи S3; системный Secret с бакетом проецируется в пространство имён тенанта контроллером резервного копирования. Игнорируется, если задан s3CredentialsSecret.name или useSystemBucket равен true. Чарт пропускает материализацию <release>-s3-creds, если это поле пустое, чтобы стандартная установка не раскрывала заглушки учётных данных в пространство имён тенанта. | string | "" |
backup.s3SecretKey | УСТАРЕЛО. См. s3AccessKey. | string | "" |
backup.s3CredentialsSecret | УСТАРЕЛО. Существующий Secret с учётными данными S3. Используйте вместо этого управляемый платформой BackupClass cozy-default. Если задан, чарт ссылается на этот Secret напрямую (устаревший управляемый чартом вариант). Драйвер резервного копирования CNPG записывает это поле при восстановлении, поэтому учётные данные никогда не попадают в .spec CR. | object | {} |
backup.s3CredentialsSecret.name | Имя Secret в пространстве имён приложения. Пусто означает, что чарт материализует <release>-s3-creds из s3AccessKey/s3SecretKey. | string | "" |
backup.s3CredentialsSecret.accessKeyIDKey | Ключ в Secret, содержащий идентификатор ключа доступа. По умолчанию AWS_ACCESS_KEY_ID. | string | "" |
backup.s3CredentialsSecret.secretAccessKeyKey | Ключ в Secret, содержащий секретный ключ доступа. По умолчанию AWS_SECRET_ACCESS_KEY. | string | "" |
backup.endpointCA | УСТАРЕЛО. Существующий Secret с пакетом CA, которому должен доверять плагин barman-cloud при обращении к самоподписанной конечной точке S3. Используется как для резервного копирования, так и для восстановления при начальной загрузке в устаревшем управляемом чартом варианте. | object | {} |
backup.endpointCA.name | Имя Secret в пространстве имён приложения. Пусто означает, что endpointCA не формируется (плагин использует системное хранилище доверия). | string | "" |
backup.endpointCA.key | Ключ в Secret, содержащий пакет CA. По умолчанию ca.crt. | string | "" |
Параметры начальной загрузки (восстановления)
| Имя | Описание | Тип | Значение |
|---|---|---|---|
bootstrap | Конфигурация начальной загрузки. | object | {} |
bootstrap.enabled | Восстанавливать ли из резервной копии. | bool | false |
bootstrap.recoveryTime | Метка времени (RFC3339) для восстановления на момент времени; пусто означает последнюю. | string | "" |
bootstrap.oldName | Имя предыдущего кластера до удаления. | string | "" |
bootstrap.serverName | Имя сервера (префикс пути S3), использовавшееся исходным кластером при записи резервных копий; передаётся в плагин barman-cloud через externalClusters[].plugin.parameters.serverName. По умолчанию равно bootstrap.oldName. Задавайте только когда исходный кластер писал резервные копии под явным именем сервера, отличающимся от имени его ресурса Kubernetes. | string | "" |
bootstrap.newServerName | WAL-archive server name (префикс пути в S3), в который пишет ВОССТАНОВЛЕННЫЙ кластер. Должен отличаться от serverName (источника восстановления), чтобы восстановленный кластер архивировал данные в новый, пустой префикс, и barman-cloud-check-wal-archive проходил проверку, пока идёт восстановление из префикса источника. Драйвер резервного копирования CNPG устанавливает это значение при восстановлении; если оно пустое, кластер архивирует данные под собственным именем. | string | "" |
Примеры и справочник по параметрам
resources и resourcesPreset
resources задаёт явные конфигурации CPU и памяти для каждой реплики.
Если оставить пустым, применяется пресет, указанный в resourcesPreset.
resources:
cpu: 4000m
memory: 4Gi
resourcesPreset задаёт именованные конфигурации CPU и памяти для каждой реплики.
Эта настройка игнорируется, если задано соответствующее значение resources.
Пресеты следуют облачной схеме именования <серия>.<размер>. Пять серий покрывают весь диапазон соотношений CPU к памяти (t1 1:0.5, c1 1:1, s1 1:2, u1 1:4, m1 1:8), и каждая серия поставляется с восемью размерами (от nano до 4xlarge). Устаревшие плоские имена (nano, micro, small, medium, large, xlarge, 2xlarge) по-прежнему принимаются как устаревшие псевдонимы соответствующих типов инстансов с соотношением 1:1.
См.
docs/operations/resource-presets.md, где приведены полная матрица размеров и сопоставление устаревших имён с типами инстансов.
users
users:
user1:
password: strongpassword
user2:
password: hackme
airflow:
password: qwerty123
debezium:
replication: true
databases
databases:
myapp:
roles:
admin:
- user1
- debezium
readonly:
- user2
airflow:
roles:
admin:
- airflow
extensions:
- hstore