KubeBlocks
BlogsKubeBlocks Cloud
⌘K
​
Overview
Quickstart

Operations

Lifecycle Management
Vertical Scaling
Horizontal Scaling
Volume Expansion
Manage PostgreSQL Services
Minor Version Upgrade
Modify PostgreSQL Parameters
PostgreSQL Switchover
Decommission PostgreSQL Replica
Recovering PostgreSQL Replica

Backup And Restores

Create BackupRepo
Create Full Backup
Scheduled Backups
Scheduled Continuous Backup
Restore PostgreSQL Cluster
Restore with PITR

Custom Secret

Custom Password
Custom Password Policy

TLS

PostgreSQL Cluster with TLS
PostgreSQL Cluster with Custom TLS

Monitoring

Observability for PostgreSQL Clusters
FAQs

tpl

  1. What is PITR?
  2. Prerequisites
  3. Prerequisites for Backup
  4. Deploy a PostgreSQL Cluster, with pg-basebackup and archive-wal
  5. Verifying the Deployment
    1. Monitor the Cluster Status
    2. Check Backups are Scheduled Correctly
    3. Verify Backup Configuration
  6. Deploy a PostgreSQL Cluster, with wal-g and wal-g-archive
  7. How to check the progress of continuous backup
  8. Summary

Setting Up a PostgreSQL Cluster with Scheduled Continuous Backup Enabled in KubeBlocks

This guide demonstrates how to configure a PostgreSQL cluster on KubeBlocks with:

  • Scheduled full backups (base backups)
  • Continuous WAL (Write-Ahead Log) archiving
  • Point-In-Time Recovery (PITR) capabilities

This combination provides comprehensive data protection with minimal recovery point objectives (RPO).

What is PITR?

Point-In-Time Recovery (PITR) allows you to restore a database to a specific moment in time by combining full backups with continuous binlog/wal/archive log backups.

For details on restoring data from both full backups and continuous binlog backups, refer to the Restore From PITR guide.

Prerequisites

Before proceeding, ensure the following:

  • Environment Setup:
    • A Kubernetes cluster is up and running.
    • The kubectl CLI tool is configured to communicate with your cluster.
    • KubeBlocks CLI and KubeBlocks Operator are installed. Follow the installation instructions here.
  • Namespace Preparation: To keep resources isolated, create a dedicated namespace for this tutorial:
kubectl create ns demo namespace/demo created

Prerequisites for Backup

  1. Backup Repository Configured:

    • Configured BackupRepo
    • Network connectivity between cluster and repo, BackupRepo status is Ready
  2. Cluster is Running:

    • Cluster must be in Running state
    • No ongoing operations (scaling, upgrades etc.)
  3. Check the list of backup methods.

    As introduced in the Create Full Backup guide, KubeBlocks PostgreSQL supports these backup methods:

    FeatureMethodDescription
    Full Backuppg-basebackupUses pg_basebackup, a PostgreSQL utility to create a base backup
    Full Backupwal-gUses wal-g to create a full backup (requires WAL-G configuration)
    Continuous Backuparchive-walUploads PostgreSQL Write-Ahead Logging (WAL) files periodically to the backup repository, usually paired with pg-basebackup
    Continuous Backupwal-g-archiveUploads PostgreSQL Write-Ahead Logging (WAL) files periodically to the backup repository, usually paired with wal-g
    NOTE
    • It is recommended to pair pg-basebackup with archive-wal, and pair wal-g with wal-g-archive.
    • Method pg-basebackup can be enabled alone to create a full backup.
    • Method wal-g cannot be enabled alone. It must be paired with wal-g-archive.

    In this guide, we will show how to deploy a PostgreSQL cluster with different combinations of backup methods. You may choose one of the following combinations.

    • pg-basebackup and archive-wal
    • wal-g and wal-g-archive (Recommended)

Deploy a PostgreSQL Cluster, with pg-basebackup and archive-wal

Deploy a 2-node PostgreSQL replication cluster (1 primary, 1 secondary) and specify backup information.

apiVersion: apps.kubeblocks.io/v1 kind: Cluster metadata: name: pg-cluster namespace: demo spec: terminationPolicy: Delete clusterDef: postgresql topology: replication componentSpecs: - name: postgresql serviceVersion: 16.4.0 disableExporter: true replicas: 2 resources: limits: cpu: "0.5" memory: "0.5Gi" requests: cpu: "0.5" memory: "0.5Gi" volumeClaimTemplates: - name: data spec: accessModes: - ReadWriteOnce resources: requests: storage: 20Gi backup: retentionPeriod: 7d # for full backup method: pg-basebackup # full backup methnod name enabled: true cronExpression: 0 18 * * * # full backup scheuler # for continuous backup continuousMethod: archive-wal # continuous backup method pitrEnabled: true # enable continous method or not repoName: s3-repo # specify backuprepo, if not specified, the BackupRepo annotated as `default` will be used.

Or you can patch an existing cluster to enable scheduled continuous backup:

kubectl patch cluster pg-cluster -n demo --type='merge' -p=' { "spec": { "backup": { "retentionPeriod": "7d", "method": "pg-basebackup", "enabled": true, "cronExpression": "0 18 * * *", "continuousMethod": "archive-wal", "pitrEnabled": true, "repoName": "s3-repo" } } }'

Key Configuration Fields Explained

FieldValueDescription
backup.enabledtrueEnables scheduled backups
methodpg-basebackupFull backup method using PostgreSQL's native utility
cronExpression0 18 * * *Daily full backup at 6PM UTC
retentionPeriod7dRetains backups for 7 days
repoNames3-repoBackup repository name (S3-compatible storage)
pitrEnabledtrueEnables continuous WAL archiving for PITR
continuousMethodarchive-walMethod for continuous WAL archiving

Verifying the Deployment

Monitor the Cluster Status

Monitor the cluster status until it transitions to the Running state:

kubectl get cluster pg-cluster -n demo -w

Example Output:

NAME CLUSTER-DEFINITION TERMINATION-POLICY STATUS AGE pg-cluster postgresql Delete Creating 50s pg-cluster postgresql Delete Running 4m2s

Once the cluster status becomes Running, your PostgreSQL cluster is ready for use.

Check Backups are Scheduled Correctly

Verify full backup and continuous backups are configured correctly:

  1. Check full backup task is scheduled correctly. KubeBlocks create CronJob to schedule full backup.

    kubectl get cronjob -l app.kubernetes.io/instance=pg-cluster,app.kubernetes.io/managed-by=kubeblocks-dataprotection -n demo
  2. Check continuous backup is RUNNING correctly. KubeBlocks create a StatefulSet to run continuous backup.

    kubectl get sts -l app.kubernetes.io/instance=pg-cluster,app.kubernetes.io/managed-by=kubeblocks-dataprotection -n demo
  3. Check continuous Backup resource is created correctly.

    kubectl get backup -l app.kubernetes.io/instance=pg-cluster,app.kubernetes.io/managed-by=kubeblocks-dataprotection,dataprotection.kubeblocks.io/backup-type=Continuous -n demo

    Example Output:

    NAME POLICY METHOD REPO STATUS TOTAL-SIZE DURATION DELETION-POLICY CREATION-TIME COMPLETION-TIME EXPIRATION-TIME b387c27b-pg-cluster-postgresql-archive-wal pg-cluster-postgresql-backup-policy archive-wal <BACKUP_REPO> Running Delete 2025-05-16T02:58:10Z

Verify Backup Configuration

KubeBlocks automatically creates a BackupSchedule resource. Inspect the configuration:

kubectl get backupschedule pg-cluster-postgresql-backup-schedule -n demo -oyaml

Example Output:

apiVersion: dataprotection.kubeblocks.io/v1alpha1 kind: BackupSchedule ... spec: backupPolicyName: pg-cluster-postgresql-backup-policy schedules: - backupMethod: pg-basebackup cronExpression: 0 18 * * * enabled: true retentionPeriod: 7d - backupMethod: archive-wal cronExpression: '*/5 * * * *' enabled: true name: archive-wal retentionPeriod: 7d

Deploy a PostgreSQL Cluster, with wal-g and wal-g-archive

Deploy a 2-node PostgreSQL replication cluster (1 primary, 1 secondary)

apiVersion: apps.kubeblocks.io/v1 kind: Cluster metadata: name: pg-cluster namespace: demo spec: terminationPolicy: Delete clusterDef: postgresql topology: replication componentSpecs: - name: postgresql serviceVersion: 16.4.0 disableExporter: true replicas: 2 resources: limits: cpu: "0.5" memory: "0.5Gi" requests: cpu: "0.5" memory: "0.5Gi" volumeClaimTemplates: - name: data spec: accessModes: - ReadWriteOnce resources: requests: storage: 20Gi backup: retentionPeriod: 7d # for full backup method: wal-g # full backup methnod name enabled: true cronExpression: 0 18 * * * # full backup scheuler # for continuous backup continuousMethod: wal-g-archive # continuous backup method pitrEnabled: true # enable continous method or not repoName: s3-repo # specify backuprepo, if not specified, the BackupRepo annotated as `default` will be used.

Or you can patch an existing cluster to enable scheduled continuous backup:

kubectl patch cluster pg-cluster -n demo --type='merge' -p=' { "spec": { "backup": { "retentionPeriod": "7d", "method": "wal-g", "enabled": true, "cronExpression": "0 18 * * *", "continuousMethod": "wal-g-archive", "pitrEnabled": true, "repoName": "s3-repo" } } }'

You may use the steps introduced in the Deploy a PostgreSQL Cluster, with wal-g and wal-g-archive section to check the deployment of the cluster.

Apart from that, you need to check if archive_command is configured correctly.

NOTE

Method wal-g and wal-g-archive work only when PostgreSQL's archive_command is configured properly.

Kubeblocks will do it automatically for you when method wal-g-archive is enabled.

KubeBlocks will create a Reconfiguration OpsRequest to set the archive_command to envdir /home/postgres/pgdata/wal-g/env /home/postgres/pgdata/wal-g/wal-g wal-push %p

To monitor the progress of the reconfiguration, you can check the status of the OpsRequest:

kubectl get opsrequest -l app.kubernetes.io/instance=pg-cluster,operations.kubeblocks.io/ops-type=Reconfiguring -n demo

If the OpsRequest is Failed or is Pending for quite a long time, you need to check the logs of the OpsRequest to see the error message. Otherwise the wal-g-archive and wal-g will not work.

How to check the progress of continuous backup

Each continuous backup methods upload WAL files to the backup repository periodically (every few seconds).

TIP

If there is no wal log to upload, the backup pod has nothing to do. Then backup's total-size won't increase and backup's timeRange won't change.

You may perform a sysbench benchmark against the cluster or you can run the python script pg_benchmark.py to benchmark the cluster.

Check the progress of continuous backup by following the steps below:

  1. checking the backup resource.

    kubectl get backup -l app.kubernetes.io/instance=pg-cluster,dataprotection.kubeblocks.io/backup-type=Continuous -n demo

    Example Output:

    NAME POLICY METHOD REPO STATUS TOTAL-SIZE DURATION DELETION-POLICY CREATION-TIME COMPLETION-TIME EXPIRATION-TIME b387c27b-pg-cluster-postgresql-archive-wal pg-cluster-postgresql-backup-policy archive-wal <BACKUP_REPO> Running 104325519 Delete 2025-05-16T02:58:10Z
    • TOTAL-SIZE is the total size of the WAL files uploaded to the backup repository. It will increase over time.
  2. checking the backup pod logs.

    kubectl logs b387c27b-pg-cluster-postgresql-archive-wal-0 -n demo -c backupdata

    where b387c27b-pg-cluster-postgresql-archive-wal-0 is the name of the backup pod, and backupdata is the container name.

    Example Output:

    2025-05-16 06:36:12 INFO: start to upload the wal log which maybe misses 2025-05-16 06:36:13 INFO: start to archive wal logs 2025-05-16 06:46:14 INFO: start to switch wal file 2025-05-16 06:56:16 INFO: start to switch wal file 2025-05-16 07:05:18 INFO: upload 000000010000000000000004 2025-05-16 07:05:20 INFO: upload 000000010000000000000005 2025-05-16 07:06:17 INFO: upload 000000010000000000000006 2025-05-16 07:09:44 INFO: upload 000000010000000000000007 2025-05-16 07:09:46 INFO: upload 000000010000000000000008 2025-05-16 07:09:48 INFO: upload 000000010000000000000009 ...
    kubectl logs b387c27b-pg-cluster-postgresql-wal-g-archive-0 -n demo -c backupdata

    Where b387c27b-pg-cluster-postgresql-wal-g-archive-0 is the name of the backup pod, and backupdata is the container name.

    Example Output:

    2025-05-16 08:16:59 INFO: start to archive and update wal infos 2025-05-16 08:16:59 INFO: config wal-g environment variables... 2025-05-16 08:25:18 INFO: upload 000000010000000000000022 ... INFO: 2025/09/08 08:25:18.904842 Files will be uploaded to storage: default INFO: 2025/09/08 08:25:22.729796 FILE PATH: 000000010000000000000023.zst INFO: 2025/09/08 08:25:22.845932 FILE PATH: 000000010000000000000022.zst 2025-05-16 08:25:22 INFO: WAL-G upload succeeded for 000000010000000000000022 2025-05-16 08:25:22 INFO: upload 000000010000000000000023 ... INFO: 2025/09/08 08:25:22.883391 Files will be uploaded to storage: default 2025-05-16 08:25:22 INFO: WAL-G upload succeeded for 000000010000000000000023 2025-05-16 08:25:24 INFO: start time of the oldest wal: 2025-05-16T08:09:45Z, end time of the latest wal: 2025-05-16T08:25:17Z, total size: 14938340 2025-05-16 08:26:23 INFO: upload 000000010000000000000024 ... INFO: 2025/09/08 08:26:23.166320 Files will be uploaded to storage: default INFO: 2025/09/08 08:26:25.738435 FILE PATH: 000000010000000000000025.zst INFO: 2025/09/08 08:26:25.784766 FILE PATH: 000000010000000000000024.zst 2025-05-16 08:26:25 INFO: WAL-G upload succeeded for 000000010000000000000024 2025-05-16 08:26:25 INFO: upload 000000010000000000000025 ... INFO: 2025/09/08 08:26:25.822544 Files will be uploaded to storage: default 2025-05-16 08:26:25 INFO: WAL-G upload succeeded for 000000010000000000000025 2025-05-16 08:26:27 INFO: start time of the oldest wal: 2025-05-16T08:09:45Z, end time of the latest wal: 2025-05-16T08:26:20Z, total size: 29775523
  3. checking the backup's timeRange, it should increase over time.

    kubectl get backup b387c27b-pg-cluster-postgresql-archive-wal -n demo -oyaml | yq '.status.timeRange'

    where b387c27b-pg-cluster-postgresql-archive-wal is the name of the continuous backup.

    Example Output:

    timeRange: end: "2025-05-16T07:09:48Z" start: "2025-05-16T06:36:12Z"
    • timeRange.start is the start time of the backup (earliest PostgreSQL transaction time).
    • timeRange.end is the end time of the backup (latest PostgreSQL transaction time).

Summary

This guide covered:

  1. Configuring scheduled full backups with pg-basebackup
  2. Enabling continuous WAL archiving with wal-g-archive
  3. Setting up Point-In-Time Recovery (PITR) capabilities
  4. Monitoring backup operations

Key Benefits:

  • Scheduled full backups ensure regular recovery points
  • Continuous WAL archiving minimizes potential data loss
  • PITR enables recovery to any moment in time

© 2025 ApeCloud PTE. Ltd.