-
Postgresql 集群,小可热备,中可读写分离,大可作为分布式存储的基础设施;
-
使用 Docker 搭建,可以隔离开发、测试、生产环境的差异,实现搭建脚本本身的可测试,进一步实现 DevOps 的目标。
为什么不进一步使用 Docker Swarm 或 K8S 等容器编排系统?Postgresl 集群是强状态的,容器编排适合无状态的服务,任由 K8S 进行自动故障迁移会引起 Postgesql 底层数据的更多故障,即使关闭 K8S 的状态迁移,还会因为 PG 服务器之间需要强状态通信,带来很多不必要的编排配置,比脱裤子放屁还多此一举。
-
Docker: 20+
-
Postgresql: 13 + 镜像
为了不与其它网络环境混淆,我们可以先创建一个 Docker 虚拟网络
docker network create pg-cluster-network
本文演示的是在一台机器上搭建 PG 集群,生产环境的 PG 会搭建在两台机器上,可以忽略此步。
1.创建主库镜像
## 使用postgres官方镜像创建主库容器
docker run -d
--restart=unless-stopped
--name=pg-cluster-pg1
--network-alias=pg1
--network pg-cluster-network
-e POSTGRES_DB=test
-e POSTGRES_USER=test
-e POSTGRES_PASSWORD=123456
postgres:13-alpine
对备库开放远程同步权限
# 增加备库远程同步权限配置
docker exec -it pg-cluster-pg1
sh -c "echo host replication test all md5 >> /var/lib/postgresql/data/pg_hba.conf"
开启同步备份 (可选)
同步备份对主库性能影响较大,仅当对备份的事务一致性要求有绝对保障时开放 关闭后,当主库崩溃时,有极小的可能性部分事务未同步 {.is-warning}
# 开启同步备份
docker exec -it pg-cluster-pg1
sh -c "echo synchronous_standby_names = '*' >> /var/lib/postgresql/data/postgresql.conf"
重新加载配置
# 重载配置文件,以便生效
docker exec -it -u postgres pg-cluster-pg1 sh -c "pg_ctl reload"
创建备份插槽
# 创建备份槽,以便备用服务器接入
docker exec -it pg-cluster-pg1
psql -U test -c "select * from pg_create_physical_replication_slot('standby1_slot');"
Step3 搭建备份数据库 1.创建数据卷,以便从主库同步数据、修改配置
docker volume rm pg-cluster-pg2-data
docker volume create pg-cluster-pg2-data
从主库创建基础备份
# 使用pg_basebackup创建数据库基础备份到数据卷,-R参数会自动生成热备配置到postgresql.auto.conf中
docker run -it --rm
--network pg-cluster-network
-v pg-cluster-pg2-data:/var/lib/postgresql/data
postgres:13-alpine
pg_basebackup -R -h pg1 -U test -X stream -P -S standby1_slot -D /var/lib/postgresql/data
执行时会提示输入主库备份账号密码,输入完成后,会显示备份进度直到 100% 否则失败,则需要检查主库权限配置、网络连接
启动备份库
docker run -d
--restart=unless-stopped
--name=pg-cluster-pg2
--network-alias=pg2
--network pg-cluster-network
-v pg-cluster-pg2-data:/var/lib/postgresql/data
postgres:13-alpine
验证同步状态 在主库中可查询插入状态,来验证备库是否已连接
docker exec -it pg-cluster-pg1
psql -U test -c "SELECT slot_name, slot_type, active, wal_status from pg_replication_slots;"
# slot_name slot_type active wal_status
# standby1_slot physical t reserved
测试数据同步
搭建 pgadmin 用于测试
docker run -d
--restart=unless-stopped
--name=pg-cluster-pgadmin
--network pg-cluster-network
-p 8888:80
-e PGADMIN_DEFAULT_EMAIL=admin
-e PGADMIN_DEFAULT_PASSWORD=123456
dpage/pgadmin4:snapshot
pgadmin 容器创建后,可以在 http://localhost:8888 上配置到 pg1、pg2 的连接 因为设置了网络别名,两台数据库服务器可以用 pg1、pg2 代替 ip 直接访问 pgadmin 的账号 / 密码为:admin/123456
在主库中创建测试表并插入数据 在 pg1.test 库中执行以下 sql
CREATE TABLE userInfo(
userName VARCHAR(20),
age INT,
PRIMARY KEY(userName)
);
INSERT INTO userInfo VALUES('张三',10);
在 pg2.test 中执行以下查询
SELECT * FROM userInfo;
如果看到刚在 pg1.test 中插入的数据,则说明主备已经搭建成功
故障恢复 当主库崩溃时,需要进行故障转移或恢复
请谨慎执行以下操作,否则有可能会造成主备数据不同步 {.is-warning}
故障处理方案一:转移到备库 备库默认是只读的,可以用来分担只读负载,可以通过以下 sql 来验证,正常情况会报数据库只读
-- 在 pg2.test中执行
UPDATE userInfo SET age=4;
-- ERROR: cannot execute UPDATE in a read-only transaction
-- SQL 状态: 25006
当主库挂掉时,可快速在备库中执行命令将备库转换为主库:方式一:使用 SQL
-- 在pg2.test中执行:
SELECT pg_promote(true,60);
-- 参数1:等待提升完成
-- 参数2:等待60秒
方式二:使用 pg_ctl 命令
docker exec -it -u postgres pg-cluster-pg2
pg_ctl promote
将备库转换为主库后,需另外再搭建备份库来保证下次的故障转移
故障处理方案二:主库恢复 步骤一 主库反向从备库恢复数据 (可选)
大部分情况下,如主机断电等,只需要将主库启动并连接到网络即可完成恢复 当且仅当主库文件系统损坏等情况造成数据丢失时,需要从备库恢复数据
1. 备库中向主库开放插槽
# 在原备库中创建备份槽,以便原主库接入并恢复数据
docker exec -it pg-cluster-pg2
psql -U test -c "select * from pg_create_physical_replication_slot('main_slot');"
2 从备份库恢复数据
# 创建docker数据卷
docker volume rm pg-cluster-pg1-data
docker volume create pg-cluster-pg1-data
# 使用pg_basebackup从备份库恢复数据到数据卷,-R参数会自动生成热备配置到postgresql.auto.conf中
docker run -it --rm
--network pg-cluster-network
-v pg-cluster-pg1-data:/var/lib/postgresql/data
postgres:13-alpine
pg_basebackup -R -h pg2 -U test -X stream -P -S main_slot -D /var/lib/postgresql/data
3. 配置主库在数据同步完成后自动升级为主库
如果备库已经升级为主库,不要执行本操作!否则有可能造成主备数据不一致!{.is-warning}
在主库启动后,可手动执行 pg_promote 进行升级,也无须执行本节操作 如果数据较大、恢复时间较长,考虑使用以下方式
# 配置升级触发文件
docker run -it --rm
--network pg-cluster-network
-v pg-cluster-pg1-data:/var/lib/postgresql/data
postgres:13-alpine
sh -c "echo promote_trigger_file = 'standby.signal' >> /var/lib/postgresql/data/postgresql.conf"
当主库启动成功恢复后,其会自动切换到主库状态,提供正常的读写服务
步骤二 启动主库
docker run -d
--restart=unless-stopped
--name=pg-cluster-pg1
--network-alias=pg1
--network pg-cluster-network
-v pg-cluster-pg1-data:/var/lib/postgresql/data
postgres:13-alpine
等主库启动完毕,验证下数据没有丢失,即已完成主库的恢复,如果发现数据丢失,请执行步骤一
作者:chentao106
来源:OSC DevOps 社区
链接:https://my.oschina.net/u/4254626/blog/5403511
助力DevOps文化传播与实践
原文始发于微信公众号(OSC DevOps):使用 Docker 搭建 Postgresql 主备集群
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论