清单映射

从 Zalando CR(acid.zalan.do/v1 postgresql)到 CloudNativePG 资源(postgresql.cnpg.io/v1)的逐字段映射。

随产品交付提供一个自动化转换脚本,zalando-to-cnpg(operator 源代码仓库,hack/zalando-to-cnpg/): 它会生成一个 Cluster 以及 Pooler/Database 资源,并为每个无法映射的字段输出明确的 WARN —— 请将每条警告视为一项检查项。

图例:direct = 复制;transform = 重命名/转换; mechanism = 不同的资源或方法;none = 无对应项(工具会发出警告)。

核心

ZalandoCloudNativePGKind说明
metadata.namemetadata.namedirectCNPG 中没有 teamId- 前缀规则;重命名会改变 service DNS 名称。
spec.teamIdnone仅为约定;通过 inheritedMetadata 作为 label 保留。
spec.numberOfInstancesspec.instancesdirectZalando 的 0(hibernation)→ 注解 cnpg.io/hibernation: "on",而不是 instances: 0
spec.dockerImagespec.imageNametransform绝不要直接复制——Spilo 镜像无法与 CNPG 配合使用。根据 postgresql.version 推导出对应 major 的 PostgreSQL operand 镜像。
spec.postgresql.versionimage majortransformCNPG 会从镜像中推断版本。
spec.envspec.envtransform删除 Spilo/WAL-G 变量(WAL_S3_BUCKETUSE_WALG_*AWS_* 等)——备份配置会迁移到 barman-cloud ObjectStore

存储和资源

ZalandoCloudNativePGKind说明
spec.volume.sizespec.storage.sizedirect支持原地扩容;不支持缩容(任一侧均不支持)。
spec.volume.storageClassspec.storage.storageClassdirect
spec.volume.selectorspec.storage.pvcTemplate.selectortransform
spec.volume.subPath / iops / throughputnone固定的 PGDATA 布局;IOPS/throughput 过去是 AWS EBS API 调用——请通过 StorageClass 表达。
spec.additionalVolumesnone (partial)Secrets/ConfigMaps → spec.projectedVolumeTemplate;数据卷 → spec.tablespaces / spec.walStorage
spec.resourcesspec.resourcesdirect如果在 Zalando CR 中缺失,则会应用 operator-config 默认值——在 CNPG 中应显式设置。

用户和数据库

ZalandoCloudNativePGKind说明
spec.usersspec.managed.roles[]transform标志位按 1:1 映射(superusercreatedbcreaterolereplicationbypassrlsnologinlogin: false)。⚠ Zalando 用户默认具有 LOGIN;CNPG managed roles 默认 login: false —— 工具始终会显式输出 login
credential secretsmanaged.roles[].passwordSecretmechanismCNPG 期望使用 kubernetes.io/basic-auth Secret。将密码从 Zalando 的 <user>.<cluster>.credentials... Secret 中复制出来,以保持应用凭证可用。
spec.usersWithSecretRotation (+ in-place variant)none不支持自动密码轮换。
spec.databasesbootstrap.initdb.{database,owner} + Database CRstransform第一项用于引导集群;其余每一项都会成为一个 Database 资源。
spec.preparedDatabasesDatabase CR (schemas, extensions) + rolestransformZalando 的自动角色层次结构(<db>_owner/_reader/_writer + 默认权限)不会自动创建——需要合成 roles 和 GRANT(例如 postInitApplicationSQL)。

PostgreSQL 配置

ZalandoCloudNativePGKind说明
spec.postgresql.parametersspec.postgresql.parameterstransform直接复制,但要排除由 operator 控制的参数(工具会剥离并告警):archive_*restore_commandporthot_standby、recovery targets、ssl*synchronous_standby_namesshared_preload_libraries(→ 专用字段)、listen/log/file-path 设置。调优参数(max_connectionsshared_buffers 等)都会透传。
spec.patroni.pg_hbaspec.postgresql.pg_hbatransformCNPG 会前置固定规则,并追加 host all all all scram-sha-256;Zalando 的列表会替换整个文件。Spilo 特有的行(pamstandby)会被剥离。
spec.patroni.initdbspec.bootstrap.initdbtransformencoding/locale/data-checksums 会映射;仅在全新引导时相关。
spec.patroni.synchronous_modespec.postgresql.synchronoustransform{method: any, number: <synchronous_node_count or 1>};非 strict → dataDurability: preferredsynchronous_mode_strict: truerequired
spec.patroni.slotsspec.replicationSlotsmechanismHA slots 会自动创建;用于 CDC 的永久逻辑 slot → Publication/Subscription 资源或 SQL。
spec.patroni.ttl / loop_wait / retry_timeout / maximum_lag_on_failover / failsafe_modenonePatroni/DCS 调优没有对应项(相关字段:spec.failoverDelayspec.probes)。

Pooling、服务、网络

ZalandoCloudNativePGKind说明
spec.enableConnectionPoolerseparate Pooler resourcemechanism⚠ Zalando 的默认 pool 模式是 transaction;CNPG 的默认值是 session —— 请显式设置 pgbouncer.poolMode: transaction。Zalando 默认 2 个实例,而 CNPG 为 1 个。应用需要重定向到 Pooler service。
spec.enableReplicaConnectionPoolersecond Pooler with type: romechanism
spec.connectionPooler.*Pooler.spec.*transformnumberOfInstancesinstancesmodepgbouncer.poolModemaxDBConnectionspgbouncer.parameters;resources/image → pod template
spec.enableMasterLoadBalancer / enableReplicaLoadBalancerspec.managed.services.additional[]mechanism添加 {selectorType: rw or ro, serviceTemplate: {spec: {type: LoadBalancer}}}——默认服务不会被修改;service DNS 名称会改变。
spec.allowedSourceRanges…serviceTemplate.spec.loadBalancerSourceRangestransform
spec.serviceAnnotations (+ per-role variants)service templates / inheritedMetadata.annotationstransform
spec.podAnnotationsspec.inheritedMetadata.annotationstransform作用于所有生成的对象。

调度和 pod 属性

ZalandoCloudNativePGKind说明
spec.nodeAffinityspec.affinity.nodeAffinitydirectCNPG 还提供了反亲和控制(podAntiAffinityTypetopologyKey)。
spec.tolerationsspec.affinity.tolerationsdirect注意其嵌套在 affinity 下。
spec.podPriorityClassNamespec.priorityClassNamedirect
spec.schedulerNamespec.schedulerNamedirect
spec.spiloRunAsUser / spiloRunAsGroup / spiloFSGroupspec.postgresUID / postgresGIDtransformCNPG 默认 uid/gid 为 26(Spilo 使用 101);通常应去掉。
spec.sidecars / spec.initContainersnone有意不支持。Metrics sidecar → 内置 exporter;初始化逻辑 → bootstrap.initdb.postInit*SQL
spec.maintenanceWindowsnone最接近的选项:spec.primaryUpdateStrategy: supervised

备份、克隆、待机、TLS、CDC

ZalandoCloudNativePGKind说明
spec.enableLogicalBackup + schedulenoneCNPG 备份通过 ScheduledBackup 执行物理备份(⚠ 6 字段 cron——需要在前面加一个秒字段)。如有需要,请将逻辑导出保留为你自己的 CronJob。
spec.clone(无 timestamp)spec.bootstrap.pg_basebackup + externalClustersmechanism运行中的集群克隆——可对正在运行的 Zalando 集群执行(这是受支持的迁移路径)。
spec.clone(timestamp / s3 fields)bootstrap.recovery + externalClusters[].barmanObjectStoremechanism仅可从 barman 格式归档恢复——Spilo WAL-E/WAL-G 归档对 CNPG 不可读
spec.standby(S3 WAL path)none同样存在归档不兼容问题。
spec.standby(host/port)spec.replica + externalClustersmechanism外部 primary 的流式 standby;通过切换 replica.enabled 完成提升。
spec.tlsspec.certificatestransform单 Secret 模型会拆分为 server/client(+ replication)证书;SAN 必须覆盖 <cluster>-rw.<ns>.svc。最简单的做法是省略,让 CNPG 自行管理。
spec.streams (CDC)none需要基于 Publication/Subscription 资源或外部 Debezium 重新设计(wal_level=logical 是 CNPG 的默认值)。

ACP PostgreSQL 旧版本中的 Zalando 专有字段

Zalando (ACP fork)CloudNativePG说明
spec.backup (WAL-G schedule/retention/storage)barman-cloud ObjectStore + spec.plugins + ScheduledBackup + retentionPolicyCNPG 的第一次备份是全新的完整备份。
spec.exporter / enableExporterspec.monitoring (built-in exporter)参见 Grafana dashboards 指南(How To 部分)。
spec.enablePgpool2仅支持 PgBouncer Pooler;查询负载均衡 ≈ -ro service + 应用路由。
spec.clusterReplicationspec.replica + externalClusters (+ promotion/demotion tokens)CNPG 的 replica-cluster(分布式拓扑)模型。
spec.usersCustomizedPasswdmanaged.roles[].passwordSecret将密码从 CR 中移出,放入 basic-auth Secret。
spec.ipFamilyPreferservice templates ipFamilies/ipFamilyPolicy单栈 IPv6 需要 operator 中的 url.Build 修复(参见 配置)。

实战示例

Zalando 源:

apiVersion: acid.zalan.do/v1
kind: postgresql
metadata:
  name: acid-orders
spec:
  teamId: acid
  numberOfInstances: 3
  postgresql:
    version: "16"
    parameters:
      shared_buffers: 512MB
      max_connections: "300"
  volume:
    size: 20Gi
    storageClass: sc-topolvm
  users:
    orders_svc: [createdb]
    analyst: []
  databases:
    orders: orders_svc
  patroni:
    pg_hba: [host all all 10.0.0.0/8 md5]
    synchronous_mode: true
    synchronous_node_count: 1
  resources:
    requests: {cpu: "1", memory: 2Gi}
    limits: {cpu: "2", memory: 4Gi}
  enableConnectionPooler: true

转换后的结果(工具输出的内容——一个 Cluster 加一个 Pooler):

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: acid-orders
spec:
  instances: 3
  imageName: <postgresql-16-operand-image>   # per your platform registry
  inheritedMetadata:
    labels:
      acid.zalan.do/team: acid
  bootstrap:
    initdb:
      database: orders
      owner: orders_svc
  managed:
    roles:
      - {name: analyst, ensure: present, login: true}
      - {name: orders_svc, ensure: present, login: true, createdb: true}
  postgresql:
    parameters:
      shared_buffers: 512MB
      max_connections: "300"
    pg_hba: [host all all 10.0.0.0/8 md5]
    synchronous:
      method: any
      number: 1
      dataDurability: preferred   # synchronous_mode without 'strict'
  storage: {size: 20Gi, storageClass: sc-topolvm}
  resources:
    requests: {cpu: "1", memory: 2Gi}
    limits: {cpu: "2", memory: 4Gi}
---
apiVersion: postgresql.cnpg.io/v1
kind: Pooler
metadata:
  name: acid-orders-pooler-rw
spec:
  cluster: {name: acid-orders}
  type: rw
  instances: 2                   # Zalando default
  pgbouncer:
    poolMode: transaction        # Zalando default (CNPG default is session!)

在发布验收期间,这一转换已完成端到端验证:转换后的 manifest 成功部署到了一个健康的 3 实例集群中,并通过 SQL 验证了引导数据库/owner、角色标志、同步复制(ANY 1 (...))、参数以及 pg_hba;写入则通过 transaction 模式下的 Pooler 执行。

对应用而言,变化如下:

ZalandoCloudNativePG
write endpointacid-orders.<ns>.svcacid-orders-rw.<ns>.svc(或 Pooler service)
read endpointacid-orders-repl.<ns>.svcacid-orders-ro.<ns>.svc
credentialsorders_svc.acid-orders.credentials... secretacid-orders-app(bootstrap owner)/ 你的 basic-auth Secret