Skip to main content

Restore PostgreSQL (CloudNativePG)

This document describes how to restore a CloudNativePG cluster from backups or VolumeSnapshots.

Recovery Options

CloudNativePG supports multiple recovery methods:

  1. Barman Cloud Backup - Restore from S3-stored backups
  2. VolumeSnapshot - Restore from Longhorn snapshots
  3. pg_basebackup - Clone from an existing cluster

Recovery from Barman Cloud Backup

Prerequisites

  • ObjectStore resource configured with S3 credentials
  • Existing backups in the S3 bucket
  • CNPG operator running

Recovery Cluster Manifest

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: <app>-db-recovered
namespace: <namespace>
spec:
instances: 1
imageName: ghcr.io/cloudnative-pg/postgresql:18

storage:
size: 20Gi
storageClass: longhorn

bootstrap:
recovery:
source: <app>-backup

externalClusters:
- name: <app>-backup
plugin:
name: barman-cloud.cloudnative-pg.io
parameters:
barmanObjectName: <app>-minio-store

Point-in-Time Recovery (PITR)

To recover to a specific point in time:

bootstrap:
recovery:
source: <app>-backup
recoveryTarget:
targetTime: "2024-01-15 10:30:00"

Recovery from VolumeSnapshot

Prerequisites

  • Longhorn VolumeSnapshot exists
  • Snapshot contains valid PGDATA

Create Snapshot (if needed)

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
name: <app>-pgdata-backup
namespace: <namespace>
spec:
volumeSnapshotClassName: longhorn-snapshot
source:
persistentVolumeClaimName: <app>-db-1

Recovery from Snapshot

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: <app>-db-recovered
namespace: <namespace>
spec:
instances: 1
imageName: ghcr.io/cloudnative-pg/postgresql:18

storage:
size: 20Gi
storageClass: longhorn

bootstrap:
recovery:
volumeSnapshots:
storage:
name: <app>-pgdata-backup
kind: VolumeSnapshot
apiGroup: snapshot.storage.k8s.io

Verification Steps

Check Cluster Status

# Watch cluster initialization
kubectl get cluster <cluster-name> -n <namespace> -w

# Check pod logs during recovery
kubectl logs -n <namespace> <cluster-name>-1 -f

Verify Data Integrity

# Port forward to the cluster
kubectl port-forward -n <namespace> svc/<cluster-name>-rw 5432:5432 &

# Connect and verify
psql -h localhost -U <user> -d <database> -c '\dt'
psql -h localhost -U <user> -d <database> -c 'SELECT COUNT(*) FROM <table>;'

Troubleshooting

Cluster Stuck in Recovery

Check operator logs:

kubectl logs -n cnpg-system deployment/cnpg-controller-manager --tail=100

VolumeSnapshot Issues

Verify snapshot is ready:

kubectl get volumesnapshot -n <namespace>
kubectl describe volumesnapshot <snapshot-name> -n <namespace>

Permission Issues

CNPG expects PGDATA owned by UID/GID 26:26. If restoring from a foreign snapshot:

# Check permissions inside the pod
kubectl exec -n <namespace> <pod-name> -- ls -la /var/lib/postgresql/data/

Post-Recovery Tasks

  1. Update application configs - Point applications to the new cluster service
  2. Verify credentials - Check the auto-generated <cluster-name>-app secret
  3. Enable backups - Add ObjectStore and ScheduledBackup resources
  4. Scale replicas - Increase instances after primary is healthy

Reference

For detailed disaster recovery scenarios, see Zalando to CNPG Migration which documents a real-world recovery case.