ทำ Backup Archive & Restore ของ PostgreSQL ด้วย WAL-G
Tags: postgres, walg, backup, database
Published: 2023-09-07 11:07:29

## [WAL-G](https://github.com/wal-g/wal-g) เป็นเครื่องมือสำหรับการทำ Archive & Restore
รองรับฐานข้อมูลต่าง ๆ เช่น PostgreSQL, MySQL/MariaDB, and MS SQL Server (และ beta สำหรับ MongoDB and Redis)
รองรับ Storage หลายแบบเช่น AWS S3, Google Cloud Storage, Azure, File System

## โดยคำสั่งที่เราจะใช้ในที่นี้จะมี
```
$ wal-g backup-push # สำหรับการทำ Base Backup
$ wal-g backup-fetch # สำหรับการกู้ข้อมูลจาก Base Backup
$ wal-g wal-fetch # สำหรับการกู้ข้อมูลจาก WAL
```

## WAL คืออะไร
Write-Ahead Logging (WAL) เป็นเทคนิคที่ใช้ใน Database เพื่อรักษาความปลอดภัยและความทนทานของข้อมูลในกรณีเกิดความขัดข้องระหว่างการเขียนข้อมูลลงใน Database โดยที่ตัวนี้แหละจะทำให้ Database เรารอดกรณีมันบึ้มขึ้นมา

โดยตัวอย่างในที่นี้จะเป็น PostgreSQL 15, Google Cloud Storage และ Ubuntu 20
## Table of content

1. [Prerequires](#prerequires)
2. [Install wal-g](#install-wal-g)
3. [Install envdir](#install-envdir)
 - [Enviroment variable](#enviroment-variable)
 - [Create envdir Directory](#create-envdir-directory)
 - [Set Enviroment with envdir](#set-environment-with-envdir)
4. [Configuration](#configuration)
5. [Backup](#backup)
 - [Backup Push](#backup-push)
 - [Cronjob Backup](#cronjob-backup)
6. [Restore](#restore)
 - [Restore Base Backup](#restore-base-backup)
 - [Restore WAL](#restore-wal)
7. [Retain](#retain)
 - [Cronjob Retain](#cronjob-retain)

## Prerequires
- Ubuntu version ที่ wal-g รองรับเช็คได้ที่หน้า [wal-g releases](https://github.com/wal-g/wal-g/releases)
- wal-g
- Service Account json for connect to Google Cloud Storage
- envdir
- postgresql 15


## Install wal-g
สำหรับ Postgresql บน Ubuntu หากใช้ตัวอื่นดูได้ที่ [wal-g releases](https://github.com/wal-g/wal-g/releases)
```
$ curl -O -L 'https://github.com/wal-g/wal-g/releases/download/v2.0.1/wal-g-pg-ubuntu-20.04-amd64.tar.gz'
tar -zxvf wal-g-pg-ubuntu-20.04-amd64.tar.gz
$ mv wal-g-pg-ubuntu-20.04-amd64 /usr/local/bin/wal-g
```
## Install envdir
```
$ sudo apt install -y daemontools
```
### Enviroment variable
เนื่องจากเราใช้ Google Cloud Storage หากใช้ตัวอื่นดูได้ที่ [WAL-G Storage](https://wal-g.readthedocs.io/STORAGES/)
`GOOGLE_APPLICATION_CREDENTIALS` เพื่อกำหนด path ของ Service account
`WALG_GS_PREFIX` เพื่อกำหนด bucket และ directory 
`PGPASSWORD` เพื่อเก็บรหัสผ่าน Postgresql

#### Create envdir Directory
สร้าง Directory สำหรับเก็บ environment variable เพราะตอน postgres สั่ง archive_command ตัว wal-g จะได้อ่าน environment variable ได้จาก envdir ได้
```
umask u=rwx,g=rx,o=
mkdir -p /etc/wal-g.d/env
chown -R postgres /etc/wal-g.d/env
```


#### Set Enviroment with envdir
GOOGLE_APPLICATION_CREDENTIALS จำเป็นต้องให้ User postgres มีสิทธิ์เข้าถึงด้วย 
```
$ cp service_account.json /var/lib/postgresql/service_account.json
$ chown -R postgres /var/lib/postgresql/service_account.json
```
ตั้งค่า envdir ด้วย user postgres
```
# ใช้ user postgres
$ su - postgres
$ echo '/var/lib/postgresql/service_account.json' > /etc/wal-g.d/env/GOOGLE_APPLICATION_CREDENTIALS
$ echo 'gs://{bucket_name}/{your_backup_folder}' > /etc/wal-g.d/env/WALG_GS_PREFIX 
$ echo 'Your PG Password' > /etc/wal-g.d/env/PGPASSWORD
```
## Configuration 
ตั้งค่า PostgreSQL ให้รองรับ WAL-G เพื่อ Push WAL ไปยัง Storage
```
# ใช้ user postgres
$ su - postgres
$ echo "archive_mode = yes" >> /etc/postgresql/15/main/conf.d/wal-g.conf
$ echo "archive_command = 'envdir /etc/wal-g.d/env /usr/local/bin/wal-g wal-push %p'" >> /etc/postgresql/15/main/conf.d/wal-g.conf
$ echo "archive_timeout = 60" >> /etc/postgresql/15/main/conf.d/wal-g.conf
```
## Backup
กรณีเครื่องเก่าระเบิดให้ข้ามตรงนี้ไป [Restore](#restore) ได้เลยแล้วค่อยกลับมาหัวข้อนี้

หลังจากติดตั้งเสร็จแล้วจำเป็นต้องสั่ง backup-push เพื่อสร้าง Base Backup ตัวแรก
### Backup Push
Base Backup ตามชื่อเลยเป็นพื้นฐานของ backup ที่เราจะไปใช้กู้ข้อมูลร่วมกับ WAL
ควรสร้าง Base Backup อย่างสม่ำเสมอเพื่อความสดใหม่ของ Backup
```
# ใช้ user postgres
$ su - postgres
$ envdir /etc/wal-g.d/env /usr/local/bin/wal-g backup-push /var/lib/postgresql/15/main
```
### Cronjob Backup
สร้าง Base Backup อัตโนมัติทุก 01:00 ของทุกวัน
```
$ echo "0 1 * * * postgres /usr/bin/envdir /etc/wal-g.d/env /usr/local/bin/wal-g backup-push /var/lib/postgresql/15/main" > /etc/cron.d/pg_auto_create_base_backup
```
## Restore
## Restore Base Backup
การ Restore Base Backup ด้วยคำสั่ง backup-fetch 
```
# ใช้ user postgres
$ su - postgres
$ envdir /etc/wal-g.d/env /usr/local/bin/wal-g backup-fetch  /var/lib/postgresql/15/main LATEST
```
หลังจากกู้คืน Base Backup แล้วแต่ข้อมูลยังไม่ล่าสุดเหมือนก่อนล่ม
และอาจจะ start postgresql service ไม่ได้เพราะ Data interrupt
เราจะเอาข้อมูล WAL ตรงนั้นกลับมาด้วยคำสั่ง wal-fetch

## Restore WAL
จากหัวข้อที่แล้วข้อมูลของเรายังไม่ล่าสุดเพราะจะมี Base Backup เฉพาะตอนที่เราสั่งเท่านั้น หรือตอนที่ Cronjob ทำงาน เราจะมากู้ข้อมูลที่ไม่มีใน Base Backup กันผ่าน WAL 
กรณีติดตั้งใหม่ให้ stop service ก่อน
```
$ sudo systemctl stop postgresql@15-main.service
```
เพิ่มคำสั่ง restore ด้วย wal-fetch ใน postgresql config
```
# ใช้ user postgres
$ su - postgres
$ echo "restore_command = 'envdir /etc/wal-g.d/env wal-g wal-fetch "%f" "%p"'" >> /var/lib/postgresql/15/main/postgresql.auto.conf
```
สร้าง Signal เพื่อให้ PostgreSQL เข้าสู่ recovery mode
```
# ใช้ user postgres
$ su - postgres
$ touch /var/lib/postgresql/15/main/recovery.signal
```
Start Service และรอให้มัน recovery เองด้วย restore_command ที่เราตั้งค่าไปด้านบน
```
$ sudo systemctl start postgresql@15-main.service
```
แล้วจากนี้ก็ไปจิบกาแฟรอสักแก้วนึง 
ถ้า Base Backup ไม่เก่ามากแปปเดียว PostgreSQL เราก็พร้อมใช้งานแล้ว
## Retain
เพื่อจัดการการลบการสำรองข้อมูล Base Backup และ WAL ที่เก่าเกินไป.
### Cronjob Retain
ตั้งค่า Retain อัตโนมัติทุก 02:00 ของทุกวันโดย
โดยที่จะลบ base backups แบบ FULL และเหลือ 30 รายการล่าสุด
การข้อมูล Base Backup และ WAL ที่เกินจากนี้จะถูกลบออก.
ทำให้เราประหยัดเนื้อที่ไปอีกถ้าใช้ร่วมกับ [Cronjob Backup](#cronjob-backup) ข้อมูล Base Backup เราจะใหม่อยู่เสมอ
```
echo "0 2 * * * postgres /usr/bin/envdir /etc/wal-g.d/env /usr/local/bin/wal-g delete retain FULL 30 --confirm" > /etc/cron.d/pg_auto_retain
```

ทิ้งท้ายควรมีการซ้อม backup & restore อยู่เสมอ ๆ เมื่อถึงเวลามันจำเป็น 
ref
- [wal-g document](https://wal-g.readthedocs.io)
- [supabase continuous postgresql backup walg](https://supabase.com/blog/continuous-postgresql-backup-walg)