Percona PostgreSQL Operator 3.1:把磁盘加密、只读分析与持久日志纳入集群声明

2026-09-10 21 预计阅读时间: 1 分钟
来源: postgr.es AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:12 分钟

Percona Operator for PostgreSQL 3.1.0 解决了数据库平台评审中最常见的三类问题:静态数据是否由数据库自身加密、分析查询能否绕开主库,以及 Pod 重启后故障日志是否还在。新版本把这些能力直接放进 PerconaPGCluster 自定义资源,包括基于 pg_tde 的透明数据加密、面向只读负载的逻辑副本,以及 PostgreSQL 与 pgBackRest 的持久化日志。

这不只是功能数量增加。更重要的变化是,团队可以用声明式配置管理这些能力,不再需要额外维护一套加密脚本、手工复制链路或临时日志采集方案。

pg_tde:加密范围从磁盘扩展到数据库对象和 WAL

云盘或存储阵列提供的加密可以保护物理介质,但无法完全回答另一些安全问题:卷快照被复制后怎么办,备份被传到对象存储后怎么办,单独泄露的 WAL 文件是否仍然可读?

3.1.0 通过开源扩展 pg_tde 增加数据库层透明数据加密。它可以加密磁盘上的表、索引、临时表和预写日志,PostgreSQL 只在持有密钥的会话内存中完成解密。密钥并不与数据放在一起,而是由外部 HashiCorp Vault 管理,从而把数据库运维权限与密钥保管权限分开。

pg_tde 使用两级密钥模型:Vault 中的 principal key 用来包装内部数据密钥。轮换 principal key 主要是密钥管理操作,不等同于重新加密整个数据库,这对大型集群尤其重要。

可以这样接入 Vault

下面的命令会创建 Operator 引用的 Secret。运行前需要准备 Vault Token 和 CA 文件,并把命名空间、地址及挂载路径替换成自己的值:

export VAULT_TOKEN='replace-with-a-real-token'

kubectl create namespace postgres --dry-run=client -o yaml | kubectl apply -f -
kubectl -n postgres create secret generic pg-tde-vault-secret \
  --from-literal=token="${VAULT_TOKEN}" \
  --from-file=ca.crt=./vault-ca.crt

随后把以下配置合并到集群清单中:

apiVersion: pgv2.percona.com/v2
kind: PerconaPGCluster
metadata:
  name: cluster1
  namespace: postgres
spec:
  extensions:
    pg_tde:
      enabled: true
      walEncryption: true
      vault:
        host: https://vault-service:8200
        mountPath: tde
        tokenSecret:
          name: pg-tde-vault-secret
          key: token
        caSecret:
          name: pg-tde-vault-secret
          key: ca.crt

应用前可以先做服务端校验:

kubectl apply --server-side --dry-run=server -f cluster.yaml
kubectl apply --server-side -f cluster.yaml

这里的 enabled: true 会启用 pg_tdewalEncryption: true 则把 WAL 纳入加密范围。Vault Token 和 CA 应保存在 Kubernetes Secret 中,不要直接写进 Git 仓库里的清单。

这项能力目前适用于 PostgreSQL 17 和 18。另一个必须提前确认的边界是:启用加密后,保护的是随后写入的数据,并不会瞬间把已有生产库的所有存量页转换成密文。因此,更稳妥的做法是在新集群创建阶段启用;如果要迁移已有集群,应设计数据重写、逻辑迁移或重建流程,并实际验证备份与恢复。

逻辑副本:给报表一个不会被提升为主库的稳定端点

由 Patroni 管理的物理副本主要服务于高可用。发生故障切换时,它们的角色可能改变,因此并不是报表工具最稳定的长期连接目标。分析查询又往往持续时间长、扫描数据多,并在仪表盘刷新或夜间任务执行时形成突发负载;如果这些查询落在主库上,就会与交易写入争夺 CPU、内存和 I/O。

3.1.0 允许在同一个集群声明逻辑副本。该副本拥有独立卷、计算资源和 Service,通过 pgBackRest 备份完成初始装载,再用逻辑复制持续追赶主库。它不受 Patroni 管理,不会在故障切换中晋升为主库,因此报表系统可以持续使用同一个只读端点。

下面是一段可合并到 spec 下的配置:

spec:
  logicalReplicas:
    - name: analytics
      databases: []
      bootstrapMethod: pgbackrest
      dataVolumeClaimSpec:
        accessModes:
          - ReadWriteOnce
        resources:
          requests:
            storage: 100Gi
      resources:
        requests:
          cpu: "500m"
          memory: 1Gi
        limits:
          cpu: "2"
          memory: 4Gi
      expose:
        type: ClusterIP

databases: [] 表示复制除 postgres 之外的所有非模板数据库;如果只需报表库,应显式列出目标数据库。bootstrapMethod: pgbackrest 让初始数据来自备份,避免直接给主库增加一次完整复制压力。示例使用 ClusterIP,适合 Kubernetes 集群内访问;只有确实需要从集群外连接时,才应改成 LoadBalancer,并同时落实网络访问控制与 TLS。

逻辑副本在 3.1.0 中仍是技术预览,且要求 PostgreSQL 17 或更高版本。它也不是一个“复制所有变化”的魔法镜像:PostgreSQL 逻辑复制不会自动传播 DDL。发布新表、修改列或调整约束时,必须把副本侧的 Schema 变更纳入发布流程。

例如,可以在应用迁移流水线中明确区分 Schema 与数据复制:

# 示例流程:先备份,再对主库和逻辑副本协调执行兼容的 DDL。
kubectl -n postgres get pods
kubectl -n postgres get services | grep analytics

# 实际执行前,将连接串替换为受控 Secret 或 CI 变量。
psql "$PRIMARY_DSN" -v ON_ERROR_STOP=1 -f migrations/2025_analytics.sql
psql "$ANALYTICS_DSN" -v ON_ERROR_STOP=1 -f migrations/2025_analytics.sql

不要盲目在两个端点执行同一迁移。涉及复制订阅、只读策略或对象所有权的语句,应拆分成针对主库与副本的独立脚本。

持久日志:Pod 消失后仍能还原现场

容器标准输出适合实时采集,却不应成为唯一证据。实例进入 CrashLoop、Pod 被重新调度或节点故障时,关键的崩溃信息可能随着旧容器一起消失。

新版本可以把 PostgreSQL 和 pgBackRest 日志保存在实例数据卷上,并通过 Fluent Bit sidecar 读取日志、转换成结构化 JSON。日志既能跨 Pod 重启保留,也可以继续发送到 S3 或支持 OpenTelemetry 的日志平台。

可以在集群清单中启用日志收集器:

spec:
  logcollector:
    enabled: true
    image: docker.io/perconalab/fluentbit:main-logcollector
    configuration: |
      pipeline:
        filters:
          - name: record_modifier
            match: "*"
            record:
              - cluster_name cluster1
              - environment production

这段过滤配置会给记录增加集群和环境字段,方便在集中式平台中检索。生产环境不宜长期依赖浮动镜像标签,应换成经过验证的版本标签或镜像摘要,并在升级 Operator 时一起做兼容性测试。

持久日志也有明确成本:它会占用数据库实例的数据卷。如果没有限制日志保留量,最终可能让日志与 PostgreSQL 数据争夺空间。上线前至少应确定:

  • 单文件大小与轮转频率;
  • 本地保留天数和最大容量;
  • 转发失败时的缓冲上限;
  • S3 或日志平台的长期保留策略;
  • 日志中密码、Token、SQL 参数等敏感信息的脱敏规则。

其他影响日常运维的变化

3.1.0 还扩展了镜像和平台选择。Operator 现在正式支持 RKE2,并提供完整 ARM64 镜像;团队也可以通过 spec.imageproxy.pgBouncer.imagespec.backups.pgbackrest.image 使用社区 PostgreSQL 或私有镜像仓库中的构建。

其他值得评估的能力包括:

  • pgBackRest 仓库卷可按上限自动扩容,降低备份因磁盘写满而失败的概率;
  • pgBouncer 支持暂停与恢复,可在维护期间暂缓流量;
  • pgBouncer 可以通过额外 CA 建立 mTLS 信任;
  • 可接入自有 cert-manager Issuer,并通过证书管理策略明确生命周期责任;
  • PostgreSQL 容器支持挂载额外的 ConfigMap、Secret、PVC 或 emptyDir
  • pg_cronset_user 成为内置扩展;
  • PostgreSQL 19 可用于技术预览测试。

升级时还要处理两项兼容性变化:PMM2 支持已经移除,需要迁移到 PMM3;extensions.builtin 已弃用,应改成 extensions.<name>.enabled,并在 3.4.0 之前完成清单迁移。

上线前的决策清单

这三个功能不必一次全部开启,可以按风险和收益分阶段采用:

  1. 新建受监管集群:在初始化阶段启用 pg_tde 和 WAL 加密,确认 Vault 高可用、Token 生命周期、密钥轮换和灾难恢复流程。
  2. 隔离分析负载:先为一个非关键报表建立逻辑副本,测量复制延迟、备份装载时间和 DDL 发布复杂度,再决定是否扩大使用范围。
  3. 保留故障证据:启用持久日志前先设置轮转与容量告警,并把日志转发到集群外,避免数据库卷成为唯一副本。
  4. 验证恢复而非只验证部署:执行一次加密备份恢复、Vault 暂时不可用和逻辑副本重建演练。能创建集群不代表能在事故中恢复集群。
  5. 检查升级阻塞项:迁移 PMM2 和 extensions.builtin,同时确认自定义镜像在 AMD64、ARM64 或 RKE2 环境中的兼容性。

Percona Operator for PostgreSQL 3.1.0 的核心价值,是把安全、读负载隔离和故障取证变成同一个 Kubernetes API 下的声明式能力。它减少了外围脚本,但不会替团队自动完成密钥治理、DDL 协调和容量规划。真正上线前,仍应把这些边界写进运行手册,并通过恢复演练验证。


相关推荐