PostgresCluster
Scope: namespaced · Backend: CloudNativePG (type: cnpg)
Shared PostgreSQL with per-consumer databases inside one cluster. Engine is pluggable via type; cnpg is implemented, zalando and cockroachdb are scaffolded.
Spec
| Field | Type | Description |
|---|---|---|
type | enum cnpg (default) | zalando | cockroachdb | Backend implementation |
mode | enum managed | adopt | external (required) | Provenance mode |
managed | object | Settings when mode: managed |
adopt | object | Reference to an existing CNPG Cluster |
external | object | Connection secret for an external database |
databases[] | list | Databases to ensure inside the cluster (one per consuming workload) |
managed
| Field | Default | Description |
|---|---|---|
instances | 3 | CNPG HA replica count |
storageSize | — | PVC size per instance |
storageClass | cluster default | StorageClass |
resources | — | CPU/memory requests & limits |
backup | disabled | Scheduled backups to object storage (see backup) |
backup
Off by default. When enabled, the operator configures CNPG's object-store backups (in-tree Barman) and continuous WAL archiving — giving you scheduled full backups and point-in-time recovery. It emits the Cluster.spec.backup block plus a ScheduledBackup. Credentials come from a Secret via SecretsManagement — never inline.
| Field | Default | Description |
|---|---|---|
enabled | false | Turn on scheduled backups + WAL archiving |
provider | s3 | s3, azure, or gcs |
s3 / azure / gcs | — | Provider block (the one matching provider is required) |
schedule | 0 0 2 * * * | 6-field cron with seconds (CNPG format, not 5-field) — default daily 02:00 |
retentionPolicy | 30d | Recovery-window retention, e.g. 30d, 4w |
Provider blocks — each takes a destinationPath plus credentials (or a workload-identity escape so no static keys are stored):
| Provider | destinationPath | Credentials Secret keys | Workload identity |
|---|---|---|---|
s3 | s3://bucket/path (+ optional endpointURL for MinIO/R2) | access-key-id, secret-access-key | inheritFromIAMRole: true |
azure | https://<acct>.blob.core.windows.net/<container>/ | connection-string | inheritFromAzureAD: true |
gcs | gs://bucket/path | credentials (service-account JSON) | gkeEnvironment: true |
The destinationPath must include a container/bucket segment — a bare https://<acct>.blob.core.windows.net/ (Azure) or s3:// with no bucket produces a backup target that can't be written. The ClickHouse and MongoDB backup jobs reject a container-less path with a BackupMisconfigured warning event on the datastore rather than emitting a CronJob whose pods fail.
adopt / external
| Field | Description |
|---|---|
adopt.clusterRef | An existing CNPG Cluster (postgresql.cnpg.io/v1); namespace is optional and may point at another namespace — see cross-namespace adoption |
external.connectionSecretRef | Secret holding a DATABASE_URL |
databases[]
| Field | Description |
|---|---|
name | Database name |
owner | Owning role (optional) |
credentialsSecretName | Secret the operator materializes for the consumer |
Workloads that reference this cluster get their database even when it is not declared here, with the auto-wiring licence; status.databases[].claimedBy shows who uses each. A database name Kubernetes cannot use in object names (for example langfuse_prod) gets a sanitized name for its CNPG Database and credentials Secret. See Databases for workloads that reference a datastore.
Behavior by mode
managed(type: cnpg) — ensures thecloudnative-pgoperator, creates a CNPGCluster, and creates a CNPGDatabase(plus role and credentials Secret) perdatabases[]entry.adopt— resolves the referencedCluster, ensures the databases inside it, and never touches the cluster's lifecycle. When the cluster lives in another namespace the CNPGDatabaseresources are created beside it (CNPG resolvesDatabase.spec.clusterin theDatabase's own namespace), while the consumer credentials Secret is still materialized in this namespace. Deleting this resource removes thoseDatabaseCRs — never the adopted cluster.external— exposes the suppliedDATABASE_URL; no operator is installed.zalando/cockroachdb— scaffolded; the resource reportsReady=Falsewith reasonBackendNotImplemented.
Example — managed, two databases
apiVersion: core.navique.com/v1alpha1
kind: PostgresCluster
metadata:
name: forge-pg
namespace: forge-data
spec:
type: cnpg
mode: managed
managed:
instances: 3
storageSize: 20Gi
databases:
- { name: litellm, credentialsSecretName: litellm-db-credentials }
- { name: langfuse, credentialsSecretName: langfuse-db-credentials }Example — external (bring your own managed Postgres)
spec:
type: cnpg
mode: external
external:
connectionSecretRef: { name: azure-postgres, key: DATABASE_URL }
databases:
- { name: litellm, credentialsSecretName: litellm-db-credentials }Example — managed with scheduled S3 backups
spec:
type: cnpg
mode: managed
managed:
instances: 3
storageSize: 20Gi
backup:
enabled: true
provider: s3
schedule: "0 0 2 * * *" # daily 02:00 (6-field cron: sec min hour dom mon dow)
retentionPolicy: 30d
s3:
destinationPath: s3://forge-backups/pg
# endpointURL: https://minio.example.com:9000 # for S3-compatible stores
credentialsSecretRef: { name: pg-backup } # keys: access-key-id, secret-access-key
databases:
- { name: litellm, credentialsSecretName: litellm-db-credentials }Restore
A managed Postgres is backed up continuously by CNPG (base backups + WAL archiving), so restore is a point-in-time recovery (PITR) into a new cluster that bootstraps from the same object store — CNPG never restores in place. Create a second Cluster with a bootstrap.recovery source pointing at the backup barmanObjectStore; the navique operator does not model restore as a CRD, so apply the CNPG Cluster directly:
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata: { name: forge-pg-restored, namespace: forge }
spec:
instances: 1
bootstrap:
recovery:
source: forge-pg
# recoveryTarget: { targetTime: "2026-06-27 14:00:00+00" } # omit = latest
externalClusters:
- name: forge-pg
barmanObjectStore:
destinationPath: s3://my-bucket/postgres
s3Credentials:
accessKeyId: { name: pg-backup, key: access-key-id }
secretAccessKey: { name: pg-backup, key: secret-access-key }Once forge-pg-restored is healthy, repoint workloads (or swap the PostgresCluster to mode: adopt referencing it). Full reference: CNPG recovery. The auto-created Lock protects the original from accidental deletion during recovery — keep it until you've confirmed the restored data.
Sharing across workloads
A single PostgresCluster typically backs both the Gateway (litellm DB) and Langfuse (langfuse DB). Each consumer references the cluster and names its database; the operator provisions an isolated database and credentials Secret per consumer.
Status
Exposes connection coordinates and, per database, readiness and the credentials Secret name, plus the standard conditions and observedGeneration.