您的位置:首页 > 运维架构 > Docker

Docker实现Timescale+pgpool-II复制的高可用(六)

2020-01-13 16:13 281 查看

Docker实现Timescale+pgpool-II复制的高可用

  • 4.修改配置文件
  • 5.run一个新的容器,将文件挂载进去
  • 6.设置 ssh免密登录
  • 7.测试:
  • 8.错误:
  • 一、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
    • 点赞
    • 收藏
    • 分享
    • 文章举报
    昨夜冻成狗 发布了12 篇原创文章 · 获赞 10 · 访问量 1323 私信 关注
    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: