十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

CloudNativePG 数据库导入完全指南:microservice 与 monolith 两种逻辑备份迁移方案

CloudNativePG 数据库导入完全指南:microservice 与 monolith 两种逻辑备份迁移方案 CloudNativePG 数据库导入完全指南microservice 与 monolith 两种逻辑备份迁移方案【免费下载链接】cloudnative-pgThe most popular Kubernetes Operator for PostgreSQL.项目地址: https://gitcode.com/GitHub_Trending/cl/cloudnative-pg本指南讲解如何在 CloudNativePG 中通过initdb.import将现有 PostgreSQL 实例中的一个或多个数据库以在线逻辑备份的方式导入到全新创建的 Kubernetes 集群中。它既适用于把 Kubernetes 内外的存量实例迁入 CloudNativePG也适用于将任意旧版本 PostgreSQL 数据库导入到同版本或更新版本的目标集群从而实现大版本升级major upgrade。读完本文你将掌握microservice与monolith两种导入类型的完整配置方法、底层执行流程、性能优化手段以及自定义pg_dump/pg_restore行为与基于逻辑复制的在线导入方案。导入机制概述基于快照的在线逻辑备份CloudNativePG 的数据库导入功能建立在 PostgreSQL 原生能力之上通过pg_dump经由网络连接源主机导出数据再用pg_restore导入目标集群。得益于 PostgreSQL 内置的多版本并发控制MVCC与快照机制系统能够在完全不中断写入活动的前提下通过并发方式在网络上取得一致性的数据备份。这里有一个必须理解的概念整个导入操作针对的是源数据库的一致快照consistent snapshot。也就是说备份开始之后、导入完成之前源数据库中发生的任何写入都不会出现在目标集群中。这正是官方文档将其称为offline import或offline major upgrade的原因——在最终写入Cluster资源之前建议先停止对源数据库的写操作。逻辑备份同时也是 PostgreSQL 执行大版本升级时最常用、最灵活也最可靠的技术手段。因此本文的指令同时适用于两类场景从一个现有 PostgreSQL 实例即使不在 Kubernetes 中导入一个或多个数据库从任意 PostgreSQL 版本导入到同版本或更新版本完成 PostgreSQL 的大版本升级例如从 14.x 升级到 18.x。⚠️警告执行大版本升级时你需要自行确保应用程序与新版本兼容并且数据库内对象包括扩展的升级路径是可行的。ℹ️重要提示由于导入基于快照建议在最终执行导入前停止源端的写入操作否则快照启动后源库的新变更不会进入目标集群。工作原理从initdb引导到逻辑导入从概念上讲导入操作要求你从零创建一个新集群目标集群 destination cluster使用initdb引导方式并填写initdb.import子段以从现有 PostgreSQL 集群源集群 source cluster导入对象。按照 PostgreSQL 的官方建议目标集群的 PostgreSQL 主版本应当大于或等于源集群的主版本。CloudNativePG 提供了两种从源集群向目标集群导入对象的方式microservice 方式微服务目标集群设计为只承载一个应用数据库由指定的应用用户所有这也是 CloudNativePG 项目推荐的做法monolith 方式单体目标集群设计为承载从源集群导入的多个数据库和不同用户。对应地第一种方式通过microservice类型实现第二种通过monolith类型实现。这两个值正是api/v1/cluster_types.go中SnapshotType枚举所允许的两个取值CRD 层面的校验kubebuilder:validation:Enummicroservice;monolith会保证非法值在提交时即被拒绝。⚠️警告你有责任确保目标集群能够以超级用户或具备足够权限执行pg_dump逻辑备份的用户访问源集群。相关权限要求请参考 PostgreSQL 官方关于pg_dump的文档。从源码看两种导入类型分别由pkg/management/postgres/logicalimport/microservice.go中的Microservice()函数和pkg/management/postgres/logicalimport/monolith.go中的Monolith()函数驱动它们都运行在目标集群的实例管理器instance manager中通过连接池pool.Pooler同时连接目标与源两端完成整个导入编排。配置字段总览initdb.import结构在深入两种类型之前先总览initdb.import下可用的全部字段。以下结构体定义位于api/v1/cluster_types.go字段类型必填说明source.externalClusterstring是指向包含待导入数据的现有 PostgreSQL 实例的外部集群名称typestring是导入类型枚举值microservice或monolithdatabasesstring[]是要导入的数据库列表monolith 支持用*通配全部数据库rolesstring[]否要导入的角色列表仅 monolith 支持monolith 支持用*通配postImportApplicationSQLstring[]否导入完成后以超级用户身份在应用数据库中执行的 SQL 列表仅 microservice 支持默认空schemaOnlybool否为 true 时只执行pg_restore的pre-data与post-data段跳过数据导入默认falsepgDumpExtraOptionsstring[]否追加传给pg_dump的自定义选项操作符不校验需谨慎pgRestoreExtraOptionsstring[]否追加传给pg_restore的通用自定义选项pgRestorePredataOptionsstring[]否pre-data阶段专属的pg_restore选项覆盖通用选项pgRestoreDataOptionsstring[]否data阶段专属的pg_restore选项覆盖通用选项pgRestorePostdataOptionsstring[]否post-data阶段专属的pg_restore选项覆盖通用选项其中source对应ImportSource结构体目前仅包含externalCluster一个字段用于关联到spec.externalClusters中定义的外部集群连接信息主机、用户名、数据库名、认证方式等。microservice类型一库一集群的微服务导入在微服务方式下你可以指定一个要从源集群导入到目标集群的数据库。从Microservice()的实现看整个操作按以下步骤执行initdb引导新集群在目标数据库的PGDATA中创建临时dumps目录对应createDumpsDirectory使用pg_dump -Fd导出initdb.import.databases中指定的数据库先删除目标空数据库中已安装的用户扩展dropExtensionsFromDatabase保证恢复过程能正确执行 dump 中的CREATE EXTENSION指令使用pg_restore --no-owner --no-privileges即文档所述的--no-acl --no-owner将数据导入initdb.database应用数据库并由initdb.owner用户所有清理 dump 文件目录可选地在应用数据库中执行postImportApplicationSQL定义的用户 SQL在专属连接上以search_path $user, public执行结束后恢复对导入的数据库执行ANALYZE VERBOSE。下图展示了含N个数据库的单个 PostgreSQL 集群被拆分为多个 CloudNativePG 集群、每个集群通过 microservice 导入其中一个源数据库的典型拓扑microservice 完整配置示例下面这个 YAML 创建一个名为cluster-microservice的 3 实例 PostgreSQL 集群使用操作符发布时支持的最新主版本从cluster-pg96集群导入angus数据库——注意示例刻意使用已不受支持的 PostgreSQL 9.6 作为源apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: cluster-microservice spec: instances: 3 bootstrap: initdb: import: type: microservice databases: - angus source: externalCluster: cluster-pg96 #postImportApplicationSQL: #- | # INSERT YOUR SQL QUERIES HERE storage: size: 1Gi externalClusters: - name: cluster-pg96 connectionParameters: # Use the correct IP or host name for the source database host: pg96.local user: postgres dbname: postgres password: name: cluster-pg96-superuser key: password⚠️关于旧版本导出的说明上述示例刻意使用社区已不再支持、CloudNativePG 也不再支持的 PostgreSQL 版本。源实例的数据导出使用的是目标集群内的pg_dump版本它必须是受支持的、且版本大于或等于源版本。根据项目经验这种导出方式对更旧、不受支持的 Postgres 版本同样有效可以借此把遗留数据迁移到 Kubernetes 内更好的系统中——这也是本节示例使用 9.6 的主要原因。如遇问题欢迎向项目反馈。使用microservice类型的注意事项需要一个指向现有 PostgreSQL 实例的externalCluster详见 bootstrap 文档中的 TheexternalClusterssection操作期间 Kubernetes 集群与externalCluster之间必须允许网络流量连接源数据库的用户必须具有运行pg_dump和读取角色信息的权限超级用户即可pg_dump -Fd的结果会临时存放在PGDATA卷的dumps文件夹中因此目标节点上需要有足够的临时空间同时容纳 dump 结果与恢复出的数据和索引导入完成后该文件夹由操作符自动删除见cleanDumpDirectoryinitdb.import.databases数组中只能指定一个数据库角色不会被导入因此不能在initdb.import.roles中指定。提示microservice 方式遵循 CloudNativePG 对目标集群的约定与默认值。如果你没有为目标集群设置initdb.database或initdb.owner两个参数都会默认为app。monolith类型多库多角色的单体导入在单体方式下你可以指定一组要从源集群导入到目标集群的角色和数据库。从Monolith()的实现看操作步骤如下initdb引导新集群导出并导入选定的角色cloneRoles随后处理角色继承关系cloneRoleInheritance使用pg_dump -Fd逐个导出initdb.import.databases中选定的数据库逐一创建选定的数据库并调用pg_restore导入数据同样按pre-data/data/post-data三个 section 分段执行对每个导入的数据库执行ANALYZE VERBOSE清理 dump 文件。下图展示了单个源集群的多个数据库导入到单一 CloudNativePG 集群、共享同一套实例的拓扑monolith 完整配置示例下面这个 YAML 创建名为cluster-monolith的 3 实例集群从cluster-pg96导入accountant与bank_user两个角色以及accounting、banking、resort三个数据库apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: cluster-monolith spec: instances: 3 bootstrap: initdb: import: type: monolith databases: - accounting - banking - resort roles: - accountant - bank_user source: externalCluster: cluster-pg96 storage: size: 1Gi externalClusters: - name: cluster-pg96 connectionParameters: # Use the correct IP or host name for the source database host: pg96.local user: postgres dbname: postgres sslmode: require password: name: cluster-pg96-superuser key: password使用monolith类型的注意事项需要一个指向现有 PostgreSQL 实例的externalCluster且操作期间网络必须可达连接源数据库的用户需具备运行pg_dump和检索角色信息的权限超级用户即可pg_dump -Fd结果临时存放于目标集群实例的PGDATA/dumps目录需保证足够磁盘空间导入完成后自动清理initdb.import.databases数组中至少要指定一个数据库导入的数据库所需的任何角色都必须列在initdb.import.roles中并遵守以下限制若存在以下角色则不会被导入postgres、streaming_replica、cnpg_pooler_pgbouncer对应源码中role.go的排除逻辑任何导入角色的SUPERUSER选项都会被移除通配符*可以作为databases和/或roles数组中的唯一元素用于导入该类型的全部对象匹配数据库时通配符会忽略postgres数据库、模板数据库以及不允许连接的数据库对应database.go中getDatabaseList的查询逻辑datallowconn AND NOT datistemplate AND datname ! postgres克隆完成后会对每个数据库执行ANALYZE VERBOSEpostImportApplicationSQL字段在 monolith 方式下不支持。提示数据库及其所有者会原样保留与源集群完全一致——导入过程中不会创建app数据库或用户。如果你的bootstrap.initdb中自定义了与导入对象不匹配的database和owner值实例管理器会额外创建一个指定名称的空应用数据库和所有者角色但不会改动已导入的数据库及其所有者。实战对比用 monolith 导入单个数据库你完全可以用monolith方式导入单个数据库。以源集群含数据库mydb、属主角色me为例apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: cluster-example spec: instances: 1 postgresql: pg_hba: - host all all all trust storage: size: 1Gi bootstrap: initdb: database: mydb owner: me通过microservice导入apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: cluster-example-microservice spec: instances: 1 storage: size: 1Gi bootstrap: initdb: import: type: microservice databases: - mydb source: externalCluster: cluster-example externalClusters: - name: cluster-example connectionParameters: host: cluster-example-rw dbname: postgres通过monolith导入apiVersion: postgresql.cnpg.io/v1 kind: Cluster metadata: name: cluster-example-monolith spec: instances: 1 storage: size: 1Gi bootstrap: initdb: import: type: monolith databases: - mydb roles: - me source: externalCluster: cluster-example externalClusters: - name: cluster-example connectionParameters: host: cluster-example-rw dbname: postgres两种情况下数据库内容都会被导入但结果有本质差异microservice 场景导入后的数据库名称与属主都变为app或bootstrap.initdb中database、owner字段配置的任意值monolith 场景数据库与属主保持源集群原样即mydb和me不会创建app数据库或用户。如果bootstrap.initdb中自定义的database/owner与源对象不匹配实例管理器会创建新的空应用数据库和属主角色但保留已导入的数据库与属主。导入优化速度优先的临时参数调优在逻辑导入期间CloudNativePG 会临时改写 PostgreSQL 配置以优先速度、暂时牺牲数据持久性。对应的实现位于pkg/management/postgres/configuration.go的configurePostgresForImport函数它会将以下 GUC 强制写入override.confGUC导入期间取值作用archive_modeoff关闭 WAL 归档避免归档拖慢写入fsyncoff跳过磁盘同步加快写入full_page_writesoff关闭整页写入减少 WAL 体积与 I/Omax_wal_senders0禁用 WAL 发送进程省去复制开销wal_levelminimal采用最低 WAL 级别进一步减少 WAL 开销在导入任务完成之前CloudNativePG 会恢复预期配置随后执行initdb --sync-only对应initdb.go中的initdbSyncOnly确保数据被永久写入磁盘。ℹ️重要提示如果需要 WAL 归档归档功能和 WAL 级别将在数据库导入流程结束后恢复同样副本replicas会在引导阶段完成后、实际集群资源启动时才进行克隆。此外你还可以在导入阶段做其他优化。虽然这超出了 CloudNativePG 的职责范围官方仍建议直接在Cluster配置中调整shared_buffers、max_wal_size、checkpoint_timeout等 GUC以减少检查点区域不必要的写入。自定义pg_dump与pg_restore行为你可以通过pgDumpExtraOptions和pgRestoreExtraOptions参数为pg_dump和pg_restore追加自定义选项这在提升性能或应对复杂导入/导出场景时尤其有用。例如启用并行任务可以显著加速数据传输bootstrap: initdb: import: type: microservice databases: - app source: externalCluster: cluster-example pgDumpExtraOptions: - --jobs2 pgRestoreExtraOptions: - --jobs2在源码中这些选项分别被传入exportDatabases拼装的pg_dump命令行和pg_restore命令行。值得注意的细节是pg_restore命令还固定携带-U postgres --no-owner --no-privileges --roleowner -d database --section section等选项见database.go导入前会把属主用户临时提升为超级用户、导入结束后再降回以保证 schema 对象按initdb.owner归属。分阶段Stage-Specific的pg_restore选项为了更精细地控制导入过程CloudNativePG 支持针对以下三个阶段分别设置pg_restore选项pre-data——例如 schema 定义data——例如表数据post-data——例如索引、约束和触发器。通过为每个阶段指定选项你可以针对恢复对象的性质优化并行度并应用定制标志。对应的底层实现是section.go中的buildPgRestoreSectionOptions当某个阶段配置了专属选项时优先使用forSection否则回退到通用的pgRestoreExtraOptions。bootstrap: initdb: import: type: microservice schemaOnly: false databases: - mynewdb source: externalCluster: sourcedb-external pgRestorePredataOptions: - --jobs1 pgRestoreDataOptions: - --jobs4 pgRestorePostdataOptions: - --jobs2上述示例中--jobs1应用于pre-data阶段以保持 schema 创建的次序--jobs4提高data阶段的并行度加速大型数据导入--jobs2在post-data阶段平衡性能与依赖关系处理。这些分阶段设置对大型数据库或资源敏感环境尤其有价值调整并发度可以显著提升性能。注意提供分阶段选项时它们会优先于通用的pgRestoreExtraOptions。⚠️警告pgDumpExtraOptions、pgRestoreExtraOptions以及所有分阶段恢复选项pgRestorePredataOptions、pgRestoreDataOptions、pgRestorePostdataOptions都会被不加校验地直接透传给底层 PostgreSQL 工具。某些标志可能与操作符的预期功能或设计相冲突请谨慎使用并在应用于生产环境前于安全、受控的环境中充分测试。schemaOnly模式只导入结构不导入数据Import结构体中的schemaOnly字段默认false控制是否跳过数据导入。从getSectionsToExecute的实现可见当schemaOnly: true时pg_dump与pg_restore只执行pre-data和post-data两个 section从而只迁移 schema表结构、索引、约束、触发器不迁移表数据——这一能力是与逻辑复制结合实现在线迁移见下文的基础。在线导入与升级基于逻辑复制的方案除了基于快照的离线导入逻辑复制还提供了一种强大的在线导入途径可以导入任何网络可达的 PostgreSQL 数据库方法如下导入引导 Schema-Only 选项在复制开始前先在目标数据库初始化 schemaSubscription资源设置持续复制以同步数据变更。具体来说先用schemaOnly: true的initdb.import完成结构导入再创建 CloudNativePG 的Subscription自定义资源对应 api/v1/subscription_types.go建立发布/订阅关系将源库的存量与增量数据持续同步到目标库从而实现近零停机的迁移。这一技术同样可以用于执行最小停机时间的 PostgreSQL 大版本升级非常适合无缝迁移和系统升级场景。完整的限制说明与最佳实践请参阅文档中的 Logical Replication逻辑复制 章节以及仓库内的示例清单 cluster-example-logical-destination.yaml。仓库中的配套资源以下仓库资源可帮助你进一步验证与实践本指南的内容API 类型定义Import结构体 与ImportSource以及initdb引导方式 的完整文档核心实现microservice.go、monolith.go、database.go、role.go、section.go与constants.go优化与收尾逻辑configurePostgresForImport与initdbSyncOnly测试用例database_test.go、role_test.go、section_test.go完整示例cluster-import-snapshot-basicauth.yaml、cluster-import-snapshot-tls.yaml 与 cluster-import-schema-only-basicauth.yaml以及 samples 索引CRD 定义postgresql.cnpg.io_clusters.yaml。总结与选型建议归纳本指南的核心决策点离线 vs 在线默认的initdb.import基于一致快照属离线迁移简单可靠但需停写若追求近零停机用schemaOnly: true配合Subscription逻辑复制实现在线迁移microservice vs monolith遵循 CloudNativePG 微服务惯例、单个应用数据库选microservice数据库与属主收敛为app或自定义值需要保留源库多库多角色原样布局选monolith支持roles与*通配但禁止postImportApplicationSQL性能调优操作符会自动在导入期间关闭fsync/full_page_writes/archive_mode等并恢复后执行initdb --sync-only你还可以通过pgDumpExtraOptions、pgRestoreExtraOptions及pgRestore{Pre,}Data{Post}Options精细化控制并发但这些选项不被校验务必先在测试环境验证版本兼容目标集群的pg_dump版本应不低于源版本官方经验表明对已停止支持的旧版本如 9.6也能完成导出迁移这为遗留系统迁移进 Kubernetes 提供了可行路径。【免费下载链接】cloudnative-pgThe most popular Kubernetes Operator for PostgreSQL.项目地址: https://gitcode.com/GitHub_Trending/cl/cloudnative-pg创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表