PostgreSQL实战(下):repmgr主从自动切换
本系列分为上下2篇,上篇是搭建PostgreSQL主从集群,下篇是使用repmgr配置高可用PostgreSQL集群。推荐先阅读上篇文章了解Postgres主从搭建和手动切换方法之后,再阅读本文。
接上一篇文章,已经搭建好了PostgresSQL服务器,而且已经配置好了主从,现在尝试使用repmgr来管理PostgresSQL的高可用自动切换。
接上一篇文章,现在主从关系如下:
- standby server: 172.17.0.7
- primary server: 172.17.0.8
安装和配置repmgr
在主从服务器上同时进行如下操作:
# yum -y install postgresql10-devel flex git make unzip gcc
# git clone https://github.com/2ndQuadrant/repmgr
# export PG_CONFIG=/usr/pgsql-10/bin/pg_config
# cd repmgr
# ./configure && make isntall
分别在主从上创建配置文件: /data/pgsql_data/repmgr.conf,在172.17.0.7上的文件内容:
node_id=1
node_name='172.17.0.7'
conninfo='host=172.17.0.7 user=replicauser dbname=repmgr connect_timeout=2'
data_directory='/data/pgsql_data/10/data'
172.17.0.8上的 /data/pgsql_data/repmgr.conf 文件内容
node_id=2
node_name='172.17.0.8'
conninfo='host=172.17.0.8 user=replicauser dbname=repmgr connect_timeout=2'
data_directory='/data/pgsql_data/10/data'
在primary机器(172.17.0.8)创建repmgr数据库,并给用于同步的用户(replicauser)授权,使用postgres用户操作。
$ createdb repmgr
$ psql
postgres=# alter user replicauser superuser login;
ALTER ROLE
postgres=# alter database repmgr owner to replicauser;
ALTER DATABASE
接着在primary机器(172.17.0.8)上启动repmgr,并注册为primary,用postgres用户执行:
$ /usr/pgsql-10/bin/repmgr -f /data/pgsql_data/repmgr.conf primary register
INFO: connecting to primary database...
NOTICE: attempting to install extension "repmgr"
NOTICE: "repmgr" extension successfully installed
NOTICE: primary node record (ID: 2) registered
$ /usr/pgsql-10/bin/repmgr cluster show # 查看集群状态
ID | Name | Role | Status | Upstream | Location | Prio. | TLI
----+------------+---------+-----------+----------+----------+-------+-----
2 | 172.17.0.8 | primary | * running | | default | 100 | 2
primary机器(172.17.0.8)上的repmgr至此已经就绪,接下来操作standby机器(172.17.0.7)。先删除standby上的数据目录,因为standby上的数据同步要使用repmgr程序进行。
$ rm -rf /data/pgsql_data/10/data/*
$ /usr/pgsql-10/bin/repmgr -h 172.17.0.8 -U replicauser -d repmgr -f /data/pgsql_data/repmgr.conf standby clone --dry-run # 172.16.49.183是主节点ip,dry-run是测试,不实际执行
$ /usr/pgsql-10/bin/repmgr -h 172.17.0.8 -U replicauser -d repmgr -f /data/pgsql_data//repmgr.conf standby clone # 执行clone,从master上同步数据
# systemctl restart postgresql-10 # 已root用户重启postgresql服务
$ /usr/pgsql-10/bin/repmgr -f /data/pgsql_data/repmgr.conf standby register --force # 注册为standby,force的作用是在重新注册的时候,强制更新upstream id, 否则可能导致自动切换失败
INFO: connecting to local node "172.17.0.7" (ID: 1)
INFO: connecting to primary database
WARNING: --upstream-node-id not supplied, assuming upstream node is primary (node ID 2)
INFO: standby registration complete
NOTICE: standby node "172.17.0.7" (ID: 1) successfully registered
# 再次查看集群
$ /usr/pgsql-10/bin/repmgr cluster show --compact
ID | Name | Role | Status | Upstream | Location | Prio. | TLI
----+------------+---------+-----------+------------+----------+-------+-----
1 | 172.17.0.7 | standby | running | 172.17.0.8 | default | 100 | 2
2 | 172.17.0.8 | primary | * running | | default | 100 | 2
配置repmgrd自动切换
在2台机器上修改主配置文件/data/pgsql_data/10/data/postgresql.conf
:
...
shared_preload_libraries = 'pg_stat_statements,repmgr'
...
然后用root用户重启postgresql
# systemctl restart postgresql-10.service
接下来修改repmgrd的配置文件/data/pgsql_data/repmgr.conf
,在repmgr.conf文件中追加如下5行,用来指定故障发生时的切换行为。
……
log_file='/tmp/repmgr.log'
pg_bindir='/usr/pgsql-10/bin/'
failover=automatic # 开启自动故障切换
promote_command='/usr/pgsql-10/bin/repmgr standby promote -f /data/pgsql_data/repmgr.conf --log-to-file'
follow_command='/usr/pgsql-10/bin/repmgr standby follow -f /data/pgsql_data/repmgr.conf --log-to-file --upstream-node-id=%n'
在各个节点上使用postgres用户启动repmgrd
$ /usr/pgsql-10/bin/repmgrd -f /data/pgsql_data/repmgr.conf
故障切换测试
在primary服务器(172.17.0.8)上停掉postgresql,模拟primary服务器发生故障。
$ /usr/pgsql-10/bin/pg_ctl -D /data/pgsql_data/10/data/ -m immediate stop
waiting for server to shut down.... done
server stopped
此时,切换到standby服务器(172.17.0.7)上持续观察集群状态,大约一分钟之后,172.17.0.7切换为primary,查看集群状态结果如下:
$ /usr/pgsql-10/bin/repmgr cluster show --compact
ID | Name | Role | Status | Upstream | Location | Prio. | TLI
----+------------+---------+-----------+----------+----------+-------+-----
1 | 172.17.0.7 | primary | * running | | default | 100 | 3
2 | 172.17.0.8 | primary | - failed | ? | default | 100 |
WARNING: following issues were detected
- unable to connect to node "172.17.0.8" (ID: 2)
HINT: execute with --verbose option to see connection error messages
此时,172.17.0.7成为新的primary,数据库变为可写。如果此时启动 172.17.0.8 会发生什么呢?
在172.17.0.8执行如下命令启动postgresql。
$ /usr/pgsql-10/bin/pg_ctl -D /data/pgsql_data/10/data/ start
分别到2台机器上查看集群状态:
# 在 172.17.0.7 上看到的集群状态如下
$ repmgr cluster show --compact
ID | Name | Role | Status | Upstream | Location | Prio. | TLI
----+------------+---------+-----------+----------+----------+-------+-----
1 | 172.17.0.7 | primary | * running | | default | 100 | 3
2 | 172.17.0.8 | primary | ! running | | default | 100 | 2
WARNING: following issues were detected
- node "172.17.0.8" (ID: 2) is running but the repmgr node record is inactive
# 在 172.17.0.8 上看到的集群状态如下
$ repmgr cluster show --compact
ID | Name | Role | Status | Upstream | Location | Prio. | TLI
----+------------+---------+----------------------+----------+----------+-------+-----
1 | 172.17.0.7 | standby | ! running as primary | | default | 100 | 3
2 | 172.17.0.8 | primary | * running | | default | 100 | 2
WARNING: following issues were detected
- node "172.17.0.7" (ID: 1) is registered as standby but running as primary
发现2台机器现实的集群状态不一样,这就是明显的脑裂现象,需要我们手动干预来修复。修复的操作方法和重新配置新的standby机器一样,把172.17.0.8配置为172.17.0.7的standby,看前面的操作步骤即可,不再做详细演示。
优化故障切换行为
在现在的情况下,如果发生故障,既不会给相关人员发送通知去人工干预恢复主从配置,也不会发生Primary服务器的IP地址切换,此时我们都不知道发生了问题,客户端的请求还是会连接到原来的主服务器而持续报错。
我们可以通过定制脚本来完成这些自动化的功能。一种可行的方法是给主服务器设置一个域名,当发生主从切换的时候,同时把域名也解析到新的primary服务器上。当应用通过域名重连数据库的时候,就可以连接到新的primary机器。
下面是一个待完成的通知和域名切换脚本/data/pgsql_data/promote_postgresql.sh
:
#!/bin/bash
notification_api="http://api.xnow.me/api/message"
dns_api="http://dnsapi.xnow.me/api/record"
domain="xnow.me"
record="primary.postgresql" # 完整的primary域名是 primary.postgresql.xnow.me
server_ip=$1 # 把新的primary ip传递进来
send_notification() {
curl -X POST -H "content-type:application/json" $notification_api \
-d '{"title": "PostgreSQL发生了主从切换", "type": "wechat", "to":["someone"], "content": "'"PostgreSQL: $server_ip promote to be new primary, start switchover domain $record.$domain to $server_ip."'"}'
}
record_id=$(curl "$dns_api?domain=${domain}&record=${record}" | jq .data[0].id)
switchover_dns() {
curl -X PUT -H "content-type:application/json" $dns_api \
-d '{"status": 1, "value": "'"$server_ip"'", "type": "A", "record": "'"$record"'", "line": "default", "domain": "'"$domain"'","record_id": "'"${record_id}"'"}'
}
send_notification
switchover_dns
注意:这个脚本是搭配了我们公司的DNS和通知发送的http api服务使用,如果没有这种的api或者api参数不一样,是肯定无法使用这个脚本的。所以,这个脚本只是用作简单的示范。
可以使用多个方法来完成以上脚本的这些工作,比如使用python编写切换和通知脚本,使用邮件smtp等各种方式来实现通知。但是目标就是实现问题通知和域名切换。
我们接着配置repmgr的配置文件,修改/data/pgsql_data/repmgr.conf
,修改promote_command这一行
...
promote_command='/usr/pgsql-10/bin/repmgr standby promote -f /data/pgsql_data/repmgr.conf --log-to-file && bash /data/pgsql_data/promote_postgresql.sh 172.17.0.7' # 修改这行调用上面的脚本,参数172.17.0.7更换为本机的ip地址
...
保存退出后重启repmgrd服务
$ kill $(cat /tmp/repmgrd.pid)
$ /usr/pgsql-10/bin/repmgrd -f /data/pgsql_data/repmgr.conf
完成上面的工作,就已经是一个可以在生产环境使用的高可用postgresql服务了。但是,postgresql并不是我的工作领域,上面的内容也许有很多错误,还请谨慎使用。
其它方案
除了repmgr这个方案外,还有许多postgresql的高可用方案,比如keepalived的虚ip切换等等。不同方案有自己的优势,在使用中可以广泛比较和参考。
参考:
Repmgr: http://citusdb.cn/?p=1068
PostgreSQL使用repmgr配置级联复制:https://my.oschina.net/u/4360424/blog/3217743
repmgrd basic configuration:https://repmgr.org/docs/4.0/repmgrd-basic-configuration.html
当前暂无评论 »