
CloudNativePG PostgreSQL 大版本升级完全指南从 Minor 滚动更新到离线 In-Place 就地升级【免费下载链接】cloudnative-pgThe most popular Kubernetes Operator for PostgreSQL.项目地址: https://gitcode.com/GitHub_Trending/cl/cloudnative-pg本文以 CloudNativePG 操作符为背景系统讲解 PostgreSQL 版本升级的两大路径小版本minor升级的滚动更新机制以及大版本major升级的三种策略并重点深入剖析由操作符自动编排的离线就地offline in-place升级——包括pg_upgrade --link的底层执行流程、Job 编排、扩展extensions处理、update_extensions.sql脚本、备份与 WAL 归档的跨版本边界问题以及完整的可运行示例。读完本文你将掌握在 Kubernetes 上安全、可回滚地完成 PostgreSQL 大版本升级的完整实战方案。升级分类总览PostgreSQL 的升级工作可分为两大类二者在兼容性、停机方式和操作复杂度上完全不同小版本升级Minor version upgrades例如从 18.0 升级到 18.1属于同一大版本内的补丁更新通常通过滚动更新即可完成。大版本升级Major version upgrades例如从 16.x 升级到 18.0会改变数据内部存储格式需要结构化的升级流程。小版本升级滚动更新PostgreSQL 版本号遵循major.minor格式。以版本 18.1 为例18是大版本号1是小版本号。同一大版本内的所有小版本之间完全兼容——它们只包含缺陷修复bug fixes和安全更新不会改变内部存储格式。小版本升级操作步骤在 CloudNativePG 中升级小版本非常简单只需更新集群定义中的 PostgreSQL 容器镜像引用即可既可以直接修改.spec.imageName也可以通过 镜像目录image catalog 管理镜像版本变化。操作符检测到镜像变化后会触发集群的滚动更新一个接一个地替换实例从副本replicas开始所有副本更新完成后对主实例primary执行 switchover 或重启完成整个流程。整个过程中集群始终保持可用应用几乎无感知。这也是小版本升级与大版本升级在体验上的本质区别。大版本升级三种策略与权衡PostgreSQL 大版本发布会改变数据内部存储格式因此必须采用结构化的升级流程。CloudNativePG 支持三种大版本升级方法方法部署模式在线/离线核心工具逻辑导出/导入Logical dump/restoreBlue/green离线pg_dump/pg_restore详见数据库导入原生逻辑复制Native logical replicationBlue/green在线逻辑复制槽详见逻辑复制在线迁移与大版本升级示例物理升级Physical withpg_upgradeIn-place离线pg_upgrade --link即本文后续讲解的离线就地大版本升级三种方法在停机时长、复杂度、数据量处理能力上各有取舍逻辑导出/导入灵活但耗时与数据量成正比离线进行原生逻辑复制可在旧库运行期间完成大部分数据迁移实现近乎零停机的在线升级但需要预先搭建逻辑复制拓扑物理pg_upgrade速度最快、最适合大数据量但集群必须整体停机采用就地替换磁盘数据的方式。最佳方案取决于你的升级策略与运维约束。重要提示强烈建议在生产环境升级前先在受控的测试环境中完整演练上述所有候选方法。离线就地大版本升级Offline In-Place当集群以声明式方式请求一个PostgreSQL 大版本号更高的 operand 容器镜像时CloudNativePG 会自动执行离线就地大版本升级。触发升级的两种方式你可以通过以下任一种方式触发就地大版本升级通过.spec.imageName更新镜像标签中的大版本号如16→18使用镜像目录image catalog 来管理版本变更。关于受支持镜像标签的详细要求请参阅镜像标签要求。前置约束与注意事项1. 操作系统发行版必须一致大版本升级只支持基于同一操作系统发行版的镜像。例如如果旧版本使用的是bullseye镜像则不能升级到bookworm镜像。2. PostgreSQL 17.0–17.5 的已知缺陷PostgreSQL 17.0 至 17.5 存在一个缺陷当max_slot_wal_keep_size参数被设置为除-1之外的任何值时大版本升级会失败并报出与复制槽replication slot配置相关的错误。该问题已在 PostgreSQL 17.6 及 18 或更高版本中修复。如果你正在使用 PostgreSQL 17.0–17.5请先升级到至少 PostgreSQL 17.6 再执行大版本升级或者临时将max_slot_wal_keep_size设置为-1。这一约束在源码中也有对应处理internal/cmd/manager/instance/upgrade/execute/cmd.go中针对 PostgreSQL 17.6 之前的版本专门绕过了该参数确保pg_upgrade能正常执行。3. 扩展extensions兼容性由用户负责CloudNativePG 不负责 PostgreSQL 扩展的兼容性。你必须确保源镜像中的扩展与目标镜像兼容且升级路径受支持并提前充分测试升级过程。操作符的数据库扩展管理功能可以帮助你以声明式方式管理扩展升级。4. 就地升级具有固有风险务必先备份就地升级是一种特殊操作存在固有风险。强烈建议在发起升级前对集群进行完整备份。关于pg_upgrade的详细官方指南可参考 PostgreSQL 官方文档。升级流程Upgrade ProcessCloudNativePG 的就地大版本升级由控制器驱动。在源码层面该逻辑位于 pkg/reconciler/majorupgrade/reconciler.go并由 internal/controller/cluster_controller.go 在reconcileResources中、且早于 running-jobs 守护检查调用因为升级 Job 的生命周期由它全权管理。整体流程如下关闭所有集群 Pod确保数据一致性。对应源码中deleteAllPodsInMajorUpgradePreparation会删除全部实例 Pod 与残留 Job等待删除完成后继续。记录旧版本信息将之前的 PostgreSQL 版本和镜像记录到集群状态.status.pgDataImageInfo中。源码中同时使用乐观锁将集群 phase 置为PhaseMajorUpgrade并将目标镜像信息写入Status.TargetPGDataImageInfo。发起新的升级 Job该 Job 负责校验确认镜像中的二进制文件与数据文件与大版本升级请求相符否则拒绝执行准备新目录为新的PGDATA、WAL 文件如适用和表空间创建新目录执行升级使用pg_upgrade --link完成升级替换目录升级成功后用升级后的新目录替换原目录。升级 Job 的内部结构从 pkg/reconciler/majorupgrade/job.go 的源码可以看出升级 Job 的命名与结构相当讲究Job 名称以主实例 Pod 名称 -major-upgrade后缀命名并通过utils.SetInstanceRole(..., primary)标记为主角色直接挂载主实例的持久卷组。init 容器prepare使用旧版本镜像cluster.Status.PGDataImageInfo.Image运行/controller/manager instance upgrade prepare /controller/old把旧版本二进制目录记录下来供后续执行阶段使用——这是pg_upgrade同时需要新旧两套二进制的前提。主容器运行/controller/manager instance upgrade execute /controller/old/bindir.txt即internal/cmd/manager/instance/upgrade/execute子命令实际调用pg_upgrade执行升级。BackoffLimit 0失败的pg_upgrade重试也不会成功因此 Job 失败即终止不自动重试。升级期间的停机声明警告升级期间整个 PostgreSQL 集群包括副本对应用不可用。在继续之前请确保你的系统能够容忍这段时间的停机。升级后的处理Post-Upgrade Actions升级成功时的动作如果升级成功CloudNativePG 会销毁副本的 PVC如可用源码majorVersionUpgradeHandleCompletion会遍历所有 PVC删除除主实例之外的所有 PVC按需扩容副本随后按 spec 中声明的instances数量从升级后的主实例重新克隆副本。同时源码还会在升级完成后重置Status.TimelineID为 1与pg_upgrade的行为一致并清理升级 Job。警告重新克隆副本可能非常耗时尤其是对于超大数据库。请预留足够的时间。升级完成后尽快做一次新的基础备份base backup。升级前的备份与 WAL 文件不能用于跨大版本边界的基于时间点恢复PITR详见下文备份与 WAL 归档考虑。警告pg_upgrade不会迁移优化器统计信息。升级后建议在你的数据库上运行ANALYZE以更新统计信息。升级失败时的回滚如果升级失败只需将集群配置中的镜像回退到之前的大版本。操作符会检测到回滚并自动删除失败的升级 Job让集群以原版本重新启动。重要提示这一流程保护现有数据库免受数据丢失——因为升级过程中不修改任何数据。如果升级失败通常无需从备份做完整恢复即可回滚。请密切监控整个过程并在需要时采取纠正措施。源码中对应handleRollbackIfNeeded只要用户回退的镜像大版本不再高于.status.pgDataImageInfo.majorVersion等于也算回滚即使升级 Job 正在运行也会被终止操作符就会删除升级 Job并重置Status.Image为旧镜像、清除TargetPGDataImageInfo同时发出MajorUpgradeRollback事件。大版本升级期间的扩展处理Extensions当集群声明了镜像卷扩展image-volume extensions时升级 Job 会同时挂载源版本与目标版本的扩展镜像源版本扩展旧服务器启动时需要其已有的共享库因此必须保留目标版本扩展为新的 PostgreSQL 大版本构建pg_upgrade需要它们才能正确执行到新大版本的升级。具体挂载布局如下源版本扩展挂载在/extensions/name即稳态路径这样旧PGDATA中的dynamic_library_path和extension_control_path两个 GUC 保持原值不变。这确保了大版本升级失败时回退到旧大版本可以无缝进行。目标版本扩展仅在升级 Job 期间临时挂载在/new-extensions/name并为新大版本的PGDATA相应配置dynamic_library_path和extension_control_path。同时LD_LIBRARY_PATH和PATH会被扩展为同时包含两套路径使得任一版本的二进制与共享对象都可达。通过extensions[].env声明的环境变量遵循优先级与冲突解决规则。注意目标版本条目在源版本条目之后应用。当同一个变量在两者中都定义时目标版本的值优先生效。从源码看扩展的解析发生在创建 Job 之前resolveExtensionsForMajorVersion若集群使用imageCatalogRef则从镜像目录解析新大版本的扩展集合否则要求扩展在集群 spec 中完整声明。解析失败时集群进入PhaseImageCatalogError阶段且不会触碰任何 Pod。此外升级完成后使用 Job 启动时已解析并持久化在TargetPGDataImageInfo中的扩展集合而非重新查询目录以保证与pg_upgrade实际构建的新PGDATA一致。当pg_upgrade生成update_extensions.sql时当目标集群包含某些扩展且其default_version比pg_upgrade遗留安装的版本更新时pg_upgrade会在PGDATA内生成一个update_extensions.sql脚本。在该脚本执行之前pg_catalog中的 SQL 级扩展元数据与运行中服务器实际加载的共享库是不一致的。该脚本位于主实例 Pod 的PGDATA内。你可以使用数据库超级用户postgres在所有数据库中执行它来更新这些扩展PRIMARY$(kubectl get cluster name -o jsonpath{.status.currentPrimary}) SCRIPT/var/lib/postgresql/data/pgdata/update_extensions.sql kubectl exec -i $PRIMARY -- psql -f $SCRIPT注意上述脚本路径假设使用 CloudNativePG operand 镜像的默认PGDATA位置。当pg_upgrade生成该脚本时操作符也会在日志中记录解析后的实际路径如果您的 operand 镜像使用了不同的PGDATA请查看操作符日志获取准确路径。备份与 WAL 归档考虑Backup and WAL Archive Considerations执行大版本升级时pg_upgrade会创建一个带有新 System ID的全新数据库系统并将 PostgreSQL 时间线重置为 1。这对备份和 WAL 归档有直接影响时间线文件冲突新的时间线 1 文件可能会覆盖原集群的时间线 1 文件混合版本归档不加干预的话归档中将同时包含两个 PostgreSQL 版本的 WAL 文件和备份。警告跨大版本边界不支持基于时间点恢复PITR。你不能用升级前的备份恢复到升级后的某个时间点。升级后应尽快做新的基础备份为新大版本建立恢复基线。备份系统如何处理大版本升级取决于插件实现部分插件会自动管理升级期间的归档分离另一些则要求手动配置为大版本使用不同的归档路径。请查阅你的备份插件文档了解其在升级期间的具体行为。示例使用 Barman Cloud 插件手动分离归档路径Barman Cloud 插件在升级期间不会自动分离归档。为了保留升级前的备份并保持归档干净需要在触发升级时同时修改serverName参数。升级前PostgreSQL 16spec: imageName: ghcr.io/cloudnative-pg/postgresql:16-minimal-trixie plugins: - name: plugin-barman-cloud enabled: true parameters: destinationPath: s3://my-bucket/ serverName: cluster-example-pg16触发升级时同时修改imageName与serverNamespec: imageName: ghcr.io/cloudnative-pg/postgresql:18-minimal-trixie plugins: - name: plugin-barman-cloud enabled: true parameters: destinationPath: s3://my-bucket/ serverName: cluster-example-pg18采用该配置后旧的cluster-example-pg16归档完整保留可用于升级前恢复升级后的集群则写入cluster-example-pg18互不干扰。注意已弃用的内置barmanObjectStore实现同样需要在升级期间手动修改serverName来分离归档。完整示例执行一次大版本升级以一个运行版本 16 的 PostgreSQL 集群为例apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: cluster-example spec: imageName: ghcr.io/cloudnative-pg/postgresql:16-minimal-trixie instances: 3 storage: size: 1Gi第 1 步确认当前版本使用以下命令查看当前 PostgreSQL 版本kubectl cnpg psql cluster-example -- -qAt -c SELECT version()输出类似PostgreSQL 16.x ...第 2 步修改imageName触发升级将大版本标签从16改为18apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: cluster-example spec: imageName: ghcr.io/cloudnative-pg/postgresql:18-minimal-trixie instances: 3 storage: size: 1Gi第 3 步观察升级过程提交修改后操作符会自动执行以下步骤集群停机Cluster shutdown——终止所有集群 Pod确保升级时数据一致升级 Job 执行Upgrade job execution——创建名为主实例 Pod -major-upgrade后缀的 Job在主实例的持久卷组上运行pg_upgrade升级后步骤Post-upgrade steps删除副本cluster-example-2与cluster-example-3的 PVC 组重启主实例 Pod从升级后的主实例重新克隆两个新副本cluster-example-2与cluster-example-3。提示与源码对应pkg/reconciler/majorupgrade/reconciler_test.go 与 job_test.go 覆盖了 Job 创建、副本 PVC 删除、回滚清理等关键路径的单元测试可作为理解流程行为的补充参考。第 4 步验证新版本升级完成后再次运行同一命令kubectl cnpg psql cluster-example -- -qAt -c SELECT version()输出应类似PostgreSQL 18.x ...第 5 步更新统计信息由于pg_upgrade不迁移优化器统计信息请在app数据库上运行ANALYZEkubectl cnpg psql cluster-example -- app -c ANALYZE同时如前所述尽快执行一次新的基础备份为 18 大版本建立 PITR 恢复基线。小结CloudNativePG 将 PostgreSQL 升级提炼为一条清晰的分层路径小版本升级通过镜像更新 滚动更新零停机完成大版本升级则根据在线/离线需求在逻辑导入导出、逻辑复制和物理pg_upgrade之间选择。其中离线就地升级由操作符全自动编排——从 Pod 停机、旧版本信息记录.status.pgDataImageInfo、pg_upgrade --linkJob 执行、副本 PVC 重建到失败时的自动回滚全程声明式驱动且对数据零修改。掌握这一机制配合扩展兼容性检查、update_extensions.sql执行、归档路径分离和升级后新基线备份即可在生产环境中可靠地推进 PostgreSQL 大版本演进。延伸阅读滚动更新镜像目录Image Catalog容器镜像与镜像标签要求数据库导入逻辑 dump/restore逻辑复制与大版本在线升级数据库扩展管理镜像卷扩展Image Volume Extensions【免费下载链接】cloudnative-pgThe most popular Kubernetes Operator for PostgreSQL.项目地址: https://gitcode.com/GitHub_Trending/cl/cloudnative-pg创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考