Project: KubeDB by AppsCode (App Definition and Development / Database)
File: archiver.md

title: Continuous Archiving and Point-in-time Recovery menu: docs_{{ .version }}: identifier: pitr-postgres-archiver name: Overview parent: pitr-postgres weight: 10 menuname: docs{{ .version }} sectionmenuid: guides New to KubeDB? Please start . Here, will show you how to use KubeDB to provision a PostgreSQL to Archive continuously and Restore point-in-time. At first, you need to have a Kubernetes cluster, and the kubectl command-line tool must be configured to communicate with your cluster. If you do not already have a cluster, you can create one by using . Now,install `KubeDB` operator in your cluster following the steps . To install `KubeStash` operator in your cluster following the steps . To install `SideKick` in your cluster following the steps . To install `External-snapshotter` in your cluster following the steps . To keep things isolated, this tutorial uses a separate namespace called `demo` throughout this tutorial. ```bash $ kubectl create ns demo namespace/demo created ``` Note: The yaml files used in this tutorial are stored in folder in GitHub repository . Continuous archiving involves making regular copies (or "archives") of the PostgreSQL transaction log files.To ensure continuous archiving to a remote location we need prepare `BackupStorage`,`RetentionPolicy`,`PostgresArchiver` for the KubeDB Managed PostgreSQL Databases. BackupStorage is a CR provided by KubeStash that can manage storage from various providers like GCS, S3, and more. ```yaml apiVersion: storage.kubestash.com/v1alpha1 kind: BackupStorage metadata: name: linode-storage namespace: demo spec: storage: provider: s3 s3: bucket: mehedi-pg-wal-g endpoint: https://ap-south-1.linodeobjects.com region: ap-south-1 prefix: backup secretName: storage usagePolicy: allowedNamespaces: from: All default: true deletionPolicy: WipeOut ``` ```bash $ kubectl apply -f backupstorage.yaml backupstorage.storage.kubestash.com/linode-storage created ``` ```yaml apiVersion: v1 kind: Secret type: Opaque metadata: name: storage namespace: demo stringData: AWSACCESSKEY_ID: "*26CX" AWSSECRETACCESS_KEY: "jj3lp" AWS_ENDPOINT: https://ap-south-1.linodeobjects.com ``` ```bash $ kubectl apply -f storage-secret.yaml secret/storage created ``` RetentionPolicy is a CR provided by KubeStash that allows you to set how long you'd like to retain the backup data. ```yaml apiVersion: storage.kubestash.com/v1alpha1 kind: RetentionPolicy metadata: name: postgres-retention-policy namespace: demo spec: maxRetentionPeriod: "30d" successfulSnapshots: last: 100 failedSnapshots: last: 2 ``` ```bash $ kubectl apply -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/guides/postgres/pitr/yamls/retention-policy.yaml retentionpolicy.storage.kubestash.com/postgres-retention-policy created ``` PostgreSQLArchiver is a CR provided by KubeDB for managing the archiving of MongoDB oplog files and performing volume-level backups ```yaml apiVersion: archiver.kubedb.com/v1alpha1 kind: PostgresArchiver metadata: name: postgresarchiver-sample namespace: demo spec: pause: false databases: namespaces: from: Selector selector: matchLabels:

demo selector: matchLabels: archiver: "true" retentionPolicy: name: postgres-retention-policy namespace: demo encryptionSecret: name: "encrypt-secret" namespace: "demo" fullBackup: driver: "VolumeSnapshotter" task: params: volumeSnapshotClassName: "longhorn-snapshot-vsc" scheduler: successfulJobsHistoryLimit: 1 failedJobsHistoryLimit: 1 schedule: "/30 " sessionHistoryLimit: 2 manifestBackup: scheduler: successfulJobsHistoryLimit: 1 failedJobsHistoryLimit: 1 schedule: "/30 " sessionHistoryLimit: 2 backupStorage: ref: name: "linode-storage" namespace: "demo" ``` ```yaml apiVersion: v1 kind: Secret type: Opaque metadata: name: encrypt-secret namespace: demo stringData: RESTIC_PASSWORD: "changeit" ``` ```bash $ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/guides/postgres/pirt/yamls/postgresarchiver.yaml postgresarchiver.archiver.kubedb.com/postgresarchiver-sample created $ kubectl create -f https://github.com/kubedb/docs/raw/{{< param "info.version" >}}/docs/guides/postgres/pirt/yamls/encryptionSecret.yaml ``` ```bash $ kubectl get volumesnapshotclasses NAME DRIVER DELETIONPOLICY AGE longhorn-snapshot-vsc driver.longhorn.io Delete 7d22h ``` If not any, try using `longhorn` or any other . ```yaml kind: VolumeSnapshotClass apiVersion: snapshot.storage.k8s.io/v1 metadata: name: longhorn-snapshot-vsc driver: driver.longhorn.io deletionPolicy: Delete parameters: type: snap ``` ```bash $ helm install longhorn longhorn/longhorn --namespace longhorn-system --create-namespace $ kubectl apply -f volumesnapshotclass.yaml volumesnapshotclass.snapshot.storage.k8s.io/longhorn-snapshot-vsc unchanged ``` So far we are ready with setup for continuously archive PostgreSQL, We deploy a postgresql referring the PostgreSQL archiver object ```yaml apiVersion: kubedb.com/v1alpha2 kind: Postgres metadata: name: demo-pg namespace: demo labels: archiver: "true" spec: version: "13.13" replicas: 3 standbyMode: Hot storageType: Durable storage: storageClassName: "longhorn" accessModes: ReadWriteOnce resources: requests: storage: 1Gi archiver: ref: name: postgresarchiver-sample namespace: demo terminationPolicy: WipeOut ``` ```bash $ kubectl get pod -n demo NAME READY STATUS RESTARTS AGE demo-pg-0 2/2 Running 0 8m52s demo-pg-1 2/2 Running 0 8m22s demo-pg-2 2/2 Running 0 7m57s demo-pg-backup-config-full-backup-1702388088-z4qbz 0/1 Completed 0 37s demo-pg-backup-config-manifest-1702388088-hpx6m 0/1 Completed 0 37s demo-pg-sidekick 1/1 Running 0 7m31s ``` `demo-pg-sidekick` is responsible for uploading wal-files `demo-pg-backup-config-full-backup-1702388088-z4qbz ` are the pod of volumes levels backups for postgreSQL. `demo-pg-backup-config-manifest-1702388088-hpx6m ` are the pod of the manifest backup related to PostgreSQL object ```bash $ kubectl get backupconfigurations -n demo NAME PHASE PAUSED AGE demo-pg-backup-config Ready 2m43s $ kubectl get backupsession -n demo NAME INVOKER-TYPE INVOKER-NAME PHASE DURATION AGE demo-pg-backup-config-full-backup-1702388088 BackupConfiguration demo-pg-backup-config Succeeded 74s demo-pg-backup-config-manifest-1702388088 BackupConfiguration demo-pg-backup-config Succeeded 74s kubectl get volumesnapshots -n demo NAME READYTOUSE SOURCEPVC SOURCESNAPSHOTCONTENT RESTORESIZE SNAPSHOTCLASS SNAPSHOTCONTENT CREATIONTIME AGE demo-pg-1702388096 true data-demo-pg-1 1Gi longhorn-snapshot-vsc snapcontent-735e97ad-1dfa-4b70-b416-33f7270d792c 2m5s 2m5s ``` After each and every wal switch the wal files will be uploaded to backup storage ```bash $ kubectl exec -it -n demo demo-pg-0 -- bash bash-5.1$ psql postgres=# create database hi; CREATE DATABASE postgres=# \c hi hi=# create table tab_1 (a int); CREATE TABLE hi=# insert into tab1 values(generateseries(1,100)); INSERT 0 100 hi=# select pgswitchwal(); 0/504A0D8 (1 row) hi=# insert into tab1 values(generateseries(1,100)); INSERT 0 100 hi=# select now(); 2023-12-12 13:43:41.300216+00 hi=# select pgswitchwal();

hi=# select count(*) from tab_1 ; 200 ``` At this point We have 200 rows in our newly created table `tab_1` on database `hi` Point-In-Time Recovery allows you to restore a PostgreSQL database to a specific point in time using the archived transaction logs. This is particularly useful in scenarios where you need to recover to a state just before a specific error or data corruption occurred. Let's say accidentally our dba drops the the table tab_1 and we want to restore. ```bash $ kubectl exec -it -n demo demo-pg-0 -- bash bash-5.1$ psql postgres=# \c hi hi=# drop table tab_1; DROP TABLE hi=# select count(*) from tab_1 ; ERROR: relation "tab_1" does not exist LINE 1: select count(*) from tab_1 ; ``` We can't restore from a full backup since at this point no full backup was perform. so we can choose a specific time in which time we want to restore.We can get the specfice time from the wal that archived in the backup storage . Go to the binlog file and find where to store. You can parse wal-files using `pg-waldump`. For the demo I will use the previous time we get form `select now()` ```bash hi=# select now(); 2023-12-12 13:43:41.300216+00 ``` ```yaml apiVersion: kubedb.com/v1alpha2 kind: Postgres metadata: name: restore-pg namespace: demo spec: init: archiver: encryptionSecret: name: encrypt-secret namespace: demo fullDBRepository: name: demo-pg-repository namespace: demo manifestRepository: name: demo-pg-manifest namespace: demo recoveryTimestamp: "2023-12-12T13:43:41.300216Z" version: "13.13" replicas: 3 standbyMode: Hot storageType: Durable storage: storageClassName: "longhorn" accessModes: ReadWriteOnce resources: requests: storage: 1Gi terminationPolicy: WipeOut ``` ```bash $ kubectl apply -f restore.yaml postgres.kubedb.com/restore-pg created ``` check for Restored PostgreSQL ```bash $ kubectl get pod -n demo NAME READY STATUS RESTARTS AGE restore-pg-0 2/2 Running 0 46s restore-pg-1 2/2 Running 0 41s restore-pg-2 2/2 Running 0 22s restore-pg-restorer-4d4dg 0/1 Completed 0 104s restore-pg-restoresession-2tsbv 0/1 Completed 0 115s ``` ```bash $ kubectl get pg -n demo NAME VERSION STATUS AGE demo-pg 13.6 Ready 44m restore-pg 13.6 Ready 2m36s ``` Validating data on Restored PostgreSQL ```bash $ kubectl exec -it -n demo restore-pg-0 -- bash bash-5.1$ psql postgres=# \c hi hi=# select count(*) from tab_1 ; 200 ``` so we are able to successfully recover from a disaster To cleanup the Kubernetes resources created by this tutorial, run: ```bash $ kubectl delete -n demo pg/demo-pg $ kubectl delete -n demo pg/restore-pg $ kubectl delete -n demo backupstorage $ kubectl delete -n demo postgresqlarchiver $ kubectl delete ns demo ``` Learn about PostgreSQL database using Stash. Learn about initializing . Learn about . Want to setup PostgreSQL cluster? Check how to Monitor your PostgreSQL database with KubeDB using . Monitor your PostgreSQL database with KubeDB using . Detail concepts of . Use to deploy PostgreSQL with KubeDB. Want to hack on KubeDB? Check our .