在 Kubernetes 上运行 PostgreSQL,目前社区里两个最受关注的开源 Operator 是 CloudNativePG(CNPG)和 Crunchy Data 的 Crunchy PGO。这篇文章的作者 Gabriele Bartolini 正是 CNPG 的联合创始人和核心维护者——他坦率承认自己不可能中立,但多年深耕项目让他对两者的差异有着"有据可偏"的理解。本文基于他的对比分析,梳理两个 Operator 在架构、镜像、备份、大版本升级、可观测性、许可证与社区健康度上的关键分歧,并给出选型建议。
架构哲学:单集群 vs 多集群管理
CloudNativePG 的核心设计思路是"一个 Operator 管理一个 Kubernetes 集群内的所有 PostgreSQL 集群"。它没有引入额外的 CRD 层级——一个 Cluster 资源就定义了一组主从实例,Operator 直接监听这个 CRD 并完成实例编排。这种设计的好处是简单:你不需要理解额外的抽象层,kubectl get cluster 就能看到所有数据库集群的状态。
Crunchy PGO 的架构则更偏向"多集群集中管控"。它使用 PostgresCluster CRD,但 Operator 本身可以跨多个 Kubernetes 集群管理 PostgreSQL 实例。如果你的数据库需要分布在不同地域的多个 K8s 集群中,PGO 的集中管理视角可能更贴合需求。
取舍点:单集群场景下 CNPG 的 CRD 更轻量、更易上手;多集群场景下 PGO 的管控模型更成熟。
镜像设计:谁拥有 PostgreSQL 二进制?
这是两者最根本的分歧之一。
CNPG 的镜像策略是直接包含 PostgreSQL 官方二进制。容器镜像里就是 PostgreSQL 本身,加上少量管理脚本。升级 PostgreSQL 版本意味着拉取新镜像——版本切换由镜像标签驱动,简单直接。
PGO 的镜像策略是将 PostgreSQL 二进制与管理工具分离。Crunchy Data 构建了自己的 PostgreSQL 容器镜像(基于 Red Hat UBI 或 Debian),镜像中包含 Crunchy 的管理工具集(如 crunchy-backrest、crunchy-pgbench 等)。这种分离让管理工具可以独立演进,但也意味着你运行的不是"原版" PostgreSQL 镜像,而是 Crunchy 打包后的版本。
取舍点:如果你希望尽可能贴近 PostgreSQL 官方发行版,CNPG 的镜像更"干净";如果你更看重配套管理工具的一体化交付,PGO 的镜像体系更完整。
备份策略:Barman vs pgBackRest
备份是生产环境的生命线,两个 Operator 选了不同的备份引擎。
CNPG 使用 Barman(由 2ndQuadrant/EDB 开发)作为备份工具,支持全量备份、增量备份和 WAL 持续归档。Barman 在 PostgreSQL 社区有长期的生产验证,CNPG 将其集成进 Operator 的备份 CRD 中:
apiVersion: barmancloud.cnpg.io/v1
kind: ObjectStore
metadata:
name: backup-s3
spec:
configuration:
destinationPath: s3://my-pg-backups/cnpg
s3Credentials:
accessKeyId:
name: s3-creds
key: ACCESS_KEY_ID
secretAccessKey:
name: s3-creds
key: SECRET_ACCESS_KEY
wal:
encryption: AES256
data:
encryption: AES256
compression: bzip2
immediateCheckpoint: false
PGO 使用 pgBackRest(Crunchy Data 开发)作为备份工具,同样支持全量、增量、WAL 归档,并且有专用的备份 Sidecar 容器。pgBackRest 在 Crunchy 的商业产品中经过大量生产验证,功能丰富(如增量备份的页级增量、备份保留策略等)。
取舍点:Barman 更贴近 EDB 生态,pgBackRest 更贴近 Crunchy 生态。两者都能满足生产级备份需求,但如果你已有 Barman 运维经验,CNPG 的集成更自然;反之同理。
大版本升级:在线 vs 璇转
PostgreSQL 大版本升级(如 15 → 16)是运维中最紧张的操作之一。
CNPG 采用 pg_upgrade 在线升级策略。你在 Cluster CRD 中修改 imageName 指向新版本镜像,Operator 会自动执行 pg_upgrade 流程:创建新版本实例、迁移数据、切换主节点。整个过程在同一个 Cluster 资源内完成,不需要创建新的 CRD。
PGO 采用 旋转升级(rolling upgrade)策略。升级时需要创建一个新的 PostgresCluster 资源指向新版本,Operator 通过逻辑复制(pglogical)或 pg_upgrade 将数据从旧集群迁移到新集群,然后切换流量。这种方式更"安全"——旧集群始终保留,回滚更容易,但流程更复杂,需要管理两个 CRD。
取舍点:CNPG 的升级更简洁,适合对升级流程有信心、追求操作效率的团队;PGO 的旋转升级更保守,适合对回滚有硬性要求的场景。
可观测性:指标暴露方式
CNPG 通过 Patroni 管理 PostgreSQL 实例的生命周期,Patroni 自带 /metrics 端点暴露集群状态指标。CNPG 还额外暴露了 PostgreSQL 统计指标(如 pg_stat_statements),可以直接被 Prometheus 抓取:
apiVersion: monitoring.coreos.com/v1
kind: PodMonitor
metadata:
name: cnpg-cluster-monitor
spec:
selector:
matchLabels:
cnpg.io/cluster: my-pg-cluster
podMetricsEndpoints:
- port: metrics
path: /metrics
interval: 30s
PGO 的可观测性更"模块化"。它通过专用的 Collector Sidecar 容器暴露指标,Collector 基于 Crunchy 的 crunchy-postgres-exporter,提供了更细粒度的 PostgreSQL 内部指标。PGO 还内置了 Grafana Dashboard 的部署选项。
取舍点:CNPG 的指标暴露更轻量,依赖 Patroni 自身能力;PGO 的指标体系更丰富,但引入了额外的 Sidecar 容器。
许可证与社区健康度
CNPG 采用 Apache 2.0 许可证,代码完全开放,社区贡献流程透明。项目由 EDB 赞助但社区治理结构开放,GitHub 上活跃度较高,Issue 和 PR 的响应速度较快。
PGO 采用 Apache 2.0 许可证(核心 Operator 部分),但 Crunchy Data 的部分配套工具(如某些监控组件)可能受更严格的许可证约束。PGO 的社区同样活跃,但作为 Crunchy Data 的核心商业产品之一,其演进方向与 Crunchy 的商业策略绑定更深。
取舍点:两者核心都是 Apache 2.0,但 CNPG 的社区治理更独立于单一商业实体;PGO 的生态更依赖 Crunchy Data 的产品路线图。
实践示例:用 CNPG 快速部署一个高可用 PostgreSQL 集群
以下是一个可以直接复制运行的 CNPG 部署示例,展示从安装 Operator 到创建集群到配置备份的完整流程:
# 1. 安装 CNPG Operator(v1.24.x)
kubectl apply -f \
https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/main/releases/cnpg-1.24.0.yaml
# 等待 Operator 就绪
kubectl wait -n cnpg-system deployment/cnpg-controller-manager \
--for=condition=Available --timeout=120s
# 2. 创建 S3 备份凭证 Secret
apiVersion: v1
kind: Secret
metadata:
name: s3-creds
type: Opaque
stringData:
ACCESS_KEY_ID: "your-access-key"
SECRET_ACCESS_KEY: "your-secret-key"
---
# 3. 定义备份存储目标
apiVersion: barmancloud.cnpg.io/v1
kind: ObjectStore
metadata:
name: minio-backup
spec:
configuration:
destinationPath: s3://pg-backups/cnpg-prod
s3Credentials:
accessKeyId:
name: s3-creds
key: ACCESS_KEY_ID
secretAccessKey:
name: s3-creds
key: SECRET_ACCESS_KEY
endpointURL: "https://minio.example.com" # 如用 MinIO 替代 AWS S3
wal:
maxParallel: 8
encryption: AES256
data:
compression: bzip2
encryption: AES256
---
# 4. 创建 PostgreSQL 集群(3 实例:1 主 + 2 从)
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: pg-prod
spec:
imageName: ghcr.io/cloudnative-pg/postgresql:16.4
instances: 3
minSyncReplicas: 1
maxSyncReplicas: 2
postgresql:
parameters:
max_connections: "200"
shared_buffers: "256MB"
pg_stat_statements.track: all
bootstrap:
initdb:
database: appdb
owner: appuser
backup:
barmanObjectStore:
objectStore:
name: minio-backup
retentionPolicy: "30d"
monitoring:
enablePodMonitor: true
# 5. 验证集群状态
kubectl get cluster pg-prod
kubectl get pods -l cnpg.io/cluster=pg-prod
# 6. 连接数据库(CNPG 自动创建 Service)
kubectl run psql-client --rm -it --image=postgres:16 \
--env=PGPASSWORD=$(kubectl get secret pg-prod-appuser -o jsonpath='{.data.password}' | base64 -d) \
-- psql -h pg-prod-rw -U appuser -d appdb
运行前需要修改的地方:S3 凭证替换为你的真实值,endpointURL 如用 AWS S3 可删除该行,imageName 版本号按需调整。
选型清单
| 维度 | CNPG 更合适 | PGO 更合适 |
|---|---|---|
| 部署规模 | 单 K8s 集群 | 多 K8s 集群集中管控 |
| 镜像偏好 | 贴近 PG 官方发行版 | 一体化打包管理工具 |
| 备份工具 | 已有 Barman 经验 | 已有 pgBackRest 经验 |
| 大版本升级 | 追求简洁、一次到位 | 需要保留旧集群、随时回滚 |
| 可观测性 | 轻量够用即可 | 需要细粒度 PG 内部指标 |
| 商业依赖 | 希望社区独立演进 | 接受 Crunchy 产品路线绑定 |
| 团队背景 | EDB/2ndQuadrant 生态 | Crunchy Data 生态 |
两个 Operator 都是成熟的生产级方案,选择的核心不是"谁更好",而是"谁的架构假设更匹配你的运维模型"。如果你的 PostgreSQL 集群主要跑在一个 K8s 集群内、团队偏好简洁的 CRD 模型、升级时追求操作效率,CNPG 是更自然的选择。如果你需要跨集群管理、升级时必须保留回滚窗口、或已经在 Crunchy 的工具链上投入了大量运维经验,PGO 更值得采用。