1. Featrue
pgBackRest是一款C语言编写的功能强大的postgres WAL/备份(Backup)管理工具。
当前pgBackRest项目的主要维护者是Crunchydata公司,Crunchydata在的postgres-operator工具pgo中深度绑定了pgbackrest工具。
pgbackrest的官方文档主要介绍了以下特性:
- Parallel Backup & Restore
- 多存储库(Repo)支持
- 存储库(Repo)支持对接S3
- 存储库(Repo)基于Local、TLS、SSH方式操作
- 存储库(Repo)加密
- 支持全量、差分、增量Backup
- Backup/WAL自动Rotation/Expiration维护:支持在存储库上创建Backup的保留策略
- Backup Resume:将创建Backup的操作可以”断点重建“
- Delta Restore:基于Backup中每个文件的校验和进行增量恢复
- Backup 完整性检查
- Page Checksums:创建Backup时,检查内存Page和数据库文件一致性,并进行告警(PS:不会中断Backup)
- Streaming Compression & Checksums:pgBackRest对存储库交互的数据流进行压缩和校验
- Parallel, Asynchronous WAL Push & Get
- Tablespace & Link Support
pgbackrest的功能多余同类型竞品WAL-E/G,并且笔者在学习中发现pgbackuprest官方提供的用户手册非常详细,远胜WAL-E/G。
2.安装/编译
1.二进制安装
crunchydata提供了基于RPM等格式pgBackRest,可以从crunchydata的官网或者Postgres官方仓库获取相应操作系统的安装包。
1
2
3
|
yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
yum --showduplicates list pgbackrest
yum install pgbackrest
|
2.编译
1
2
3
4
5
6
|
yum -y install make gcc postgresql11-devel openssl-devel libxml2-devel lz4-devel libzstd-devel bzip2-devel libyaml-devel
yum -y install libpq5 libpq5-devel
mkdir -p ./build
wget -q -O - https://github.com/pgbackrest/pgbackrest/archive/release/2.37.tar.gz | tar zx -C ./build
cd ./build/pgbackrest-release-2.37/src && ./configure && make
cp pgbackrest /usr/local/bin/
|
上述编译过程结束后,在编译目录下会生成pgbackrest文件,只需要将上述文件copy到生产环境即可使用pgbackrest。 在生产环境上,还需要安装libpq5和libzstd作为pgbackrest的运行时依赖!
手工安装时可以创建pgbackrest的配置目录和日志目录:
1
2
3
4
5
6
7
|
sudo mkdir -p -m 770 /var/log/pgbackrest
sudo chown postgres:postgres /var/log/pgbackrest
sudo mkdir -p /etc/pgbackrest
sudo mkdir -p /etc/pgbackrest/conf.d
sudo touch /etc/pgbackrest/pgbackrest.conf
sudo chmod 640 /etc/pgbackrest/pgbackrest.conf
sudo chown postgres:postgres /etc/pgbackrest/pgbackrest.conf
|
3.特殊概念
在体验pgbackrest前先简单介绍以下概念。
1. Backup
Backup指的是数据库目录下所有文件的副本,通过Backup用户可以创建副本或者在新的环境中重建数据库。
pgBackRest的设计将Backup划分成以下三种类型:
- Full:全量Backup
- Differential:仅包含自上次Full Backup中发生更改的文件,Differential Backup依赖Full Backup才能restore数据库 。
- Incremental:仅包含自上次Backup中发生更改的文件,上次Backup可以是任意类型的Backup
用户可以pgbackrest backup命令创建以上类型的backup,并在需要是通过pgbackrest restore从backup还原数据库。
2. Repositories
Repositories是用来保存backup和wal的服务,pgbackrest在工作过程中可以通过SSH、HTTPS、Local的方式和Repositories交互。
当pgbackrest是基于SSH或者Local方式和Repositories交互时,Repositories本质上只是一个目录,没有实际运行进程。pgbackrest会直接读写本地目录中的文件或者通过免密SSH操作远程主机上的文件。
当pgbackrest通过HTTPS和Repositories交互时,远程主机上需要通过pgbackrest server命令启动Repositories服务。
用户可以同时定义多个Repositories,当需要执行backup/restore的时候通过–repo参数指定使用的Repositories。
以下配置中定义了repo1、repo2、repo3 三种不同类型的Repositories。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
[global]
# repo1 本地仓库
repo1-path=/var/lib/pgbackrest
# repo2 远程仓库,基于SSH访问,执行SSH的用户是postgres,用户需要手工在这两个机器之间打通免密
repo2-host=harbor-repo-host
repo2-host-user=postgres
repo2-path=/pgbackrest/repo
# repo3 远程仓库,基于HTTPS访问
repo3-host-ca-file=/etc/pgbackrest/cert/ca.crt
repo3-host-cert-file=/etc/pgbackrest/cert/client.crt
repo3-host-key-file=/etc/pgbackrest/cert/client.key
repo3-host-type=tls
|
3. Stanza
Stanza 是 pgbackrest 配置文件中的概念,它表示postgres集群中每个postgres实例的连接信息,可以简单理解为postgres的集群名称。pgbackrest管理backup和wal以Stanza为单位,数据合并存储。
以下配置中,db是Stanza名称,包含pg1、pg2、pg3 三个postgres实例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
[db]
pg1-host=postgres1.svc.cluster.local.
pg1-path=/pgdata/pg13
pg1-port=5432
pg1-socket-path=/tmp/postgres
pg2-host=postgres2.svc.cluster.local.
pg2-path=/pgdata/pg13
pg2-port=5432
pg2-socket-path=/tmp/postgres
pg3-host=postgres3.svc.cluster.local.
pg3-path=/pgdata/pg13
pg3-port=5432
pg3-socket-path=/tmp/postgres
|
上述配置中每个postgres实例包含以下配置:
- host:数据库地址
- path:数据目录
- port:数据库端口
- socket-path:unix sock 目录(这个地址是相对于postgres运行的服务器的)
4. Quick Start
官方文档详细介绍了如何使用pgbackrest在虚拟机上使用pgbackup,这里不再复述。
以下是简化的脚本命令:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
# 初始化postgres数据库
sudo -u postgres /usr/pgsql-11/bin/initdb -D /var/lib/pgsql/11/data -k -A peer
mv /var/lib/pgsql/11/data/postgresql.conf /var/lib/pgsql/11/data/postgresql.base.conf
# 生成pgbackrest的配置目录
sudo mkdir -p -m 770 /var/log/pgbackrest
sudo chown postgres:postgres /var/log/pgbackrest
sudo mkdir -p /etc/pgbackrest
sudo mkdir -p /etc/pgbackrest/conf.d
# 创建一个本地目录作为备份仓库
sudo mkdir -p /var/lib/pgbackrest
sudo chmod 750 /var/lib/pgbackrest
sudo chown postgres:postgres /var/lib/pgbackrest
# 创建配置文件,配置文件中stanza名称为demo,并且省缺配置了一个本地的pg实例,数据目录为/var/lib/pgsql/11/data
# 同时配置了本地仓库repo1
cat >> /etc/pgbackrest/pgbackrest.conf << EOF
[demo]
pg1-path=/var/lib/pgsql/11/data
[global]
repo1-path=/var/lib/pgbackrest
repo1-retention-full=2
start-fast=y
repo1-cipher-pass=zWaf6XtpjIVZC5444yXB+cgFDFl7MxGlgkZSaoPvTGirhPygu4jOKOXf9LO4vjfO
repo1-cipher-type=aes-256-cbc
[global:archive-push]
compress-level=3
EOF
sudo chown postgres:postgres /etc/pgbackrest/pgbackrest.conf
# 创建postgresql.conf的配置文件,PS:这里的配置都不是必须的,只用于演示
cat >> /var/lib/pgsql/11/data/postgresql.conf << EOF
include 'postgresql.base.conf'
listen_addresses = '*'
log_line_prefix = ''
log_filename = 'postgresql.log'
archive_command = '/usr/bin/pgbackrest --stanza=demo archive-push %p'
archive_mode = on
max_wal_senders = 3
wal_level = replica
EOF
chown postgres:postgres /var/lib/pgsql/11/data/postgresql.conf
# 启动数据库
mkdir /home/postgres
chown postgres:postgres /home/postgres
cd /home/postgres
sudo -u postgres /usr/pgsql-11/bin/pg_ctl -D /var/lib/pgsql/11/data -l logfile start
# 初始化/运行stanza
sudo -u postgres /usr/bin/pgbackrest --stanza=demo --log-level-console=info stanza-create
# 检查指定stanza的配置
sudo -u postgres /usr/bin/pgbackrest --stanza=demo --log-level-console=info check
# 强制运行backup,由于设置了start-fast=y参数,此时会强制触发postgres的checkpoint操作,PS:如果没有该配置创建backup的动作会被延后,直到有一个checkpoint完成
sudo -u postgres /usr/bin/pgbackrest --stanza=demo --log-level-console=info backup
# 查看demo集群信息,以下命令会展示指定demo集群的所有备份信息,并且支持--output=json参数将结果格式化为json
sudo -u postgres /usr/bin/pgbackrest --stanza=demo info
# 恢复数据库
sudo -u postgres /usr/bin/pgbackrest --stanza=demo restore
|
5.Crunchydata架构
Crunchydata 公司开源的pgo中,使用pgbackrest和patroni搭建了一个Postgres HA方案,相比于Zalando开源的postgres-operator有以下不同:
- pgo中完全关闭了postgres的Replication Slot功能,Standby启动时先从Repo中获取wal,replay完成后通过Replication Stream从Master同步。Zalando的方案主要基于Replication Slot。pgo将wal数据的存储和Postgres分离,但是同时引入了repo目录的高可用问题。
- Standby启动时,pgo通过Repo的backup创建/restore数据目录。由于pgbackrest支持差分restore,因此对于长时间下线的Standby可能可以更快将数据目录的恢复到backup的状态(PS:这里更快的前提是用户定时生成backup,否则pgo依然会回退到pg_basebackup的方式全量同步数据)。Zalando默认使用pg_basebackup,用户也可以配置使用WAL-G。
PS:pgbackrest通过计算文件的SHA-1实现差分restore
pgo默认配置下,部署一个2副本的postgres集群会生成3个Pod,如下图:

pgo默认情况下Patroni的配置文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
bootstrap:
dcs:
postgresql:
use_pg_rewind: true
# 关闭Replication Slot
use_slots: false
parameters:
# Master 调用 pgbackrest archive-push 备份 wal
archive_command: pgbackrest --stanza=db archive-push "%p"
archive_mode: 'on'
jit: 'off'
# Standby 调用 pgbackrest archive-get 获取 wal
restore_command: pgbackrest --stanza=db archive-get %f "%p"
wal_level: logical
postgresql:
# 定义以下两种方式创建replicas,优先级pgbackrest
create_replica_methods:
- pgbackrest
- basebackup
pgbackrest:
# 调用pgbackrest restore
command: 'bash -ceu -- install --directory --mode=0700 "${PGDATA?}" && exec "$@" - pgbackrest restore --delta --stanza=db --repo=1 --link-map=pg_wal=/pgdata/pg13_wal'
# 执行command时,patroni不会清楚pg的数据目录
keep_data: true
# no_master参数表示即使当前patroni集群不存在leader也依然创建replica
no_master: true
# 调用command时,patroni不会额外注入参数
no_params: true
basebackup:
- waldir=/pgdata/pg13_wal
|
上述配置中,create_replica_methods 中定义了pgbackrest用于差分创建副本。关于patroni的配置说明参考博客。
参考