Docker实现Timescale+pgpool-II复制的高可用(六)
Docker实现Timescale+pgpool-II复制的高可用具体步骤具体步骤1.运行普通容器2.将容器内的两个文件夹拷贝出来3.修改初始化脚本4.修改配置文件5.run一个新的容器,将文件挂载进去6.测试:进入timescale,psql -h192.168.50.34 -p9999 -Upostgres密码1234567.show pool_nodes...
Docker实现Timescale+pgpool-II复制的高可用
一、pgpool-II简介
pgpool-II的作用,可以以redis的sentinel作参考,都是为了完成主从复制的高可用,实现故障迁移。对于Timescale,或者PostgreSQL数据库来说,基于流复制的故障迁移,有pgpool,pacemaker+corosync等解决方案。这里选择了pgpool,而pgpool-I已经被弃用,所以自然而然的选择了pgpool-II中间件技术。
pgpool-II可以看作一个,介于服务器和客户端之间的中间件,对应数据库服务器来说,它就相当于客户端;对于客户端来说,它就相当于服务器。
二、参考文件
配置流程及配置文件参考:
Postgresql流复制+pgpool实现高可用
PGPool-II+PG流复制实现HA主备切换
完整配置文件参考:pgpool-II 手册
入门教程参考:pgpool-II 入门教程
官方网站:pgpool Wiki
三、注意
该文章,是基于上篇文件的基础上进行配置,已经配置好了Timescale数据库的主从异步流复制,是在此基础上完成进一步的故障迁移的。
上篇文章参考:Docker实现TimescaleDB 基于异步流的主从复制(四)
四、具体步骤
1.运行普通容器
docker run postdock/pgpool:latest
2.将容器内的两个文件夹拷贝出来
docker cp 容器id:/usr/local/etc /data/pgpool
docker cp 容器id:/usr/local/bin/pgpool /data/pgsh
解释:将对应容器id内部的冒号后的文件内容,拷贝到容器外部,即第二个文件中。比如上例,将容器id
内部的/usr/local/bin/pgpool
文件夹内容,拷贝到容器外部/data/pgsh
文件夹中。所以,容器内部的地址不能随意改变,容器外部的文件地址可根据需求自定义。
注意:docker cp 容器外部地址 容器id:容器内部地址
,即将两个地址反过来,是将容器外部的文件拷贝到容器内部。
3.修改初始化脚本
(1)修改pgpool_setup.sh脚本文件
A. 将pgpool_setup.sh
文件的cp -f /var/pgpool_configs/pgpool.conf $CONFIG_FILE
前用#
注释,一般情况下,位于配置文件的第三行,即:
# cp -f /var/pgpool_configs/pgpool.conf $CONFIG_FILE
原因:该版本docker容器重启时,会初始化配置文件,该行的作用就是初始化配置文件,将该行注释,即重启docker容器时,不会改变配置文件。
B. 再将该文件以下这行注释,位于pgpool_setup.sh
文件的第五行:
# echo "host all all 0.0.0.0/0 md5" > $HBA_FILE
原因:该行的作用,是每次重启docker容器时,默认将host all all 0.0.0.0/0 md5
语句输入到pool_hba.conf
文件中,导致无法修改该文件(即每次修改该文件后,重启docker容器,该文件又会回复到默认状态)。
(2)修改entrypoint.sh脚本文件
在entrypoint.sh
文件的最后一句后面添加:
gosu postgres /usr/local/bin/pgpool/pgpool_start.sh >> /usr/local/etc/pgpool.log
原因:将配置文件输出到/usr/local/etc/pgpool.log
文件中,但目前不知什么原因,文件可以被创建出来,但内里无日志。
4.修改配置文件
(1)修改pool_passwd
打开配置文件,其中应该会有之前在PostgreSQL中,配置的postgres
账号,以及其密码123456
的md5格式,即:
postgres:md5a3556571e93b0d20722ba62be61e8c2d
所以不用修改该文件。如果没有,可去对应数据库用select usename,passwd from pg_shadow;
语句查询。
同时,该配置文件会自动添加一行数据:
replication_user:md587cb5f1bfe7a883399a0b24a741e252c
这也是我们在上一篇中,配置该用户的原因。如果不在上篇文章中配置,在此时配置应该也是可以的(未测试)。
上篇文章参考:Docker实现TimescaleDB 基于异步流的主从复制(四),其中主机配置的第6小节:配置pgpool用户。
(2)配置pgpool.conf文件
listen_addresses = '*'
port = 9999
pcp_socket_dir = '/tmp'
# 配置主节点
backend_hostname0 = '192.168.50.34' #主机ip
backend_port0 = 5432
backend_weight0 = 1 #loadbalance不开启,无效
backend_data_directory0 = '/var/lib/postgresql/9.5/main'
backend_flag0 = 'ALLOW_TO_FAILOVER'
# 配置从节点
backend_hostname1 = '192.168.50.31'
backend_port1 = 5432
backend_weight1 = 1
backend_data_directory1 = '/data1'
backend_flag1 = 'ALLOW_TO_FAILOVER'
#配置其他
enable_pool_hba = on
pool_passwd = 'pool_passwd'
replication_mode = off
load_balance_mode = on
master_slave_mode = on
master_slave_sub_mode = 'stream'
sr_check_period = 5
sr_check_user = 'repuser' #流复制账号,第四篇配置的超级账号
sr_check_password = '123456'
sr_check_database = 'postgres'
# 修改pid地址,该地址需要与容器内部地址一致,不一定与下面地址相同
pid_file_name = '/var/run/postgresql/pgpool.pid'
# 添加故障迁移脚本
failover_command = '/usr/local/etc/failover.sh %d %P %H %R'
#健康检查(自动检查主机宕机,然后执行故障迁移脚本)
health_check_period = 10
health_check_timeout = 10
health_check_user = 'postgres'
health_check_password = '123456'
health_check_database = 'postgres'
health_check_max_retries = 0
health_check_retry_delay = 1
connect_timeout = 10000
# 添加日志配置(根据自己的情况配置)
log_destination = 'stderr'
client_min_messages = debug5
log_min_messages = debug5
(3)配置pool_hba.conf文件
host replication repuser 0.0.0.0/0 trust
host all all 0.0.0.0/0 md5
该文件会有默认配置:host all all 0.0.0.0/0 md5
。仅在该文件添加一行:host replication repuser 0.0.0.0/0 trust
。添加的该行配置是在pg_hba.conf
文件中IPv6
底下的一行。
(4)配置pcp.conf文件
在该文件中添加:
pgpool:5f4dcc3b5aa765d61d8327deb882cf99
作用:该配置文件的作用,是在pgpool容器中,运行pcp
相关命令时(特指pcp_attach_node
命令),提供账号、密码的输入功能。
md5:5f4dcc3b5aa765d61d8327deb882cf99
是password
这几个字母的md5格式。
注:该数据,是通过在pgpool-II容器中,运行/usr/sbin/pg_md5 password
命令而得。经测试,所有该容器的运行结果都是该值,所以直接将之上数据,添加到该文件即可。
(5)创建failover.sh脚本文件,修改权限777
该文件位于/data/pgpool
文件夹下。
#!/bin/bash
falling_node=$1
old_primary=$2
new_primary=$3
pgdata=$4
currTime=$(date +"%Y-%m-%d %T")
pghome=/opt/pgsql
log=/tmp/failocer.log
date >> $log
echo $currTime
echo "falling_node =$falling_node "
echo "old_primary=$old primary"
echo "new_primary=$new_primary "
echo "pgdata=$pgdata "
ssh -T root@new_primary /data/pgpool/a.sh
exit 0 ;
该脚本会由健康检测机制,自动检测宕掉的机器,然后执行该脚本文件。
日志会打印在/data/pgpool/pgpool.log
文件中。
(6)创建a.sh脚本文件,修改权限777
该脚本文件位于/data/pgpool
文件夹下。
#!/bin/bash
docker exec -i 51b4cc62ad49 su postgres -c "/usr/local/bin/pg_ctl promote"
注意:-i
,没有t。
如果为-it
,会报错:报错:the input device is not a TTY
5.run一个新的容器,将文件挂载进去
docker run -p 9999:9999 -v /data/pgpool:/usr/local/etc -v /data/pgsh:/usr/local/bin/pgpool postdock/pgpool:latest
6.设置 ssh免密登录
设置pgpool容器与容器外部主机和备机的免密登录。
参考文档:Linux远程登录免密码设置
(1)在pgpool容器中下载openssh
因为该容器存在问题,yum以及apt-get无法使用,不能使用apt-get install openssh-server
直接下载openssh,所以使用压缩包安装openssh。
下载网址:mirror.sfo12.us.leaseweb.net,我下载的7.4版本,即openssh-7.4p1.tar.gz
。
使用ftp上传至linux系统的/opt
文件,将该文件拷贝进容器中:(习惯性的将第三方软件放在/opt
文件中)
docker cp /opt/openssh-7.4p1.tar.gz 容器id:/opt
解压缩:
进入/opt
文件夹中,运行以下命令:
tar -zxvf openssh-7.4p1.tar.gz
如此,就可以使用ssh
相关命令了。
(2)在pgpool容器内部生成密钥对
ssh-keygen
连续回车,最后会生成随机RSA 2048
图,即表示成功。
同时,会在容器的/root/.ssh
隐藏文件夹中,生成公钥文件id_rsa.pub
,如下所示:
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCt/cBpRoTKyIA2QlEkcQur2rR8wKhAqhKZ8PluIly/KcX1oo/fvRAE+NhvHjY+y/NrSkWo145ks9/tPnDR/MaGYhveE9FGgBXrQg8gvFpPmtvHxnb2s2fsg176QLB9FnjGMZk2bSvfl8yje07xfuNVZCNOrbspoYVO+F49ijfzALayktDEyxbkwztHjOLoKkB0yZRP5hH1d2yhFTOtmMZ+5ZJh6Glq5mHX7foFFy0JjLaUtqO/Xyf82JAUAYnLNIF33513DUSkWepKOZo3CvpmKMl4ZDouVkOl4h0VzgIhA2zr6f2ODbKUDSprJoP/7D0WV4jX7ttDJG/PSb+tG+bz root@398823f95a99
验证该公钥是否正确,拉取到最后,看是否为root@容器id
。
(3)将容器内部的文件拷贝至容器外部
将第(2)步,容器内部生成的公钥id_rsa.pub
,拷贝至主机和备机的authorized_keys
文件夹中。id_rsa.pub
文件位于~/.ssh
,即/root/.ssh
隐藏文件夹中,authorized_keys
文件夹同样位于/root/.ssh
隐藏文件夹中。
拷贝文件,容器外部运行命令:
docker cp pgpool容器id:/root/.ssh/id_rsa.pub /root/.ssh/authorized_keys
这是将本机的pgpool容器与本机完成了免密登录,如果要进行本机的pgpool容器与外机完成免密登录,同样需要将此文件,拷贝至外机的该目录下。但由于该文件位于隐藏文件夹下,不能直接使用ftp软件完成下载和上传。所以需要将该文件从隐藏文件夹下,拷贝出来,借助中转拷贝。
将本机的id_rsa.pub
文件从隐藏文件中拷贝出来(随便一个地址):
cp /root/.ssh/id_rsa.pub /root
使用ftp软件,将该文件下载到本地,再上传至外机。
在外机进行操作,将此文件拷贝至authorized_keys
文件中:
cp /pub文件地址/id_rsa.pub /root/.ssh/authorized_keys
(4)使用免密登录
在pgpool容器内部,使用命令:
ssh root@外部ip
即可免密码登入主机备机,使用exit
登出。
如果有免密登录容器内部的需求:
ssh root@容器id
7.测试:
(1)初始正常节点
进入timescale容器内部(主从皆可),
运行su postgres
命令,切换到postgres 用户,
运行psql -h192.168.50.34 -p9999 -Upostgres
命令,输入密码123456
,
运行show pool_nodes;
命令,显示:
可见,主机为34,备机为31.
(2)故障迁移–宕掉主机,备机提升为primary
目前因脚本未完全配置,故障迁移需手动迁移,情况如下:
宕掉主机34的timescale容器,进入pgpool容器,免密登录至31备机,
运行docker exec -it 51b4cc62ad49 su postgres -c "/usr/local/bin/pg_ctl promote"
命令,
报错:pg_ctl: cannot promote server; server is not in standby mode
,
[所以不需要运行该命令]
进入容器内部,连接pgpool:
经测试:不通过容器内ssh登录,直接去外机运行相应命令,也可进行主备切换。
查看节点:
可见,31被提升为了主机。
启动34的timescale容器,重新连接,查看节点,34状态为down,存在问题。
(3)故障恢复–将宕掉的主机重新以stanbdy的身份加入到pgpool
目前脚本有问题,需在容器外手动执行a.sh
脚本文件中的内容。
修改.done
为.conf
启动34节点的timescale容器,
进入pgpool容器中,执行:
pcp_attach_node -d -U pgpool -p9898 -n 0
输入密码:password
查看节点:
目前存在的问题:虽然显示的为34复制主机,但是用navicat软件添加数据,复制不成功。
以下为之前恢复所做笔记(不用看):
A. 修改配置文件pgpool_conf
,将host0改为现在的primary–31,将host1改为现在的standby–34,重启pgpool容器。
注意:经测试,仅改变配置文件,就可以进行故障恢复。不过存在,手动恢复比较繁琐的问题。
B. 进入pgpool容器,运行命令,将节点34添加到pgpool中:
B1 参考博客的写法:
/usr/sbin/pcp_attach_node 10 localhost 9898 pgpool cloud 0
B2 pcp_attach_node --help
结果:
root@33058e47e47d:/# /usr/sbin/pcp_attach_node --help
pcp_attach_node - attach a node from pgpool-II
Usage:
pcp_attach_node [OPTION...] [node-id]
Options:
-U, --username=NAME username for PCP authentication
-h, --host=HOSTNAME pgpool-II host
-p, --port=PORT PCP port number
-w, --no-password never prompt for password
-W, --password force password prompt (should happen automatically)
-n, --node-id=NODEID ID of a backend node
-d, --debug enable debug message (optional)
-v, --verbose output verbose messages
-?, --help print this help
B3.我的写法:
B3.0 根据 A 修改配置文件,改变节点。(改变配置文件,为手动恢复;)
B3.1 修改pgpool.conf
配置文件:
pcp_socket_dir = '/tmp'
不然会报错:
ERROR: connection to socket "/tmp/.s.PGSQL.9898" failed with error "No such file or directory"
B3.2 进入pgpool容器,运行以下命令:
/usr/sbin/pcp_attach_node 10 localhost 9898 pgpool postgres 0 -v -d
输入密码:123456
报错:
FATAL: authentication failed for user "root"
DETAIL: username and/or password does not match
B3.3 进入timescale容器,查看节点:
可见:34由down提升为up,节点从0变为1,正式成为备机。
疑惑:
a.我对该添加节点命令的疑惑与理解
10
不知道什么意思,
localhost
是pgpool所在主机ip,
9898
是默认端口,
pgpool
不知道是什么名,应该是默认?,
postgres
猜测是在pool_passwd
配置文件中配置的账号,
0
是使用show nodes;
查询到的34节点。
8.错误:
(1)连接错误
问题日志:
如果测试时,产生错误(主要产生于第一次配置好pgpool,用timescale连接pgpool,查看节点的时候):
DETAIL: message length (12) in slot 1 does not match with slot 0(8)
那么,就是timescale的pg_hba.conf
文件的问题,
解决方案:
修改timescale的pg_hba.conf
文件,全部注释,添加:
host all all 0.0.0.0/0 md5
参考博客(虽然也没啥卵用,仅供参考):
登录 pgpool 的 9999 提示 DETAIL: message length (12) in slot 1 does not match with slot 0(8)
(2)pgpool容器重启不了
查看问题:使用docker logs docker容器id
查看容器日志。
错误信息:
2019-12-16 01:04:17: pid 23: FATAL: failed to bind a socket: "/tmp/.s.PGSQL.9898"
2019-12-16 01:04:17: pid 23: DETAIL: bind socket failed with error: "Address already in use"
这是由于容器没有正常关闭,tmp缓存文件未清除,所以导致地址信息被占用。
参考文档:pgpool-ii 安装手册 基于Centos7.3
解决方案:
在entrypoint.sh
文件中,添加/修改:
rm -f /tmp/.s.PGSQL*
总结:
引起该问题的原因,是因为我们在pgpool.conf
配置文件中,修改pcp_socket_dir = '/tmp'
而导致的。
但是该信息必须修改,不然会报另一个错误==>(3) 故障恢复—>无/tmp/.s.PGSQL.9898
文件错误。
(3)故障恢复——>无/tmp/.s.PGSQL.9898
文件错误。
错误日志:
ERROR: connection to socket "/tmp/.s.PGSQL.9898" failed with error "No such file or directory"
解决方案:
修改pgpool.conf
配置文件:
pcp_socket_dir = '/tmp'
备机pghba
local all all md5
host replication repuser 0.0.0.0/0 trust
host all all all md5
host all all 0.0.0.0/0 md5
备机poolhba
host replication repuser 0.0.0.0/0 trust
host all all 0.0.0.0/0 md5
主机pghba
local all all md5
host replication repuser 0.0.0.0/0 trust
host all all all md5
host all all 0.0.0.0/0 md5
更多推荐
所有评论(0)