原文作者:Stefan Fercot 于 2022 年2 月 21 日发表
原文链接:https://pgstef.github.io/2022/02/21/pgbackrest_tls_server.html
pgstef 的博客
pgBackRest 和 TLS 连接
Stefan Fercot 于 2022 年2 月 21 日发表。
TLS 服务器是使用 SSH 与远程主机进行协议连接的替代方案。它已于2022 年 1 月 3 日在2.37版本中推送。
在这个演示设置中,存储库主机将被称为backup-srv和Streaming Replication中的 3 个 PostgreSQL 节点: pg1-srv、pg2-srv、pg3-srv。所有节点都将在 Rocky Linux 8 上运行。
如果你熟悉 Vagrant,这里有一个Vagrantfile使用这些名称启动 4 个虚拟机的简单方法:
# Vagrantfile
Vagrant.configure(2) do |config|
config.vm.box = 'rockylinux/8'
config.vm.provider 'libvirt' do |lv|
lv.cpus = 1
lv.memory = 1024
end
# share the default vagrant folder
config.vm.synced_folder ".", "/vagrant", type: "nfs"
nodes = 'backup-srv', 'pg1-srv', 'pg2-srv', 'pg3-srv'
nodes.each do |node|
config.vm.define node do |conf|
conf.vm.hostname = node
end
end
end
安装
在所有服务器上,首先配置 PGDG 存储库:
$ sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm
$ sudo dnf -qy module disable postgresql
然后,在pg1-srv、pg2-srv、pg3-srv上安装 PostgreSQL :
$ sudo dnf install -y postgresql14-server postgresql14-contrib
在pg1-srv创建一个基本的 PostgreSQL 实例:
$ export PGSETUP_INITDB_OPTIONS="--data-checksums"
$ sudo /usr/pgsql-14/bin/postgresql-14-setup initdb
$ sudo systemctl enable postgresql-14
$ sudo systemctl start postgresql-14
安装 pgBackRest 并检查它的版本:
$ sudo dnf install -y epel-release
$ sudo dnf install -y pgbackrest
$ pgbackrest version
pgBackRest 2.37
在存储库主机上创建专用用户
创建用户以pgbackrest拥有备份和存档存储库。任何用户都可以拥有存储库,但最好不要使用postgres以避免混淆。
在backup-srv上创建用户和存储库位置:
$ sudo groupadd pgbackrest
$ sudo adduser -g pgbackrest -n pgbackrest
$ sudo chown pgbackrest: /var/log/pgbackrest
$ sudo mkdir /backup_space
$ sudo chown pgbackrest: /backup_space
出于本演示的目的,我们创建了/backup_space用于在本地存储我们的备份和存档。存储库可以位于 配置官方文档中描述的各种支持的类型上。
证书生成
TLS 服务器实现依赖于证书。
可以在 此处找到有关如何生成证书并使用它来验证 PostgreSQL 连接的一个很好的实用示例。
基于该示例,让我们生成我们的证书:
$ mkdir certs && cd certs
$ openssl req -new -x509 -days 365 -nodes -out ca.crt -keyout ca.key -subj "/CN=root-ca"
$ openssl req -new -nodes -out backup-srv.csr -keyout backup-srv.key -subj "/CN=backup-srv"
$ openssl req -new -nodes -out pg1-srv.csr -keyout pg1-srv.key -subj "/CN=pg1-srv"
$ openssl req -new -nodes -out pg2-srv.csr -keyout pg2-srv.key -subj "/CN=pg2-srv"
$ openssl req -new -nodes -out pg3-srv.csr -keyout pg3-srv.key -subj "/CN=pg3-srv"
$ openssl x509 -req -in backup-srv.csr -days 365 -CA ca.crt -CAkey ca.key -CAcreateserial -out backup-srv.crt
$ openssl x509 -req -in pg1-srv.csr -days 365 -CA ca.crt -CAkey ca.key -CAcreateserial -out pg1-srv.crt
$ openssl x509 -req -in pg2-srv.csr -days 365 -CA ca.crt -CAkey ca.key -CAcreateserial -out pg2-srv.crt
$ openssl x509 -req -in pg3-srv.csr -days 365 -CA ca.crt -CAkey ca.key -CAcreateserial -out pg3-srv.crt
$ rm *.csr
然后,您必须在每台服务器上部署它 ( ca.crt++ server_name.crt) server_name.key。
这是在 vagrant 主机之间使用共享文件夹的示例:
# on backup-srv
$ sudo -u pgbackrest mkdir ~pgbackrest/certs
$ sudo cp `hostname`.* ~pgbackrest/certs
$ sudo cp ca.crt ~pgbackrest/certs
$ sudo chown -R pgbackrest: ~pgbackrest/certs
$ sudo chmod -R og-rwx ~pgbackrest/certs
# on pg1-srv, pg2-srv and pg3-srv
$ sudo -u postgres mkdir ~postgres/certs
$ sudo cp `hostname`.* ~postgres/certs
$ sudo cp ca.crt ~postgres/certs
$ sudo chown -R postgres: ~postgres/certs
$ sudo chmod -R og-rwx ~postgres/certs
配置
我们现在将为我们的节准备配置,名为demo.
更新backup-srv pgBackRest 配置文件:
# /etc/pgbackrest.conf
[global]
# repo details
repo1-path=/backup_space
repo1-retention-full=2
# general options
process-max=2
log-level-console=info
log-level-file=debug
start-fast=y
delta=y
# tls server options
tls-server-address=*
tls-server-cert-file=/home/pgbackrest/certs/backup-srv.crt
tls-server-key-file=/home/pgbackrest/certs/backup-srv.key
tls-server-ca-file=/home/pgbackrest/certs/ca.crt
tls-server-auth=pg1-srv=demo
tls-server-auth=pg2-srv=demo
tls-server-auth=pg3-srv=demo
[demo]
pg1-host=pg1-srv
pg1-path=/var/lib/pgsql/14/data
pg1-host-type=tls
pg1-host-cert-file=certs/backup-srv.crt
pg1-host-key-file=certs/backup-srv.key
pg1-host-ca-file=certs/ca.crt
更新pg1-srv、pg2-srv和pg3-srv pgBackRest 配置文件:
# /etc/pgbackrest.conf
[global]
repo1-host=backup-srv
repo1-host-user=pgbackrest
repo1-host-type=tls
repo1-host-cert-file=/var/lib/pgsql/certs/pg1-srv.crt
repo1-host-key-file=/var/lib/pgsql/certs/pg1-srv.key
repo1-host-ca-file=/var/lib/pgsql/certs/ca.crt
# general options
process-max=2
log-level-console=info
log-level-file=debug
# tls server options
tls-server-address=*
tls-server-cert-file=/var/lib/pgsql/certs/pg1-srv.crt
tls-server-key-file=/var/lib/pgsql/certs/pg1-srv.key
tls-server-ca-file=/var/lib/pgsql/certs/ca.crt
tls-server-auth=backup-srv=demo
[demo]
pg1-path=/var/lib/pgsql/14/data
(备注:显然,通过pg2 -srv上的pg2-srv和pg3-srv上的 pg3-srv 调整 pg1-srv。)
这个想法是在每个主机上运行一个 TLS 服务器来服务来自另一个主机的请求。例如,在backup存储库主机上运行的命令将充当 PostgreSQL 节点上运行的 TLS 服务器的客户端。在 PostgreSQL 节点上运行的archive-push命令将充当存储库主机上运行的 TLS 服务器的客户端。
该server命令可用于启动 TLS 服务器并将运行直到被 SIGINT 信号 (Control+C) 终止。
如果 PGDG软件包尚未完成,请在backup-srv服务器 上创建一个服务文件:
# /etc/systemd/system/pgbackrest.service
[Unit]
Description=pgBackRest Server
After=network.target
StartLimitIntervalSec=0
[Service]
Type=simple
User=pgbackrest
Restart=always
RestartSec=1
ExecStart=/usr/bin/pgbackrest server
ExecReload=kill -HUP $MAINPID
[Install]
WantedBy=multi-user.target
启动服务器并检查它是否正在运行:
$ sudo systemctl daemon-reload
$ sudo systemctl enable pgbackrest
$ sudo systemctl start pgbackrest
$ pgbackrest server-ping
该server-ping命令仅用作活动性检查,因为没有尝试进行身份验证。
tls-*更改配置时不要忘记终止/重新启动进程。
现在,使用以下配置在pg1-srv、pg2-srv和pg3-srv上应用相同的步骤(服务配置和启动):
# /etc/systemd/system/pgbackrest.service
[Unit]
Description=pgBackRest Server
After=network.target
StartLimitIntervalSec=0
[Service]
Type=simple
User=postgres
Restart=always
RestartSec=1
ExecStart=/usr/bin/pgbackrest server
ExecReload=kill -HUP $MAINPID
[Install]
WantedBy=multi-user.target
现在,让我们在文件中配置 PostgreSQL 归档postgresql.conf(在pg1-srv上):
listen_addresses = '*'
archive_mode = on
archive_command = 'pgbackrest --stanza=demo archive-push %p'
在进行这些更改之后和执行备份之前,必须重新启动 PostgreSQL 实例。
$ sudo systemctl restart postgresql-14.service
让我们最后创建节并检查backup-srv上的配置:
$ sudo -iu pgbackrest pgbackrest --stanza=demo stanza-create
...
P00 INFO: stanza-create command end: completed successfully
$ sudo -iu pgbackrest pgbackrest --stanza=demo check
...
P00 INFO: check command end: completed successfully
执行备份
如果一切正常,我们现在可以进行第一次备份:
$ sudo -iu pgbackrest pgbackrest --stanza=demo --type=full backup
P00 INFO: backup command begin 2.37: ..
P00 INFO: execute non-exclusive pg_start_backup(): backup begins after the requested
immediate checkpoint completes
P00 INFO: backup start archive = 000000010000000000000003, lsn = 0/3000028
P00 INFO: check archive for prior segment 000000010000000000000002
P00 INFO: execute non-exclusive pg_stop_backup() and wait for all WAL segments to archive
P00 INFO: backup stop archive = 000000010000000000000003, lsn = 0/3000100
P00 INFO: check archive for segment(s) 000000010000000000000003:000000010000000000000003
P00 INFO: new backup label = 20220218-080535F
P00 INFO: full backup size = 25.2MB, file total = 951
P00 INFO: backup command end: completed successfully
info然后可以从正确配置 pgBackRest 的任何服务器执行该命令:
# From the PostgreSQL node
$ sudo -iu postgres pgbackrest --stanza=demo info
stanza: demo
status: ok
cipher: none
db (current)
wal archive min/max (14): 000000010000000000000001/000000010000000000000003
full backup: 20220218-080535F
timestamp start/stop: 2022-02-18 08:05:35 / 2022-02-18 08:05:42
wal start/stop: 000000010000000000000003 / 000000010000000000000003
database size: 25.2MB, database backup size: 25.2MB
repo1: backup set size: 3.2MB, backup size: 3.2MB
# From the backup server
$ sudo -iu pgbackrest pgbackrest --stanza=demo info
stanza: demo
status: ok
cipher: none
db (current)
wal archive min/max (14): 000000010000000000000001/000000010000000000000003
full backup: 20220218-080535F
timestamp start/stop: 2022-02-18 08:05:35 / 2022-02-18 08:05:42
wal start/stop: 000000010000000000000003 / 000000010000000000000003
database size: 25.2MB, database backup size: 25.2MB
repo1: backup set size: 3.2MB, backup size: 3.2MB
为流复制准备服务器
在pg1-srv上,为复制创建一个特定用户:
$ sudo -iu postgres psql
postgres=# CREATE ROLE replic_user WITH LOGIN REPLICATION PASSWORD 'mypwd';
配置pg_hba.conf:
host replication replic_user pg2-srv scram-sha-256
host replication replic_user pg3-srv scram-sha-256
重新加载配置:
$ sudo systemctl reload postgresql-14.service
~postgres/.pgpass在pg2-srv和pg3-srv上配置:
$ sudo -iu postgres
$ echo "*:*:replication:replic_user:mypwd" >> ~postgres/.pgpass
$ chown postgres: ~postgres/.pgpass
$ chmod 0600 ~postgres/.pgpass
设置备用服务器
调整/etc/pgbackrest.confpg2 -srv和pg3-srv以添加recovery-option。这个想法是使用 restore 命令自动配置流复制连接字符串。
recovery-option=primary_conninfo=host=pg1-srv user=replic_user
info然后,通过执行命令确保配置正确。它应该打印与上面相同的输出。
恢复从pg2-srv和pg3-srv上的pg1-srv服务器获取的备份:
$ sudo -iu postgres pgbackrest --stanza=demo --type=standby restore
P00 INFO: restore command begin 2.37: ...
P00 INFO: repo1: restore backup set 20220218-080535F, recovery will start at ...
P00 INFO: write updated /var/lib/pgsql/14/data/postgresql.auto.conf
P00 INFO: restore global/pg_control
(performed last to ensure aborted restores cannot be started)
P00 INFO: restore size = 25.2MB, file total = 951
P00 INFO: restore command end: completed successfully
恢复将向postgresql.auto.conf文件添加额外信息:
# Recovery settings generated by pgBackRest restore on ...
primary_conninfo = 'host=pg1-srv user=replic_user'
restore_command = 'pgbackrest --stanza=demo archive-get %f "%p"'
该--type=standby选项创建standby.signalPostgreSQL 在待机模式下启动所需的内容。我们现在要做的就是启动 PostgreSQL 实例:
$ sudo systemctl enable postgresql-14
$ sudo systemctl start postgresql-14
如果复制设置正确,您应该会在pg1-srv服务器上看到这些进程:
# ps -ef |grep postgres
postgres 26108 1 ... /usr/pgsql-14/bin/postmaster -D /var/lib/pgsql/14/data/
postgres 26506 26108 ... postgres: walsender replic_user ... streaming 0/4000CE0
postgres 26507 26108 ... postgres: walsender replic_user ... streaming 0/4000CE0
我们现在有一个 3 节点集群,它使用流复制和存档恢复作为安全网。
从备用服务器进行备份
将以下设置添加到backup-srv上的 pgBackRest 配置文件的[demo]节部分:
pg2-host=pg2-srv
pg2-path=/var/lib/pgsql/14/data
pg2-host-type=tls
pg2-host-cert-file=certs/backup-srv.crt
pg2-host-key-file=certs/backup-srv.key
pg2-host-ca-file=certs/ca.crt
pg3-host=pg3-srv
pg3-path=/var/lib/pgsql/14/data
pg3-host-type=tls
pg3-host-cert-file=certs/backup-srv.crt
pg3-host-key-file=certs/backup-srv.key
pg3-host-ca-file=certs/ca.crt
backup-standby=y
现在,执行备份,从配置中找到的第一个备用服务器获取数据:
$ sudo -iu pgbackrest pgbackrest --stanza=demo --type=full backup
P00 INFO: backup command begin 2.37: ...
P00 INFO: execute non-exclusive pg_start_backup(): backup begins after the requested
immediate checkpoint completes
P00 INFO: backup start archive = 000000010000000000000005, lsn = 0/5000028
P00 INFO: wait for replay on the standby to reach 0/5000028
P00 INFO: replay on the standby reached 0/5000028
P00 INFO: check archive for prior segment 000000010000000000000004
P00 INFO: execute non-exclusive pg_stop_backup() and wait for all WAL segments to archive
P00 INFO: backup stop archive = 000000010000000000000005, lsn = 0/5000138
P00 INFO: check archive for segment(s) 000000010000000000000005:000000010000000000000005
P00 INFO: new backup label = 20220218-082239F
P00 INFO: full backup size = 25.2MB, file total = 951
P00 INFO: backup command end: completed successfully
结论
TLS 服务器为远程操作提供了 SSH 的替代方案。这项新功能将完美适应容器化世界,在该世界中它可以显着提高性能和用户体验。




