CloudNativePG: Run a PostgreSQL cluster using Barman Cloud Plugin

Published at 23 Jun 2025

The built-in support for Barman Cloud on CloudNativePG is deprecated since version 1.26 and will be removed in a future release. So new clusters should be created using the new plugin-based architecture using the Barman Cloud Plugin.

If you're already running a cluster with Barman Cloud, the official documentation has a guide about how to migrate it to the new plugin: https://cloudnative-pg.io/plugin-barman-cloud/docs/migration.

In this tutorial we'll create a new using the Barman Cloud Plugin from scratch.

Install CloudNativePG

To install CloudNativePG, first you should check the latest version on GitHub.

Once you know what's the latest version, adapt the following command to it:

kubectl apply --server-side -f \
  https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-1.26/releases/cnpg-1.26.0.yaml

Keep in mind the version must be 1.26 or newer.

You can check the version running the following command:

kubectl get deployment -n cnpg-system cnpg-controller-manager -o yaml \
  | grep ghcr.io/cloudnative-pg/cloudnative-pg

It should output something similar to this:

image: ghcr.io/cloudnative-pg/cloudnative-pg:1.26.0

Checking cert-manager

You should make sure your cluster has cert-manager up and running before you continue to the next steps.

Installing the Barman Cloud Plugin

To install the Barman Cloud Plugin, first you should check the latest version on GitHub.

Once you know what's the latest version, adapt the following command to it:

kubectl apply -f \
  https://github.com/cloudnative-pg/plugin-barman-cloud/releases/download/v0.5.0/manifest.yaml

Once it's installed, you can check that the deployment is up and running:

kubectl rollout status deployment -n cnpg-system barman-cloud

It should output something like this if it's ready:

deployment "barman-cloud" successfully rolled out

Setting up the cluster

To set up a cluster using the Barman Cloud Plugin we should:

Defining the Object Store

First, we're going to create the object store definition, I'm using R2 as my storage provider, but you can use another compatible one.

vi object-store.yaml
apiVersion: barmancloud.cnpg.io/v1
kind: ObjectStore
metadata:
  name: postgresql-object-store
  namespace: postgresql
spec:
  configuration:
    destinationPath: s3://postgresql-k8s/
    endpointURL: https://<account-id>.r2.cloudflarestorage.com
    s3Credentials:
      accessKeyId:
        name: r2-credentials
        key: ACCESS_KEY_ID
      secretAccessKey:
        name: r2-credentials
        key: ACCESS_SECRET_KEY
    wal:
      compression: bzip2
      encryption: AES256
    data:
      compression: bzip2
      encryption: AES256
      jobs: 2
  retentionPolicy: "30d"

And we apply it.

kubectl apply -f object-store.yaml

Configuring the cluster

Now we're going to create the PostgreSQL cluster that will use our object store.

vi cluster.yaml
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: postgresql-cluster
  namespace: postgresql
spec:
  instances: 3
  imagePullPolicy: Always
  plugins:
  - name: barman-cloud.cloudnative-pg.io
    isWALArchiver: true
    parameters:
      barmanObjectName: postgresql-object-store
      serverName: postgresql-v1
  storage:
    size: 4Gi

This definition will create 3 instances of PostgreSQL with the WAL archiver enabled using the configuration from the object store we created before.

Now we apply it.

kubectl apply -f cluster.yaml

Performing a base backup

Once our cluster is up and running, we'll make an on-demand backup.

vi backup.yaml
apiVersion: postgresql.cnpg.io/v1
kind: Backup
metadata:
  name: postgresql-cluster-backup
  namespace: postgresql
spec:
  cluster:
    name: postgresql-cluster
  method: plugin
  pluginConfiguration:
    name: barman-cloud.cloudnative-pg.io

And we apply it.

kubectl apply -f backup.yaml

Restoring the custer from a backup

Once the backup has been finished successfully, we're going to restore the cluster. The following definition will restore the backup and enable the WAL archiver on the new cluster.

We can use this definition if we need to restore the cluster anytime in the future, you should only keep in mind to increase the version on both serverName so the new cluster doesn't override the old one.

vi restore.yaml
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: postgresql-cluster
  namespace: postgresql
spec:
  instances: 3
  imagePullPolicy: Always
  bootstrap:
    recovery:
      source: source
  plugins:
  - name: barman-cloud.cloudnative-pg.io
    isWALArchiver: true
    parameters:
      barmanObjectName: postgresql-object-store
      serverName: postgresql-v2
  externalClusters:
  - name: source
    plugin:
      name: barman-cloud.cloudnative-pg.io
      parameters:
        barmanObjectName: postgresql-object-store
        serverName: postgresql-v1
  storage:
    size: 4Gi

Now we apply it.

kubectl apply -f cluster.yaml

Configuring a scheduled backup

We can configure a scheduled backup so the cluster stores a backup on any schedule we want.

vi scheduled-backup.yaml
apiVersion: postgresql.cnpg.io/v1
kind: ScheduledBackup
metadata:
  name: postgresql-scheduled-backup
  namespace: postgresql
spec:
  schedule: "0 0 0 * * *"  # At midnight every day
  cluster:
    name: postgresql-cluster
  backupOwnerReference: self
  method: plugin
  pluginConfiguration:
    name: barman-cloud.cloudnative-pg.io

And we apply it.

kubectl apply -f scheduled-backup.yaml

Finally, we have configured our PostgreSQL cluster using Barman Cloud Plugin, feel free to adapt this definitions to your preferences.