一、patroni介绍

PostgreSQL是一款功能,性能,可靠性都可以和高端的国外商业数据库相媲美的开源数据库。而且PostgreSQL的许可和生态完全开 放,不被任何一个单一的公司或国家所操控,保证了使用者没有后顾之忧。国内越来越多的企业开始用PostgreSQL代替原来昂贵的国外 商业数据库。

Patroni不仅简单易用而且功能非常强大,具备如下特点

  • 支持自动failover和按需switchover

  • 可以定时执行switchover

  • 支持一个和多个备节点

  • 支持级联复制

  • 支持同步复制,异步复制

  • 支持同步复制下备库故障时自动降级为异步复制(功效类似于MySQL的半同步,但是更加智能)

  • 支持控制指定节点是否参与选主,是否参与负载均衡以及是否可以成为同步备机

  • 支持通过pg_rewind自动修复旧主

  • 支持多种方式初始化集群和重建备机,包括pg_basebackup和支持wal_e,pgBackRest,barman等备份工具的自定义脚本

  • 支持自定义外部callback脚本

  • 支持REST API

二、patroni高可用搭建

前提:需要至少三个节点

安装 patroni

yum install python3 -y
yum install python3-psycopg2-2.8.5-2.rhel7.x86_64.rpm -y 
yum install patroni-1.6.5-1.rhel7.x86_64.rpm -y

安装 安装配置etcd(etcd需要安装在多个pg节点上)

yum install etcd

etcd配置启动

vi /etc/etcd/ectd.conf
ETCD_NAME="node1"
ETCD_DATA_DIR="/var/lib/etcd/data.etcd"
ETCD_LISTEN_PEER_URLS="http://10.1.122.55:2380" ETCD_LISTEN_CLIENT_URLS="http://10.1.122.55:2379,http://127.0.0.1:2379" ETCD_ADVERTISE_CLIENT_URLS="http://10.1.122.55:2379,http://127.0.0.1:2379" ETCD_INITIAL_ADVERTISE_PEER_URLS="http://10.1.122.55:2380" ETCD_INITIAL_CLUSTER="node1=http://10.1.122.55:2380,node2=http://10.1.122.56:2380,node3=http://10.1.122.57:2380" ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_ENABLE_V2="true"

安装Watchdog

yum install watchdog -y

适用场景

  • 主节点 patroni 进程被 kill

  • 主节点 patroni因内存资源超出而照成的崩溃或者是高负载系统下 patroni 被卡死这样的 单点故障

  • 网络故障

处理方式

当遇到上述情景时,watch 会触发主节点系统重启,启动后用开机服务来自动开启 etcd和 patroni,postgres。从库在主库 down 掉 后提升为主,原主在重启完毕恢复后降级为备机

回调脚本

如下是一个vip切换的回调脚本

#!/bin/bash
VIP=10.1.122.222 # VIP地址
GATEWAY=10.1.122.1 #网关,使用ip route命令查看
DEV=eth0 #网卡设备
action=$1
role=$2
cluster=$3

log()
{
echo "loadvip: $*"|logger
}

load_vip()
{
ip a|grep -w ${DEV}|grep -w ${VIP} >/dev/null
if [ $? -eq 0 ] ;then
log "vip exists, skip load vip"
else
sudo ip addr add ${VIP}/32 dev ${DEV} >/dev/null
rc=$?
if [ $rc -ne 0 ] ;then
log "fail to add vip ${VIP} at dev ${DEV} rc=$rc"
exit 1
fi
log "added vip ${VIP} at dev ${DEV}"

arping -U -I ${DEV} -s ${VIP} ${GATEWAY} -c 5 >/dev/null
rc=$?
if [ $rc -ne 0 ] ;then
log "fail to call arping to gateway ${GATEWAY} rc=$rc"
exit 1
fi
log "called arping to gateway ${GATEWAY}"
fi
}

unload_vip()
{
ip a|grep -w ${DEV}|grep -w ${VIP} >/dev/null
if [ $? -eq 0 ] ;then
sudo ip addr del ${VIP}/32 dev ${DEV} >/dev/null
rc=$?
if [ $rc -ne 0 ] ;then
log "fail to delete vip ${VIP} at dev ${DEV} rc=$rc"
exit 1
fi
log "deleted vip ${VIP} at dev ${DEV}"
else
log "vip not exists, skip delete vip"
fi
}

log "loadvip start args:'$*'"
case $action in
on_start|on_restart|on_role_change)
case $role in
master)
load_vip
;;
replica)
unload_vip
;;
*)
log "wrong role '$role'"
exit 1
;;
esac
;;
on_stop)
unload_vip
;;
*)
log "wrong action '$action'"
exit 1
;;
esac

设置 patroni的配置文件(三个节点都需要设)

/opt/app/patroni/etc/postgresql.yml

# 集群名称
scope: pgcluster
namespace: /service/

# 节点名称
name: pg1

parameters: null

callbacks:
  on_start: /bin/bash /opt/app/patroni/bin/loadvip.sh
  on_restart: /bin/bash /opt/app/patroni/bin/loadvip.sh
  on_role_change: /bin/bash /opt/app/patroni/bin/loadvip.sh
  on_stop: /bin/bash /opt/app/patroni/bin/loadvip.sh

watchdog:
  mode: automatic
  device: /dev/watchdog
  safety_margin: 5

tags:
  nofailover: false
  noloadbalance: false
  clonefrom: false
  nosync: false

其他从节点也进行相应的配置

如何进行切换

patronictl -c /opt/app/patroni/etc/postgresql.yml switchover

patroni的部署文档参考 :https://blog.51cto.com/lqding/4202040