首页 / 资讯中心 / 文章详情

Patroni 迁移与升级实战:将独立 PostgreSQL 转化为 Patroni 集群并完成大版本升级

Patroni 迁移与升级实战:将独立 PostgreSQL 转化为 Patroni 集群并完成大版本升级 ★ FEATURED ARTICLE
数据库高可用集群管理运维后端【免费下载链接】patroniA template for PostgreSQL High Availability with Etcd, Consul, ZooKeeper, or Kubernetes项目地址https://gitcode.com/gh_mirrors/pa/patroni点击查看免费下载本指南以 docs/existing_data.rst 为骨架系统讲解两条 Patroni 生命周期中最关键的两条运维路径一是将一台或多台已有 PostgreSQL 独立实例平滑纳入 Patroni 管理二是对已由 Patroni 管理的集群执行 PostgreSQL 大版本major version升级。读完本文你将掌握完整的用户/槽位准备、配置生成、启动权移交、槽位清理操作以及基于pg_upgrade的升级步骤与常见故障排查方法并了解这些操作背后的源码级实现逻辑对应仓库源码与测试位置。说明本文面向的仓库为当前 Patroni 源码仓库根目录下 patroni/ 为实现、docs/ 为文档、tests/ 为测试。文中涉及的命令与配置均以当前仓库内容为准。一、迁移方案总览从独立 PostgreSQL 到 Patroni 集群将一台独立的 PostgreSQL 实例转换为 Patroni 管理的集群核心思路是让 Patroni 接管一个已经存在的数据目录PGDATAPatroni 启动时会自动检测到 PostgreSQL 已在运行从而不再执行 bootstrap初始化新集群而是进入监控既有实例模式随后逐步引导出主备复制拓扑。原文档给出了明确的适用前提这些前提直接影响操作安全性现有集群的所有节点当前都处于运行状态迁移过程中不打算修改 PostgreSQL 配置所有 GUC 调整应在迁移完成后再进行。整体流程分为四步创建 Patroni 所需的数据库账号superuser / replication / rewind在所有节点上逐一改造禁用 systemd 单元、生成 Patroni 配置、启动 Patroni先主节点后备节点通过patronictl restart将 PostgreSQL 的启动流程移交给 Patroni先备后主主节点放在维护窗口内若第 2 步为主节点配置了永久槽位在 Patroni 自建槽位追平原槽位后用patronictl edit-config移除临时槽位配置。如果不涉及既有实例、希望直接部署一个全新的 Patroni 集群请参见仓库中的 Running and ConfiguringPatroni 配置与运行指南。二、步骤 1创建 Patroni 所需的三个数据库账号原文档强调创建账号的方法与 Patroni 配置文档 中postgresql.authentication一节所述一致。以下是可直接在任意节点通常为主节点上执行的示例 SQL请按实际环境替换其中的用户名与密码-- Patroni superuser -- Replace PATRONI_SUPERUSER_USERNAME and PATRONI_SUPERUSER_PASSWORD accordingly CREATE USER PATRONI_SUPERUSER_USERNAME WITH SUPERUSER ENCRYPTED PASSWORD PATRONI_SUPERUSER_PASSWORD; -- Patroni replication user -- Replace PATRONI_REPLICATION_USERNAME and PATRONI_REPLICATION_PASSWORD accordingly CREATE USER PATRONI_REPLICATION_USERNAME WITH REPLICATION ENCRYPTED PASSWORD PATRONI_REPLICATION_PASSWORD; -- Patroni rewind user, if you intend to enable use_pg_rewind in your Patroni configuration -- Replace PATRONI_REWIND_USERNAME and PATRONI_REWIND_PASSWORD accordingly CREATE USER PATRONI_REWIND_USERNAME WITH ENCRYPTED PASSWORD PATRONI_REWIND_PASSWORD; GRANT EXECUTE ON function pg_catalog.pg_ls_dir(text, boolean, boolean) TO PATRONI_REWIND_USERNAME; GRANT EXECUTE ON function pg_catalog.pg_stat_file(text, boolean) TO PATRONI_REWIND_USERNAME; GRANT EXECUTE ON function pg_catalog.pg_read_binary_file(text) TO PATRONI_REWIND_USERNAME; GRANT EXECUTE ON function pg_catalog.pg_read_binary_file(text, bigint, bigint, boolean) TO PATRONI_REWIND_USERNAME;三个账号的职责划分superuserPatroni 用于连接并管理实例执行 DDL、读取状态、触发 promote/restart 等对应配置中的postgresql.authentication.superuserreplication用于主备之间的流复制连接对应postgresql.authentication.replication配置中必须包含一条类似host replication replicator 127.0.0.1/32 md5的pg_hba条目rewind仅在启用use_pg_rewind时需要。GRANT EXECUTE的四个函数权限用于让该账号通过 PostgreSQL 连接执行pg_rewind所需的数据文件读取操作。从源码看use_pg_rewind默认关闭见 docs/dynamic_configuration.rst 中 use_pg_rewind: whether or not to use pg_rewind. Defaults to false且 patroni/postgresql/rewind.py 中的可执行性检查pg_rewind_is_possible见 rewind.py#L59-L98会依次校验配置开关已开启、pg_rewind可执行、以及集群必须以data page checksumsinitdb --data-checksums初始化或开启wal_log_hintson否则pg_rewind不会生效。因此若现有集群未满足上述任一条件rewind 账号可以跳过创建也不必在配置中开启use_pg_rewind。三、步骤 2逐节点改造先主后备原文档明确要求在一个节点上完成全部子步骤后再处理下一个节点且顺序为先主节点、后各备节点。对每个节点的具体操作如下。3.1 禁用 systemd 管理的 PostgreSQL 单元如果 PostgreSQL 由 systemd 管理需先禁用其单元。原因在于 Patroni 接管后由它自己负责 PostgreSQL 守护进程的启动与停止若 systemd 单元仍处于启用状态两者会互相冲突例如 Patroni 试图监听端口时 systemd 也拉起进程或 Patroni 停库后 systemd 又将其拉起。典型命令为systemctl disable postgresql3.2 生成 Patroni YAML 配置原文档推荐使用 Patroni 自带的配置生成与校验工具来创建patroni.yml这些工具的完整说明位于 docs/patroni_configuration.rst 的 Configuration generation and validation 一节主要包括三个子命令# 1. 生成一份通用示例配置未提供文件路径时输出到 stdout patroni --generate-sample-config [configfile] # 2. 基于本地正在运行的 PostgreSQL 实例生成配置迁移场景首选 # 优先使用 --dsn否则读取 libpq 环境变量未提供密码时会交互式提示输入 patroni --generate-config [--dsn DSN] [configfile] # 3. 校验已有配置并输出失败项--ignore-listen-port 可忽略监听端口被占用 patroni --validate-config [configfile] [--ignore-listen-port | -i]其中--generate-config特别适合迁移场景它会连接本地正在运行的实例将其实时 GUC 值映射为 Patroni 配置映射规则见 docs/patroni_configuration.rst包括scope←cluster_nameGUCpostgresql.listen←listen_addresses与portGUCpostgresql.datadir←data_directoryGUCpostgresql.parameters←archive_command、restore_command、hba_file、config_file等 GUC其余 GUC 归入bootstrap.dcspostgresql.pg_hba、pg_ident← 实例现有hba_file、ident_file内容postgresql.authentication.superuser← 本次实例连接所使用的凭据postgresql.bin_dir← 从运行实例探测到的二进制路径。生成的配置可以直接作为后续patroni --validate-config的输入避免手工编写带来的拼写与缩进错误。3.3 主节点特例use_slots与永久槽位原文档专门为主节点给出了一条重要注意事项如果集群成员之间正使用复制槽replication slots进行复制建议开启use_slots并把现有复制槽通过slots配置项声明为永久槽位permanent slots。注意开启use_slots后Patroni 会自动为成员间复制创建槽位并删除它不认识的槽位。此处使用永久槽位的目的是让迁移期间原有槽位得以保留。相关参数定义见 docs/dynamic_configuration.rstpostgresql.use_slots是否使用复制槽PostgreSQL 9.4 默认trueslots定义永久复制槽。永久槽在 switchover/failover 期间被保留不存在的永久槽会被 Patroni 自动创建PostgreSQL 11 及以上版本中永久物理槽在所有节点上维护并每隔loop_wait秒推进一次位置逻辑槽则从主节点复制到备节点通过libpq使用 rewind 或 superuser 凭据。定义永久槽要求use_slots: truemember_slots_ttl备节点下线后其物理槽的保留时间默认30min设为0恢复旧行为成员 key 从 DCS 过期即立刻删除槽位该特性仅 PostgreSQL 11 生效。slots是哈希表条目示例slots: permanent_logical_slot_name: type: logical database: my_db plugin: test_decoding permanent_physical_slot_name: type: physical这条删除不认识的槽位的行为可以从源码得到直接印证在 patroni/postgresql/slots.py 的SlotsHandler.sync_replication_slots()见 slots.py#L666-L720中每个 HA 循环都会调用load_replication_slots()读取本机pg_replication_slots随后_drop_incorrect_slots()见 slots.py#L465-L506会把不在期望列表成员槽 永久槽中的槽位逐个pg_drop_replication_slot删除并记录日志Trying to drop unknown replication slot name。因此迁移时把现有槽位显式列入slots是防止它们被误删的关键。同时可留意ignore_slots配置若某些槽位由外部工具管理、不希望 Patroni 触碰可用ignore_slots数组按name/type/database/plugin匹配豁免详见 docs/dynamic_configuration.rst。3.4 启动 Patroni启动 Patronisystemd 方式为systemctl start patroni。Patroni 启动后会检测到 PostgreSQL 已在运行自动跳过 bootstrap开始监控该实例并将其状态注册进 DCS。四、步骤 3通过patronictl restart移交启动控制权原文档指出为了让 Patroni 真正接管 PostgreSQL 的启动流程需要通过重启让每个成员以 Patroni 控制的方式重新拉起命令为patronictl restart cluster-name member-name为了把停机影响降到最低原文档建议把该步骤拆成两段立即重启所有备节点对业务无影响将主节点重启安排到维护窗口内可结合patronictl restart的--scheduled参数指定具体时间戳见下。patronictl restart的完整参数定义见 docs/patronictl.rst常用选项包括--role/-r按角色选择节点如leader、primary、replica、standby-leader、any--any在匹配的节点中随机重启一个--pending仅重启标记为 Pending restart 的成员例如动态配置中修改了仅重启生效的参数后--timeout重启超时后中止若主节点出现问题则故障转移到副本--scheduled把重启调度到指定时间戳格式建议带时区now表示立即执行。对应的 CLI 实现位于 patroni/ctl.py 的restart()见 ctl.py#L1112。五、步骤 4比对restart_lsn并移除临时永久槽位如果在第 1.2 步主节点配置了永久槽位则在迁移完成、Patroni 自建槽位追平原槽位之后应当把这些临时槽位从slots配置中移除从而允许 Patroni 在它们不再被需要时将其删除。判断已追平的标准是Patroni 为某成员创建的槽位的restart_lsn≥ 原集群中对应槽位的restart_lsn。原文档给出了对比查询示例-- Assume original_slot_for_member_x is the name of the slot in your original -- cluster for replicating changes to member X, and slot_for_member_x is the -- slot created by Patroni for that purpose. You need restart_lsn of -- slot_for_member_x to be restart_lsn of original_slot_for_member_x SELECT slot_name, restart_lsn FROM pg_replication_slots WHERE slot_name IN ( original_slot_for_member_x, slot_for_member_x )确认追平后通过patronictl edit-config移除槽位定义patronictl edit-config cluster-name --set slotsnullpatronictl edit-config的参数见 docs/patronictl.rst包括-s/--set CONFIG VALUE动态配置路径用.连接层级VALUE 为null时删除该项、-p/--pg设置动态 PostgreSQL 参数、-q/--quiet跳过 diff 展示等其实现位于 patroni/ctl.py 的edit_config()见 ctl.py#L2187。从slots移除后结合前述_drop_incorrect_slots()的逻辑原槽位会随 HA 循环被自动清理。六、PostgreSQL 大版本升级推荐的唯一路径原文档明确指出目前指当前仓库文档所描述的状态大版本升级唯一可行的方式是结合pg_upgrade的手动流程。完整步骤如下假设已升级各节点上的 PostgreSQL 二进制停止 Patroni例如systemctl stop patroni保证升级期间无人干扰实例生命周期在主节点上升级 PostgreSQL 二进制并执行pg_upgradepg_upgrade官方文档见 PostgreSQL 手册 pg_upgrade 一节注意pg_upgrade会运行initdb从而生成一个全新的 PostgreSQL system identifier更新patroni.yml使其与新版本、新配置保持一致可复用patroni --generate-config或手工核对postgresql.listen、postgresql.parameters等项从 DCS 中移除initializekey或干脆清空整个集群在 DCS 中的状态——后一种方式可通过patronictl remove cluster-name完成。这一步之所以必要是因为新的 system identifier 意味着这已经是一个新集群旧标识会与 Patroni 的集群初始化机制冲突。关于initializekey 的机制在 patroni/dcs/init.py 中AbstractDCS定义了initialize常量见 dcs/init.py#L1535initialize()方法见 dcs/init.py#L2091用于在 DCS 中原子创建该 key 并写入 system identifier是集群初始化的竞速令牌对应的delete_initialize()见 dcs/init.py#L2130则将其移除。patronictl remove的交互式确认参数-f/--format控制成员列表展示格式pretty/tsv/json/yaml见 docs/patronictl.rst与示例输出见 patronictl.rst#L1481-L1526实现位于 patroni/ctl.py#L957。如果第 4 步清空了整个集群状态建议把旧数据目录中的patroni.dynamic.json复制到新数据目录这样可以保留之前设置的部分 PostgreSQL 参数关于该文件Patroni 会在每次动态配置变化时把 DCS 配置 dump 到$PGDATA/patroni.dynamic.json且仅允许 leader 在 DCS 中相关配置缺失或非法时从磁盘恢复见 docs/patroni_configuration.rst在主节点上启动 Patroni在备节点上升级二进制、更新patroni.yml并清空wipe备节点的data_dir启动备节点上的 Patroni等待复制重新追平。关于备节点的两种处理方式原文档特别提醒PostgreSQL官方不支持在备节点上运行pg_upgrade。如果确实清楚自己在做什么可以尝试 PostgreSQL 文档中描述的rsync 方式即从已升级的主节点将新数据目录 rsync 到备节点以替代清空data_dir但最稳妥的方式始终是让 Patroni 重新复制数据——即清空备节点data_dir后由 Patroni 自动完成全量重建与流复制。对于追求可预期性的生产环境优先选择后者。七、常见问题排查FAQ原文档收录了两个高频问题均与迁移/重启场景直接相关问题 1Patroni 启动时报错无法绑定 PostgreSQL 端口。排查要点核对postgresql.conf中的listen_addresses与port核对patroni.yml中的postgresql.listen该参数同时驱动listen_addresses与port两个 GUC见 docs/patroni_configuration.rst不要忘记pg_hba.conf中应允许相应来源的访问。问题 2请求 Patroni 重启节点后PostgreSQL 报错could not open configuration file /etc/postgresql/10/main/pg_hba.conf: No such file or directory。原因分析取决于你如何管理 PostgreSQL 配置如果你设置了postgresql.config_dirPatroni仅在 bootstrap 新集群时才会根据 bootstrap 配置节 中的pg_hba设置生成pg_hba.conf迁移场景中 PGDATA 非空bootstrap 不会发生因此该文件必须预先存在否则重启后 PostgreSQL 找不到它。八、小结把既有 PostgreSQL 纳入 Patroni 的关键在于先准备好账号与槽位、再逐节点接管、最后移交启动权并清理临时槽位而大版本升级则遵循停止 →pg_upgrade→ 清理 DCS 状态 → 重建备节点的固定流程。这两条路径分别由 patroni/postgresql/slots.py槽位生命周期管理、patroni/dcs/init.pyinitialize机制与 patroni/ctl.pyrestart/edit-config/remove命令在底层支撑。动手迁移前建议先在小规模环境用patroni --generate-config与patroni --validate-config验证配置再按本指南步骤推进相关测试用例可参考 tests/test_slots.py、tests/test_ctl.py 与 tests/test_rewind.py以便更深入理解各步骤的预期行为。赞分享数据库高可用集群管理运维后端【免费下载链接】patroniA template for PostgreSQL High Availability with Etcd, Consul, ZooKeeper, or Kubernetes项目地址https://gitcode.com/gh_mirrors/pa/patroni点击查看免费下载相关推荐Zulip 如何独立升级 PostgreSQL 版本并做升级前备份Zulip 如何独立升级 PostgreSQL 版本并做升级前备份 在生产环境中PostgreSQL 的主版本是独立于 Zulip 服务器版本升级的并且与宿即时通讯后端前端WebSocket深度解析CLIP文本编码器3大技术突破实战指南深度解析CLIP文本编码器3大技术突破实战指南 CLIPContrastive Language Image Pretraining作为跨模态AI领域的里人工智能基础模型大模型多模态计算机视觉5个必知的Patroni版本升级实战技巧轻松实现PostgreSQL高可用升级5个必知的Patroni版本升级实战技巧轻松实现PostgreSQL高可用升级 Patroni是一个用于PostgreSQL高可用管理的强大工具支持Etcd数据库高可用集群管理运维后端上一篇如何在已有项目中安装 React Email 依赖并运行第一个邮件模板预览下一篇Busboy开源项目安装与使用指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
阅读完成 · 觉得有帮助?
咨询建站