Patroni集群切换辅助:如何编写自动化shell脚本实现切主后重启副本
Patroni 集群Switchover自动重启副本Shell脚本实现方案
脚本核心执行流程
整个脚本按照「校验→切换→等待→识别→重启→二次校验」的逻辑设计,避免异常操作影响集群可用性:
- 前置校验:检查集群健康状态,确认所有节点在线、无同步延迟,满足switchover条件
- 执行主节点切换:调用你已掌握的curl命令完成主节点晋升
- 等待集群状态收敛:等待新主状态变为
running,所有副本同步追平新主的WAL日志 - 识别副本节点:调用Patroni集群API拉取节点列表,过滤出所有非主的副本节点
- 滚动重启副本:逐个重启副本节点,每重启一个节点等待它重新加入集群、同步完成后再操作下一个,避免集群失去多数派
- 最终状态校验:重启完成后检查整个集群的角色、同步状态是否符合预期
核心功能代码说明
前置依赖
建议提前安装jq工具用于解析Patroni返回的JSON数据,Debian/Ubuntu可直接执行apt install jq安装,CentOS/RHEL可执行yum install jq安装。
关键命令片段
- 拉取集群节点列表,筛选所有副本节点
# 替换为你的Patroni任意节点的API地址,默认端口为8008 PATRONI_API="http://10.0.0.1:8008" # 过滤出所有副本节点的主机名 REPLICA_NODES=$(curl -s ${PATRONI_API}/cluster | jq -r '.members[] | select(.role == "replica") | .name')
- 单个副本节点重启(两种方式二选一)
# 方式1:通过Patroni API重启指定节点,替换为对应节点的API地址 curl -s -X POST http://${replica_ip}:8008/restart # 方式2:如果本地安装了patronictl,可直接调用命令重启 patronictl -c /etc/patroni/patroni.yml restart ${cluster_name} ${replica_node_name} --force
- 等待节点恢复逻辑
# 等待最多300秒,直到节点重新加入集群且同步状态正常 wait_second=0 while true; do role=$(curl -s ${PATRONI_API}/cluster | jq -r --arg node "${replica_node_name}" '.members[] | select(.name == $node) | .role') state=$(curl -s ${PATRONI_API}/cluster | jq -r --arg node "${replica_node_name}" '.members[] | select(.name == $node) | .state') if [ "${role}" == "replica" ] && [ "${state}" == "running" ]; then echo "节点${replica_node_name}重启完成,已正常同步" break fi if [ ${wait_second} -ge 300 ]; then echo "节点${replica_node_name}重启超时,请手动检查状态" exit 1 fi sleep 5 wait_second=$((wait_second+5)) done
完整脚本示例
#!/bin/bash set -euo pipefail # 配置项,根据你的集群实际情况修改 PATRONI_API="http://10.0.0.1:8008" CLUSTER_NAME="patroni-cluster" NEW_MASTER="$1" # 前置参数校验 if [ $# -ne 1 ]; then echo "用法:$0 <目标新主节点名称>" exit 1 fi # 步骤1:校验集群状态 echo "1/6 检查集群健康状态..." cluster_health=$(curl -s ${PATRONI_API}/health | jq -r '.state') if [ "${cluster_health}" != "running" ]; then echo "集群当前状态异常,无法执行switchover" exit 1 fi # 步骤2:执行switchover echo "2/6 执行主节点切换到${NEW_MASTER}..." # 这里替换为你已经掌握的switchover curl命令 curl -s -X POST ${PATRONI_API}/switchover -d "{\"leader\": \"$(curl -s ${PATRONI_API}/leader | jq -r '.name')\", \"candidate\": \"${NEW_MASTER}\"}" -H "Content-Type: application/json" # 步骤3:等待集群状态收敛 echo "3/6 等待集群状态稳定..." sleep 10 wait_cluster=0 while true; do current_leader=$(curl -s ${PATRONI_API}/leader | jq -r '.name') if [ "${current_leader}" == "${NEW_MASTER}" ]; then echo "主节点切换完成,当前主节点为${NEW_MASTER}" break fi if [ ${wait_cluster} -ge 120 ]; then echo "主节点切换超时,请手动检查集群状态" exit 1 fi sleep 5 wait_cluster=$((wait_cluster+5)) done # 步骤4:识别所有副本节点 echo "4/6 识别集群副本节点..." REPLICA_NODES=$(curl -s ${PATRONI_API}/cluster | jq -r '.members[] | select(.role == "replica") | .name') echo "当前待重启副本节点:${REPLICA_NODES}" # 步骤5:滚动重启副本节点 echo "5/6 开始滚动重启副本节点..." for replica in ${REPLICA_NODES}; do echo "正在重启副本节点${replica}..." # 替换为你实际使用的重启命令 curl -s -X POST http://${replica}:8008/restart # 等待节点恢复 wait_replica=0 while true; do state=$(curl -s ${PATRONI_API}/cluster | jq -r --arg node "${replica}" '.members[] | select(.name == $node) | .state') if [ "${state}" == "running" ]; then echo "节点${replica}重启完成,已正常加入集群" break fi if [ ${wait_replica} -ge 300 ]; then echo "节点${replica}重启超时,请手动检查" exit 1 fi sleep 5 wait_replica=$((wait_replica+5)) done done # 步骤6:最终校验 echo "6/6 校验集群最终状态..." curl -s ${PATRONI_API}/cluster | jq '.members[] | {name: .name, role: .role, state: .state, lag: .lag}' echo "Switchover及副本重启操作全部完成"
注意事项
- 脚本所有配置项需要根据你的集群实际IP、端口、集群名称调整,本地需要能访问所有Patroni节点的8008端口
- 首次执行前建议在测试集群逐行验证命令逻辑,确认符合预期再全量执行
- 如果你的Patroni开启了API认证,需要在curl命令中增加
-u 用户名:密码参数 - 滚动重启逻辑避免了同时重启多个副本的问题,保证集群始终有至少1个副本在线,不会影响集群可用性
内容的提问来源于stack exchange,提问作者ljunplugged
相关产品推荐
相关产品推荐

