CNPG-I Backup Plugin Architecture#
CNPG-I (CloudNativePG Interface) is a gRPC-based plugin protocol that lets external processes extend the CloudNativePG operator. Backup-related behavior is split across three services that a plugin may expose: Backup, WAL, and RestoreJobHooks. A plugin advertises which services it supports via the Identity service GetPluginCapabilities RPC, which returns capability tokens such as TYPE_BACKUP_SERVICE, TYPE_WAL_SERVICE, and TYPE_RESTORE_JOB.
The reference implementation is plugin-barman-cloud, which handles physical backups and WAL archiving/restore via Barman Cloud.
Backup Service#
The Backup service exposes two RPCs:
| RPC | Purpose |
|---|---|
GetCapabilities | Declares which backup operations the plugin supports (must include TYPE_BACKUP) |
Backup | Takes a physical backup of PostgreSQL |
The operator passes JSON-serialized Cluster and Backup objects to the plugin. The plugin responds with a BackupResult containing required fields (backup_id, started_at, stopped_at, online) and optional provenance fields (begin_wal, end_wal, begin_lsn, end_lsn, backup_label_file). A freeform metadata map lets plugins store plugin-specific data alongside the Backup CR.
Before dispatching the RPC, the operator checks both that the plugin reports TYPE_BACKUP_SERVICE in its identity capabilities and TYPE_BACKUP in its backup-service capabilities. If either check fails, the backup is rejected before the network call.
WAL Service#
The WAL service exposes five RPCs:
| RPC | Capability Token | Purpose |
|---|---|---|
Archive | TYPE_ARCHIVE_WAL | Copies one WAL file into the archive |
Restore | TYPE_RESTORE_WAL | Retrieves a WAL file from the archive |
Status | TYPE_STATUS | Returns first_wal / last_wal bounds of the archive |
SetFirstRequired | TYPE_SET_FIRST_REQUIRED | Tells the plugin the oldest WAL it must keep (for retention) |
WALRestoreRequest includes a Mode enum (MODE_RECOVERY vs MODE_REWIND) so plugins can handle pg_rewind fetches differently—avoiding WAL prefetching and ignoring cached misses, because pg_rewind treats any restore failure as fatal.
Plugin Status Surfacing in the Cluster CR#
Each plugin can set an arbitrary JSON blob in the Cluster.status.plugins[<name>].status field via the SetStatusInCluster Operator RPC . The operator calls this at the end of every reconciliation loop. The PluginStatus struct on the Cluster CR also stores which service capabilities and backup capabilities the plugin declared.
Recoverability Metadata via ObjectStore CR#
For the barman-cloud plugin, backup recovery metadata is not written to the Cluster CR. Instead, the plugin maintains it in its own ObjectStore custom resource under status.serverRecoveryWindow[<serverName>] :
ObjectStoreStatus
└── ServerRecoveryWindow: map[string]RecoveryWindow
└── RecoveryWindow
├── FirstRecoverabilityPoint *metav1.Time
├── LastSuccessfulBackupTime *metav1.Time
└── LastFailedBackupTime *metav1.Time
The plugin updates this status in two places:
- After each successful backup —
updateRecoveryWindow()reads the backup catalog (catalog.GetFirstRecoverabilityPoint(),catalog.GetLastSuccessfulBackupTime()) and writes toObjectStore.Status. - After each failed backup —
setLastFailedBackupTime()setsLastFailedBackupTimeusing retry-on-conflict to avoid race conditions against the controller loop. - During retention enforcement —
updateRecoveryWindowis also called after the retention policy run so the window reflects any expired backups.
The Cluster CR fields FirstRecoverabilityPoint, LastSuccessfulBackup, and LastFailedBackup are deprecated for plugin-based backups and are not populated when a backup plugin is in use . The ObjectStore CR is the authoritative source.
Status Command Integration#
The kubectl-cnpg status command bridges the two worlds:
- PR #8690 added detection of the barman-cloud plugin (
barman-cloud.cloudnative-pg.io) inCluster.spec.pluginsso the command no longer reports "Not configured" when the native.spec.backupis absent. - PR #8780 added a
getBarmanObject()function that queriesbarmancloud.cnpg.io/v1/objectstoresand displays the ObjectStore'sServerRecoveryWindow— first recoverability point, last successful backup, and last failed backup — directly in the status output.
Key Source References#
| Component | File |
|---|---|
| Backup gRPC contract | proto/backup.proto |
| WAL gRPC contract | proto/wal.proto |
| Full protocol reference | docs/protocol.md |
| Operator Backup RPC dispatch | internal/cnpi/plugin/client/backup.go |
| ObjectStore CRD types | api/v1/objectstore_types.go |
| Recovery window update logic | internal/cnpgi/instance/recovery_window.go |
| Cluster PluginStatus types | api/v1/cluster_types.go |