Skip to content

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 ​

FieldTypeDescription
typeenum cnpg (default) | zalando | cockroachdbBackend implementation
modeenum managed | adopt | external (required)Provenance mode
managedobjectSettings when mode: managed
adoptobjectReference to an existing CNPG Cluster
externalobjectConnection secret for an external database
databases[]listDatabases to ensure inside the cluster (one per consuming workload)

managed ​

FieldDefaultDescription
instances3CNPG HA replica count
storageSize—PVC size per instance
storageClasscluster defaultStorageClass
resources—CPU/memory requests & limits
backupdisabledScheduled 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.

FieldDefaultDescription
enabledfalseTurn on scheduled backups + WAL archiving
providers3s3, azure, or gcs
s3 / azure / gcs—Provider block (the one matching provider is required)
schedule0 0 2 * * *6-field cron with seconds (CNPG format, not 5-field) — default daily 02:00
retentionPolicy30dRecovery-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):

ProviderdestinationPathCredentials Secret keysWorkload identity
s3s3://bucket/path (+ optional endpointURL for MinIO/R2)access-key-id, secret-access-keyinheritFromIAMRole: true
azurehttps://<acct>.blob.core.windows.net/<container>/connection-stringinheritFromAzureAD: true
gcsgs://bucket/pathcredentials (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 ​

FieldDescription
adopt.clusterRefAn existing CNPG Cluster (postgresql.cnpg.io/v1); namespace is optional and may point at another namespace — see cross-namespace adoption
external.connectionSecretRefSecret holding a DATABASE_URL

databases[] ​

FieldDescription
nameDatabase name
ownerOwning role (optional)
credentialsSecretNameSecret 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 the cloudnative-pg operator, creates a CNPG Cluster, and creates a CNPG Database (plus role and credentials Secret) per databases[] entry.
  • adopt — resolves the referenced Cluster, ensures the databases inside it, and never touches the cluster's lifecycle. When the cluster lives in another namespace the CNPG Database resources are created beside it (CNPG resolves Database.spec.cluster in the Database's own namespace), while the consumer credentials Secret is still materialized in this namespace. Deleting this resource removes those Database CRs — never the adopted cluster.
  • external — exposes the supplied DATABASE_URL; no operator is installed.
  • zalando / cockroachdb — scaffolded; the resource reports Ready=False with reason BackendNotImplemented.

Example — managed, two databases ​

yaml
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) ​

yaml
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 ​

yaml
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:

yaml
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.

Open core under AGPL-3.0. Enterprise components are proprietary and license-gated.