数据迁移

用于将运行中的 Zalando 集群迁移到 CloudNativePG 的数据路径。清单转换请参见 清单映射

选择路径

路径停机时间最适合的规模PG 版本变更复杂度
1. initdb + import(声明式 dump/restore)dump→restore 期间完全停机小/中型(最多几十 GB)任意(可跨主版本)
2. Logical replication几乎为零(仅切换时)中/大型相同或更高的主版本
3. pg_basebackup bootstrap(物理)短暂(切换时)大型必须是相同主版本
WARNING

来自 Zalando archive 的 WAL shipping 不是一种路径。 Spilo 会使用 WAL-E/WAL-G 以 barman-cloud 无法读取的布局归档 WAL;CNPG 集群无法从 Zalando S3 archive 中恢复。备份历史不会继承——切换后应立即执行一次新的 CNPG base backup。

所有路径都需要 CNPG Pod 能够访问 Zalando master service(<zalando-cluster>.<ns>.svc:5432),并且源端要有权限足够高的用户。常见准备工作:

ZC=acid-orders                      # zalando cluster name, namespace $NS
# source superuser password (Zalando-managed secret):
kubectl -n $NS get secret postgres.$ZC.credentials.postgresql.acid.zalan.do \
  -o jsonpath='{.data.password}' | base64 -d
# CNPG external clusters want basic-auth secrets:
kubectl -n $NS create secret generic zalando-src-superuser \
  --type=kubernetes.io/basic-auth \
  --from-literal=username=postgres --from-literal=password='<above>'

路径 1 — 声明式导入(由 operator 驱动的 dump/restore)

CNPG 会在 bootstrap 期间为你执行 pg_dump/pg_restore (bootstrap.initdb.import):它会连接到源端,dump 所选数据库和角色, 将其 restore 到新集群中,然后像普通集群一样继续启动。推荐用于小型/中型数据库—— 并且这是唯一一种还能在同一步中 升级主版本 的路径。

spec:
  bootstrap:
    initdb:
      database: orders
      owner: orders_svc
      import:
        type: microservice          # one DB; 'monolith' = many DBs + roles
        databases: [orders]
        source:
          externalCluster: zalando-src
  externalClusters:
    - name: zalando-src
      connectionParameters:
        host: acid-orders.<ns>.svc
        user: postgres
        dbname: postgres
      password:
        name: zalando-src-superuser
        key: password
  • type: monolith 配合 databases: ["*"]roles: ["*"] 可一次性迁移所有内容。
  • 先在源端停止写入——导入是某一时点的 dump。
  • 之后执行 ANALYZE(统计信息不会被 dump)。

路径 2 — Logical replication(最小停机时间)

先做初始拷贝,再持续流式传输变更;当堆积量接近 0 时进行切换。源端必须设置 wal_level=logical(近期版本中 Spilo 的默认值——可通过 SHOW wal_level; 验证)。

  1. 仅以 schema 启动 CNPG 集群(使用 schemaOnly: true 的路径 1 导入,或手动 restore pg_dump --schema-only —— logical replication 不会复制 DDL)。

  2. 在 Zalando primary 上创建 publication(数据库 orders):

    CREATE PUBLICATION mig_pub FOR ALL TABLES;
  3. 在 CNPG 集群 上创建 subscription(声明式):

    apiVersion: postgresql.cnpg.io/v1
    kind: Subscription
    metadata:
      name: mig-sub
    spec:
      name: mig_sub
      dbname: orders
      publicationName: mig_pub
      cluster:
        name: acid-orders            # the NEW cnpg cluster
      externalClusterName: zalando-src
  4. 监控 pg_stat_subscription(CNPG 侧)和 pg_stat_replication(源端);等待初始同步完成,并保持堆积量接近 0。

  5. 切换:停止写入 → 等待堆积量为 0 → 同步 sequence (logical replication 不会复制它们——请使用源端 pg_sequences 的值进行设置)→ 删除 Subscription → 重新指向应用。

  6. 创建第一个 CNPG base backup;下线源端。

注意事项:表需要 replica identity(主键)才能进行 UPDATE/DELETE;迁移窗口内的 DDL 变更不会被复制;large object 不会被复制。

路径 3 — 物理克隆(pg_basebackup bootstrap)

从运行中的 Zalando primary 流式传输得到的字节级副本——两侧 PostgreSQL 的 主版本 必须相同,包含所有数据库,不需要 schema 工作(等同于 Zalando 的在线 clone)。

spec:
  bootstrap:
    pg_basebackup:
      source: zalando-src
  externalClusters:
    - name: zalando-src
      connectionParameters:
        host: acid-orders.<ns>.svc
        user: standby                  # zalando replication user
        dbname: postgres
      password:
        name: zalando-src-standby      # from standby.<zc>.credentials...
        key: password

要求:源端必须允许来自 CNPG Pod 的 replication 连接(Zalando 的 standby 用户适用),并且 max_wal_senders 需保留足够余量。

该副本是某一时点的——basebackup 之后的写入不会被复制;请在开始前停止写入。Spilo 相关工件(standby 角色、Patroni 辅助对象)之后仍会保留在 catalog 中——无害,可在需要时再移除。

TIP

如果你希望长期保持同步的 standby(先持续复制,切换时再 promote),可以在相同的 pg_basebackup bootstrap 之上添加 replica: {enabled: true, source: zalando-src}——集群会持续从 Zalando primary 拉取流,直到你将 replica.enabled 关闭以完成 promote。

任何路径之后

  1. 第一次 CNPG base backup(Backup 资源,barman-cloud 插件)—— 确认 phase: completed;配置 ScheduledBackup
  2. 监控:PodMonitor + dashboards (Grafana dashboards 指南的 How To 部分)——等待归档的 WAL segments 应为 0。
  3. 在新集群上执行 ANALYZE(路径 1–2)。
  4. 验证应用凭据、连接数限制和 Pooler。
  5. 在回滚窗口期间保持 Zalando 集群暂停(不要删除)。