用 CloudNativePG 声明式管理 PostgreSQL 配置:从 postgresql.conf 到 pg_hba.conf

2026-08-04 48 预计阅读时间: 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.

预计阅读时间:10 分钟

对于习惯 SSH 登录虚拟机、编辑 postgresql.confpg_hba.conf 的 DBA 来说,迁移到 Kubernetes 后,最明显的变化不是 SQL,而是配置方式变了:Pod 可能随时重建,容器内手工修改的文件也不会成为可靠的事实来源。

CloudNativePG(CNPG)把 PostgreSQL 集群配置放进 Kubernetes 自定义资源(CRD)中。DBA 只需要声明目标状态,操作符负责生成配置、执行 reload,或在必要时安排受控的重启流程。这种“无 SSH”方式会改变日常操作习惯,但也带来了版本控制、审查、可重复部署和更清晰的恢复路径。

从编辑文件转向声明目标状态

传统虚拟机环境通常是命令式操作:

  1. SSH 到数据库服务器。
  2. 编辑磁盘上的配置文件。
  3. 执行 pg_ctl reload,或者重启 PostgreSQL。
  4. 依靠人工记录这次变更。

在 Kubernetes 中,配置应当成为集群资源的一部分。CNPG 的典型工作流是:

  1. Cluster YAML 的 spec.postgresql 下声明参数。
  2. 通过 Git 审查变更。
  3. 使用 kubectl apply 更新资源。
  4. 由 CNPG 判断哪些变化可以 reload,哪些变化需要重启。

这意味着容器文件系统不再是配置的权威来源。即使你临时进入 Pod 修改了文件,后续重建或同步也可能覆盖这次修改,而且这次变更不会自然地出现在 Git 历史中。

用 YAML 调整 PostgreSQL 参数

下面是一个可以改造的 CNPG 集群示例。它配置了三个实例、连接数、内存相关参数和基础日志设置:

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: prod-postgres
spec:
  instances: 3
  postgresql:
    parameters:
      max_connections: "500"
      shared_buffers: "4GB"
      effective_cache_size: "12GB"
      work_mem: "32MB"
      maintenance_work_mem: "1GB"
      logging_collector: "on"
      log_min_messages: "warning"
  storage:
    size: 50Gi

保存为 cluster.yaml 后,可以这样提交:

kubectl apply -f cluster.yaml
kubectl get cluster prod-postgres
kubectl get pods -l cnpg.io/cluster=prod-postgres -o wide

CNPG 会根据资源中的声明生成 PostgreSQL 配置。参数的生效方式取决于 PostgreSQL 本身:能够动态修改的参数通常可以通过配置 reload 生效;需要重新启动实例的参数则需要更谨慎的处理。像 shared_buffers 这类参数通常不能仅靠 reload 生效,而 work_mem 等参数通常适合动态调整,但仍应结合 PostgreSQL 版本和实际参数属性验证。

对于包含多个实例的集群,重启流程由操作符协调。生产环境仍然需要检查 Pod 角色、同步状态、PDB、维护窗口和应用连接重试能力,不能把“自动滚动重启”理解成任何情况下都绝对无感。

可以通过 PostgreSQL 或 CNPG 的状态信息确认变更是否真正生效,而不是只检查 Kubernetes 对象是否更新:

kubectl cnpg status prod-postgres
kubectl exec -it prod-postgres-1 -- \
  psql -U postgres -d postgres \
  -c "SHOW shared_buffers; SHOW work_mem;"

上面的 Pod 名称只是示例,实际名称应以 kubectl get pods 的输出为准。

声明式管理 pg_hba.conf

客户端认证规则也不需要直接编辑容器中的 pg_hba.conf。可以将自定义规则写入 spec.postgresql.pg_hba

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: prod-postgres
spec:
  instances: 3
  postgresql:
    pg_hba:
      - host all all 127.0.0.1/32 scram-sha-256
      - hostssl app_db app_user 10.244.0.0/16 scram-sha-256
      - host all all 0.0.0.0/0 reject

规则的顺序非常重要,PostgreSQL 会使用匹配到的第一条规则。示例中的网段需要替换成真实的应用网络范围,认证方式也应优先使用符合当前环境的安全配置,例如 scram-sha-256。不要为了快速排障在生产环境广泛使用 trust,因为它可能绕过密码认证。

CNPG 还需要保留集群内部通信和复制所需的规则。实践中,应以当前 CNPG 版本生成的默认行为和文档约束为准,避免用过于宽泛的规则覆盖内部连接所需的访问控制。

提交规则后,可以观察集群事件和实例状态:

kubectl apply -f cluster.yaml
kubectl describe cluster prod-postgres
kubectl get events --sort-by=.lastTimestamp

修改认证规则前,建议至少保留一个经过验证的管理入口,并在非生产环境测试新规则。错误的 pg_hba.conf 规则可能让应用无法连接,甚至让管理员失去登录路径。

用户、数据库与 Secret 分开管理

数据库用户的密码不应直接写在 Cluster YAML 或 Git 仓库中。可以先创建 Kubernetes Secret,再让 CNPG 在初始化数据库时引用它:

kubectl create secret generic app-user-credentials \
  --from-literal=username=app_user \
  --from-literal=password='replace-with-a-strong-password'

对应的集群资源可以这样写:

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: prod-postgres
spec:
  instances: 3
  bootstrap:
    initdb:
      database: app_db
      owner: app_user
      secret:
        name: app-user-credentials
  storage:
    size: 50Gi

这个示例假设 Secret 与 Cluster 资源位于同一个 Kubernetes namespace,并且 Secret 包含 CNPG 需要的键。生产环境中,建议使用外部 Secret 管理系统、Sealed Secrets 或其他受控的密钥同步方案,而不是把真实密码直接放进 shell 历史记录。示例中的密码只是占位值,不能用于生产。

还要区分两类变更:bootstrap.initdb 主要用于初始化集群;对于已经运行的集群,新增用户、轮换密码和修改权限通常应通过受控 SQL migration、专门的 Job,或其他符合团队审计流程的机制完成,而不是期待修改 bootstrap 配置后自动重建现有数据库。

“无 SSH”带来的工程收益

把配置放入 YAML 后,数据库运维获得了几个传统手工操作难以稳定提供的能力:

  • 变更可审查shared_buffers、认证网段和日志策略都可以通过 Pull Request 审核。
  • 配置可复现:新环境可以使用同一套声明重建集群,减少“这台机器曾经手工改过什么”的依赖。
  • 失败更容易暴露:YAML 结构、资源字段和操作符约束可以在 Kubernetes API 或部署流水线阶段被检查。
  • 恢复路径更清晰:节点或 Pod 发生故障后,操作符可以依据资源声明重新调度实例;但这并不替代备份、归档、恢复演练和数据持久化设计。
  • 减少漂移:不允许把容器内临时修改当作长期配置,能避免线上状态与仓库内容逐渐分叉。

这些收益并不意味着所有数据库操作都应该交给操作符。参数调优仍然需要容量模型、查询数据和压测结果;认证规则仍然需要网络边界和最小权限设计;重启流程仍然需要应用侧连接池和故障转移能力配合。

迁移时可以采用的检查清单

  • 把现有 postgresql.conf 中的业务相关参数整理为 spec.postgresql.parameters
  • pg_hba.conf 规则按连接来源、数据库、用户和认证方式重新审查,而不是机械复制。
  • 明确每个参数是 reload 生效还是需要重启,并为重启设置维护窗口。
  • 使用 Secret 或外部密钥系统管理密码,避免明文进入 Git 和 shell 历史。
  • 在测试集群验证 YAML、认证规则、复制状态和应用重连行为。
  • 为配置资源建立 Git 审查、部署记录和回滚流程。
  • 继续维护备份、PITR、监控和恢复演练,不能把自愈能力当成备份的替代品。

CloudNativePG 并没有削弱 DBA 对 PostgreSQL 的控制,而是把控制面从服务器上的文本文件移到了可审查的声明式资源。真正的转变是:数据库配置不再依赖某个人记得一条 SSH 命令,而成为团队可以理解、验证、发布和恢复的系统资产。


相关推荐