暂无图片
暂无图片
1
暂无图片
暂无图片
暂无图片

docker 部署postgeres主从环境

原创 雪狼sunny 2022-03-11
862

1. 创建测试网络
创建一个 docker bridge 网络用于测试:

 创建测试网络
docker network create --subnet=172.18.0.0/24 dockernetwork

 查看网络
docker network ls

规划主从库IP端口如下:

主库:172.18.0.101:5432

从库:172.18.0.102:5433

2. 拉取 postgres 镜像
docker pull postgres
3. 创建数据目录
mkdir -p /data/psql/pgsmaster
mkdir -p /data/psql/pgsslave
mkdir -p /data/psql/pgsrepl
chown 999:999 /data/psql/pgsmaster
chown 999:999 /data/psql/pgsslave
chown 999:999 /data/psql/pgsrepl
4. 运行 master 容器
docker run -d \
--network dockernetwork --ip 172.18.0.101 -p 5432:5432 \
--name master -h master \
-e "POSTGRES_DB=postgres" \
-e "POSTGRES_USER=postgres" \
-e "POSTGRES_PASSWORD=postgres" \
-v /data/psql/pgmaster:/var/lib/postgresql/data \
postgres
查看容器:

docker ps -a 

NAMES IMAGE CREATED STATUS NETWORKS PORTS
master postgres 48 seconds ago Up 46 seconds dockernetwork 0.0.0.0:5432->5432/tcp, :::5432->5432/tcp
5. 创建主从流复制专用账号
# 1. 进入容器
docker exec -it master bash

# 2. 连接PostgreSQL
psql -U postgres

# 3. 创建用户规则
CREATE ROLE repuser WITH LOGIN REPLICATION CONNECTION LIMIT 5 PASSWORD '123456';
# 用户名 repuser;最大链接数:5;密码:123456

# 4. 查看规则
\du
List of roles
Role name | Attributes | Member of
-----------+------------------------------------------------------------+-----------
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
repuser | Replication +| {}
| 5 connections |
6. 修改 master 配置文件
# 1. 进入 master 文件夹
cd /data/psql/pgmaster

# 2. 在末尾增加规则
echo "host replication repuser 172.18.0.102/24 md5" >> pg_hba.conf
修改 postgresql.conf 配置文件,找到以下几行,取消注释修改配置:

archive_mode = on # 开启归档模式
archive_command = '/bin/date' # 设置归档行为
# 从机连接到主机的并发连接数之总和
max_wal_senders = 10
# 指定在后备服务器需要为流复制获取日志段文件的情况下, pg_wal目录下所能保留的过去日志文件段的最小尺寸
wal_keep_size = 16
# 指定一个支持同步复制的后备服务器的列表
synchronous_standby_names = '*'


7. 重启 master 容器
docker stop master
docker start master
8. 创建 slave 容器
docker run -d \
--network dockernetwork --ip 172.18.0.102 -p 5433:5432 \
--name slave -h slave \
-e "POSTGRES_DB=postgres" \
-e "POSTGRES_USER=postgres" \
-e "POSTGRES_PASSWORD=postgres" \
-v /data/psql/pgslave:/var/lib/postgresql/data \
-v /data/psql/pgrepl:/var/lib/postgresql/repl \
postgres
# 查看容器
docker ps -a

NAMES IMAGE CREATED STATUS NETWORKS PORTS
slave postgres 18 seconds ago Up 15 seconds dockernetwork 0.0.0.0:5433->5432/tcp, :::5433->5432/tcp
master postgres 2 hours ago Up 2 hours dockernetwork 0.0.0.0:5432->5432/tcp, :::5432->5432/tcp
9. 同步数据
# 1. 进入容器
docker exec -it -u postgres slave /bin/bash

# 2. 备份主机数据到 repl 文件夹,此处输入在上面设置的密码:123456

从pg12版本以后pg的主从配置只支持pg_basebackup
pg_basebackup -R -D /var/lib/postgresql/repl -Fp -Xs -v -P -h 172.18.0.101 -p 5432 -U repuser

# 3. 备份完成退出容器
exit
10. 重建 slave 容器
通过上一步的初始备份,现在可以使用 /data/psql/pgrepl 里的数据重建 pgslave容器了。首先删除psslave目录,然后将 pgrepl 目录改为 pgslave,这个目录就是从库的数据目录了:

# 1. 删除容器
docker rm -f pgslave
# 2. 删除原有文件夹,将 pgrepl 重命名为 pgslave
cd /data/psql/
rm -rf pgslave
mv pgrepl psslave
cd /data/pgql/psslave
# 3. 查看配置信息
# postgresql.auto.conf 将含有复制所需信息
cat postgresql.auto.conf

primary_conninfo = 'user=repuser password=123456 channel_binding=prefer host=172.18.0.101 port=5432 sslmode=prefer sslcompression=0 ssl_min_protocol_version=TLSv1.2 gssencmode=prefer krbsrvname=postgres target_session_attrs=any'
重建 slave 容器:

docker run -d \
--network dockernetwork --ip 172.18.0.102 -p 5433:5432 \
--name slave -h slave \
-e "POSTGRES_DB=postgres" \
-e "POSTGRES_USER=postgres" \
-e "POSTGRES_PASSWORD=postgres" \
-v /data/psql/pgslave:/var/lib/postgresql/data \
postgres
# 查看容器
docker ps -a

NAMES IMAGE CREATED STATUS NETWORKS PORTS
slave postgres 23 seconds ago Up 21 seconds dockernetwork 0.0.0.0:5433->5432/tcp, :::5433->5432/tcp
master postgres 2 hours ago Up 2 hours dockernetwork 0.0.0.0:5432->5432/tcp, :::5432->5432/tcp
11. 查看主从复制信息
ps -aux | grep postgres

主库进程:从库进程:

postgres: walreceiver streaming 0/5000148
systemd+ 20020 0.0 0.0 213936 4180 ? Ss 13:36 0:00 postgres: walsender repuser 172.18.0.102(52938) streaming 0/5000148

验证主从配置
主机生成数据
# 进入 master 容器,切换到postgres用户
docker exec -it master bash
psql -U postgres
-- 查询复制信息
select * from pg_stat_replication;
-- 创建测试数据库
CREATE DATABASE test;
-- 查看所有数据库
\list
-- 切换数据库
\c test
-- 创建测试表
CREATE TABLE test (
"id" int4 NOT NULL,
"value" varchar(255),
PRIMARY KEY ("id")
);
-- 查看创建的表
\dt


-- 向表中插入十条数据
insert into test select generate_series(1,10);

-- 查看所有数据
select * from test;

从机查看数据
# 进入从机容器
docker exec -it slave bash
psql -U postgres
-- 查看数据库
\d
-- 查看表
\c test
-- 查看所有数据
select * from test;
参考链接:https://python.iitter.com/other/102038.html


所有操作步骤如下:

[root@sunny data]# docker network create --subnet=172.18.0.0/24 dockernetwork
4ddef2b0fe7db6200429977cf6f640fa9fdfb34f6e5a477652465533daec4728
[root@sunny data]# docker ps -a
CONTAINER ID   IMAGE      COMMAND                  CREATED         STATUS    PORTS     NAMES
863b930c08c3   postgres   "docker-entrypoint.s…"   4 minutes ago   Created             master
[root@sunny data]# docker rm master
master
[root@sunny data]# docker run -d \
> --network dockernetwork --ip 172.18.0.101 -p 5432:5432 \
> --name master -h master \
> -e "POSTGRES_DB=postgres" \
> -e "POSTGRES_USER=postgres" \
> -e "POSTGRES_PASSWORD=postgres" \
> -v /data/psql/pgsmaster:/var/lib/postgresql/data  postgres
51eb3d511fd3e26f1f9125df6c2035003390503994327025db58c372ff7aa8a5
[root@sunny data]# docker ps -a -f network=dockernetwork --format "table {{.Names}}\t{{.Image}}\t{{.RunningFor}}\t{{.Status}}\t{{.Networks}}\t{{.Ports}}"
NAMES     IMAGE      CREATED          STATUS          NETWORKS        PORTS
master    postgres   54 seconds ago   Up 54 seconds   dockernetwork   0.0.0.0:5432->5432/tcp, :::5432->5432/tcp
[root@sunny data]# docker exec -it master bash
root@master:/# psql -U postgres
psql (14.1 (Debian 14.1-1.pgdg110+1))
Type "help" for help.

postgres=# \du
                                   List of roles
 Role name |                         Attributes                         | Member of
-----------+------------------------------------------------------------+-----------
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}

postgres=# CREATE ROLE repuser WITH LOGIN REPLICATION CONNECTION LIMIT 5 PASSWORD '123456';
CREATE ROLE
postgres=# \du
                                   List of roles
 Role name |                         Attributes                         | Member of
-----------+------------------------------------------------------------+-----------
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
 repuser   | Replication                                               +| {}
           | 5 connections                                              |

postgres=# \q
root@master:/# exit
exit
[root@sunny data]# cd /data/psql/pgsmaster
[root@sunny pgsmaster]# ls
base    pg_commit_ts  pg_hba.conf    pg_logical    pg_notify    pg_serial     pg_stat      pg_subtrans  pg_twophase  pg_wal   postgresql.auto.conf  postmaster.opts
global  pg_dynshmem   pg_ident.conf  pg_multixact  pg_replslot  pg_snapshots  pg_stat_tmp  pg_tblspc    PG_VERSION   pg_xact  postgresql.conf       postmaster.pid
[root@sunny pgsmaster]# echo "host replication repuser 172.18.0.102/24 md5" >> pg_hba.conf
[root@sunny pgsmaster]# vi postgresql.conf
[root@sunny pgsmaster]# docker exec -it -u postgres master pg_ctl stop
waiting for server to shut down....[root@sunny pgsmaster]#
[root@sunny pgsmaster]# docker ps
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@sunny pgsmaster]# docker start master
master
[root@sunny pgsmaster]# docker ps
CONTAINER ID   IMAGE      COMMAND                  CREATED         STATUS         PORTS                                       NAMES
51eb3d511fd3   postgres   "docker-entrypoint.s…"   7 minutes ago   Up 3 seconds   0.0.0.0:5432->5432/tcp, :::5432->5432/tcp   master
[root@sunny pgsmaster]# docker run -d \
> --network dockernetwork --ip 172.18.0.102 -p 5433:5432 \
> --name slave -h slave \
> -e "POSTGRES_DB=postgres" \
> -e "POSTGRES_USER=postgres" \
> -e "POSTGRES_PASSWORD=postgres" \
> -v /data/psql/psslave:/var/lib/postgresql/data \
> -v /data/psql/psrepl:/var/lib/postgresql/repl \
> postgres
3ddc6f3967b4a3cee4ca9d71c97d5b1c697d7e63603dca64eaa0ca75eb5ac317
[root@sunny pgsmaster]# docker ps -a -f network=dockernetwork --format "table {{.Names}}\t{{.Image}}\t{{.RunningFor}}\t{{.Status}}\t{{.Networks}}\t{{.Ports}}"
NAMES     IMAGE      CREATED              STATUS              NETWORKS        PORTS
slave     postgres   About a minute ago   Up About a minute   dockernetwork   0.0.0.0:5433->5432/tcp, :::5433->5432/tcp
master    postgres   9 minutes ago        Up About a minute   dockernetwork   0.0.0.0:5432->5432/tcp, :::5432->5432/tcp
[root@sunny pgsmaster]#

[root@sunny pgsmaster]# docker exec -it -u postgres slave /bin/bash

postgres@slave:~/repl$ pg_basebackup -R -D /var/lib/postgresql/repl -Fp -Xs -v -P -h 172.18.0.101 -p 5432 -U repuser
Password:
pg_basebackup: initiating base backup, waiting for checkpoint to complete
pg_basebackup: checkpoint completed
pg_basebackup: write-ahead log start point: 0/4000028 on timeline 1
pg_basebackup: starting background WAL receiver
pg_basebackup: created temporary replication slot "pg_basebackup_148"
26288/26288 kB (100%), 1/1 tablespace
pg_basebackup: write-ahead log end point: 0/4000100
pg_basebackup: waiting for background process to finish streaming ...
pg_basebackup: syncing data to disk ...
pg_basebackup: renaming backup_manifest.tmp to backup_manifest
pg_basebackup: base backup completed
postgres@slave:~/repl$
[root@sunny psslave]# docker rm slave
slave
[root@sunny psslave]# docker run -d \
> --network dockernetwork --ip 172.18.0.102 -p 5433:5432 \
> --name slave -h slave \
> -e "POSTGRES_DB=postgres" \
> -e "POSTGRES_USER=postgres" \
> -e "POSTGRES_PASSWORD=postgres" \
> -v /data/psql/psslave:/var/lib/postgresql/data \
> postgres
c6f4973cb4657431f0ef301b9bce3b15ff0759d01f9fd7cb38d4483da9c05f24
[root@sunny psslave]# docker ps -a -f network=dockernetwork --format "table {{.Names}}\t{{.Image}}\t{{.RunningFor}}\t{{.Status}}\t{{.Networks}}\t{{.Ports}
>
[root@sunny psslave]# docker ps -a
CONTAINER ID   IMAGE      COMMAND                  CREATED          STATUS          PORTS                                       NAMES
c6f4973cb465   postgres   "docker-entrypoint.s…"   27 seconds ago   Up 26 seconds   0.0.0.0:5433->5432/tcp, :::5433->5432/tcp   slave
51eb3d511fd3   postgres   "docker-entrypoint.s…"   2 hours ago      Up 2 hours      0.0.0.0:5432->5432/tcp, :::5432->5432/tcp   master
[root@sunny psslave]# ps -aux | grep postgres
root      1613  0.0  0.0   4232   292 ?        Ss    2021   0:00 runsv postgresql
root      1632  0.0  0.0   4232   288 ?        Ss    2021   0:00 runsv postgres-exporter
root      1639  0.0  0.0   4376   536 ?        S     2021   0:02 svlogd -tt /var/log/gitlab/postgresql
root      1641  0.0  0.0   4376   484 ?        S     2021   0:00 svlogd -tt /var/log/gitlab/postgres-exporter
systemd+  6794  0.0  0.2 213264 19404 ?        Ss   11:43   0:00 postgres
systemd+  6874  0.0  0.0 213384  4032 ?        Ss   11:43   0:00 postgres: checkpointer
systemd+  6875  0.0  0.0 213264  3732 ?        Ss   11:43   0:00 postgres: background writer
systemd+  6876  0.0  0.0 213264  6624 ?        Ss   11:43   0:00 postgres: walwriter
systemd+  6877  0.0  0.0 213800  3440 ?        Ss   11:43   0:00 postgres: autovacuum launcher
systemd+  6878  0.0  0.0 213264  2608 ?        Ss   11:43   0:00 postgres: archiver last was 000000010000000000000004.00000028.backup
systemd+  6879  0.0  0.0  67856  2488 ?        Ss   11:43   0:00 postgres: stats collector
systemd+  6880  0.0  0.0 213700  2928 ?        Ss   11:43   0:00 postgres: logical replication launcher
systemd+ 19932  0.1  0.2 213264 19300 ?        Ss   13:36   0:00 postgres
systemd+ 20015  0.0  0.0 213400  2924 ?        Ss   13:36   0:00 postgres: startup recovering 000000010000000000000005
systemd+ 20016  0.0  0.0 213264  2440 ?        Ss   13:36   0:00 postgres: checkpointer
systemd+ 20017  0.0  0.0 213264  2972 ?        Ss   13:36   0:00 postgres: background writer
systemd+ 20018  0.0  0.0  67856  2300 ?        Ss   13:36   0:00 postgres: stats collector
systemd+ 20019  0.1  0.0 213660  4776 ?        Ss   13:36   0:00 postgres: walreceiver streaming 0/5000148
systemd+ 20020  0.0  0.0 213936  4180 ?        Ss   13:36   0:00 postgres: walsender repuser 172.18.0.102(52938) streaming 0/5000148
root     20145  0.0  0.0 112828   984 pts/1    S+   13:37   0:00 grep --color=auto postgres
[root@sunny psslave]#
[root@sunny psslave]# docker exec -it master bash
root@master:/# psql -U postgres
psql (14.1 (Debian 14.1-1.pgdg110+1))
Type "help" for help.

postgres=# select * from pg_stat_replication;
 pid | usesysid | usename | application_name | client_addr  | client_hostname | client_port |         backend_start         | backend_xmin |   state   | sent_lsn  | write_lsn | flush_lsn | replay_lsn | writ
e_lag | flush_lag | replay_lag | sync_priority | sync_state |          reply_time
-----+----------+---------+------------------+--------------+-----------------+-------------+-------------------------------+--------------+-----------+-----------+-----------+-----------+------------+-----
------+-----------+------------+---------------+------------+-------------------------------
 167 |    16384 | repuser | walreceiver      | 172.18.0.102 |                 |       52938 | 2022-03-11 05:36:35.269344+00 |              | streaming | 0/5000148 | 0/5000148 | 0/5000148 | 0/5000148  |
      |           |            |             1 | sync       | 2022-03-11 05:39:45.781351+00
(1 row)

postgres=# CREATE DATABASE test;
CREATE DATABASE
postgres=# \list
                                 List of databases
   Name    |  Owner   | Encoding |  Collate   |   Ctype    |   Access privileges
-----------+----------+----------+------------+------------+-----------------------
 postgres  | postgres | UTF8     | en_US.utf8 | en_US.utf8 |
 template0 | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
           |          |          |            |            | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
           |          |          |            |            | postgres=CTc/postgres
 test      | postgres | UTF8     | en_US.utf8 | en_US.utf8 |
(4 rows)

postgres=# \c test
You are now connected to database "test" as user "postgres".
test=# CREATE TABLE test (
  "id" int4 NOT NULL,
  "value" varchar(255),
  PRIMARY KEY ("id")
);
CREATE TABLE
test=# \dt
        List of relations
 Schema | Name | Type  |  Owner
--------+------+-------+----------
 public | test | table | postgres
(1 row)
test=# insert into test select generate_series(1,10);
INSERT 0 10
test=# select * from test;
 id | value
----+-------
  1 |
  2 |
  3 |
  4 |
  5 |
  6 |
  7 |
  8 |
  9 |
 10 |
(10 rows)

test=#
查看从库
[root@sunny psql]# docker exec -it slave bash
root@slave:/# psql -U postgres
psql (14.1 (Debian 14.1-1.pgdg110+1))
Type "help" for help.

postgres=# \list
                                 List of databases
   Name    |  Owner   | Encoding |  Collate   |   Ctype    |   Access privileges
-----------+----------+----------+------------+------------+-----------------------
 postgres  | postgres | UTF8     | en_US.utf8 | en_US.utf8 |
 template0 | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
           |          |          |            |            | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
           |          |          |            |            | postgres=CTc/postgres
 test      | postgres | UTF8     | en_US.utf8 | en_US.utf8 |
(4 rows)

postgres=# \dt
Did not find any relations.
postgres=# \c test
You are now connected to database "test" as user "postgres".
test=# \dt
        List of relations
 Schema | Name | Type  |  Owner
--------+------+-------+----------
 public | test | table | postgres
(1 row)

test=#
test=# select * from test;
 id | value
----+-------
  1 |
  2 |
  3 |
  4 |
  5 |
  6 |
  7 |
  8 |
  9 |
 10 |
(10 rows)

test=#

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论