Files
qinglong/docs/adr/ADR-0129-cloudnativepg-operator-and-database-role-authority.md
T

11 KiB
Raw Blame History

ADR-0129CloudNativePG Operator 与数据库角色权威

  • 状态:Acceptedoperator/operand digest lock、三实例 HA 清单、十二角色 DatabaseRole、独立 Database owner、runtime/migration 离散凭据、CA/主节点 endpoint 绑定、静态负向门及显式 opt-in 的四节点 Kind/CNPG live contract 已完成;成功的远端 live 记录、CA 轮换和备份恢复仍是 Release Gate
  • 日期:2026-07-24
  • 关联 RFCQL-RFC-0001 D-06、D-34、D-105、D-123、D-124、D-125、D-127
  • 关联 ADRADR-0104、ADR-0105、ADR-0124、ADR-0125、ADR-0126、ADR-0127

背景

ADR-0125 已用 PostgreSQL 18.4 Docker fixture 证明物理流复制、 remote_apply、fence-before-promote、timeline 1→2、旧主 pg_rewind 只读重入,以及 scheduler、credential delivery、completion 和 cancellation 在不确定提交后的收敛。但测试专用 TCP endpoint 和 promotion guard 不是生产 operator,也没有定义 Kubernetes 中谁创建数据库、角色、证书与 primary service。

QingLong 不能在应用进程内复制数据库选主;同时也不能让 operator 通过 superuser 或应用启动钩子接管 QL3 schema GRANT。部署需要一条明确分界:

  • operator 管理 PostgreSQL 实例、复制、promotion、证书、Service、Database 和 LOGIN role 生命周期;
  • QingLong reviewed migration stream 管理 schema、table、capability 与对象权限;
  • Secret manager 管理密码和 runtime pepper
  • runtime、admin、worker-ingress 只消费各自最小权限身份。

决策

1. Cluster Profile 默认使用 CloudNativePG 1.30.0

生产 Cluster Profile 选择 CloudNativePG,而不是在 QingLong 中实现选主,也不把 Crunchy PGO 或 Zalando operator 同时引入默认发行物。原因是当前需求可以直接映射 到其稳定 read-write Service、Lease promotion gate、实例隔离、声明式 DatabaseRole、operator CA 和 pg_rewind 恢复路径;只保留一个 operator 可避免 三套 CRD、Secret 命名和故障语义进入支持矩阵。

operator 只属于 cluster-control 部署档位。edge、standalone 和普通 worker 产物不得依赖 Kubernetes client、CRD 或 operator 包;本决策不增加 workspace package 和 npm importer。

供应链锁记录:

  • CloudNativePG 1.30.0 ghcr.io/cloudnative-pg/cloudnative-pg:1.30.0@sha256:a2701eb97cdd2a34b1fdb2cb51987f544b706e40bec72ae7146cd8580efefebb
  • PostgreSQL 18.4-minimal-trixie ghcr.io/cloudnative-pg/postgresql:18.4-minimal-trixie@sha256:24d229d801663f95b584416f8ebdfad4849b1a3fa4cfcf95a7f026df7aa6e22d
  • 两个 index 均锁定已观察的 linux/amd64linux/arm64 子 manifest。

operator-lock.json 还记录 release manifest、Sigstore bundle 和 certificate identity。当前本地只核验了 OCI index/platform digest;尚未保存 release asset 下载、签名验证或真实 operator 安装记录,因此不能把 lock 文件解释为部署完成。

2. 生产数据库固定为三实例同步 HA

ql3-postgres Cluster 固定:

  • instances: 3required hostname anti-affinity
  • enableSuperuserAccess: false
  • synchronous_commit=remote_apply
  • synchronous ANY 1dataDurability: requiredfailoverQuorum: true
  • 只保留 primary-tracking ql3-postgres-rw 默认 Service,禁用 -r-ro
  • CPU、memory、data PVC 与 WAL PVC 都有显式请求/上限。

该配置优先保证已确认写入在一个同步副本 remote apply。代价是只剩一个可写实例且 没有合格同步副本时,mutation 可用性会停止;不得通过改成异步提交来“恢复健康”。 required anti-affinity 也意味着生产至少需要三个合格节点。单节点开发环境可以用 私有 overlay 放宽拓扑,但不能作为 HA 证据。

3. Operator 管理 LOGIN rolemigration 管理对象 GRANT

operator 声明且只声明十二个非特权 LOGIN role:

Role Connection limit Password Secret 用途
ql3_migration 2 ql3-postgres-migration-auth Database owner 与短生命周期 DDL
ql3_ai_maintenance 4 ql3-postgres-ai-maintenance-auth Prompt output retention/rekey 维护
ql3_ai_credential_manager 4 ql3-postgres-ai-credential-manager-auth AI Provider credential 管理事务
ql3_ai_credential_tester 2 ql3-postgres-ai-credential-tester-auth 一次性 Provider 连通性测试
ql3_runtime 32 ql3-postgres-runtime-auth cluster-control runtime
ql3_admin 4 ql3-postgres-admin-auth 短生命周期管理事务
ql3_package_manager 4 ql3-postgres-package-manager-auth Plugin Package 管理事务
ql3_package_executor 4 ql3-postgres-package-executor-auth Package 执行/恢复事务
ql3_automation_manager 4 ql3-postgres-automation-manager-auth Task/Trigger 管理事务
ql3_worker_credential_manager 4 ql3-postgres-worker-credential-manager-auth Worker credential 管理事务
ql3_worker_credential_executor 4 ql3-postgres-worker-credential-executor-auth Worker credential 执行事务
ql3_worker_ingress 32 ql3-postgres-worker-ingress-auth Worker ingress

十二者均为 LOGIN,且显式禁止 SUPERUSERCREATEDBCREATEROLEREPLICATIONBYPASSRLS;删除 CR 时 role reclaim policy 为 retain,防止 operator 删除声明时同时破坏仍被数据库对象引用的身份。qinglong Database 的 owner 固定为 ql3_migration

pg-0017-database-role-grants 将 PostgreSQL stream 推进到 17 条 migration、 control-core capability v16。它先复验四个 role 已存在且属性精确,再撤销 PUBLIC 对数据库/schema/table 的默认访问,并安装 runtime/admin/worker-ingress 所需的精确对象 GRANT。CI 和 HA fixture 只预创建 role 与 Database owner,不再 复制一份手工 GRANT。readiness 同时复验当前 role 可登录、无高权限且拥有 Database CONNECT,避免 operator 配置与 schema 权限静默漂移。

ADR-0137 的 pg-0018-plugin-package-installs 在上述 role-grant authority 上继续推进 到 18 条 migration、control-core capability v17、30 张表。Plugin Package installation 三表仍只授予 ql3_admin;单用途 Project lock function 固定由 ql3_migration 拥有、撤销 PUBLIC EXECUTE,并只给 admin 调用。runtime 与 worker-ingress 权限不因该能力扩大。

后续 ADR-0144、ADR-0242 与 ADR-0259 在同一 operator authority 中依次加入 Package manager/executor、Worker credential manager/executor、Automation manager 与三个 AI 专用身份;当前生产清单的唯一事实源是十二个非特权 LOGIN role、52 条 migration 与 control-core capability v51。新增 role 不改变本 ADR 的原则:operator 只管理 登录身份,所有对象 GRANT 仍由 reviewed migration stream 管理。

4. 应用不再复制含密码 DSN

CloudNativePG overlay 使用离散配置:

  • HOST=ql3-postgres-rw.qinglong3-system.svc
  • PORT=5432DATABASE=qinglong
  • USER/PASSWORD 分别读取对应 basic-auth Secret
  • QL3_POSTGRES_TLS_SERVERNAME 与 primary Service DNS 完全相同;
  • CA 从 operator 管理的 ql3-postgres-ca 只读投影。

runtime 与 migration 的 Secret、环境键和 CA mount 保持分离。兼容用 URL 仍可供 非 operator 部署使用,但 URL 与离散配置混用、部分离散凭据、URL ssl* override 以及非法 identifier 全部失败关闭。credential example 只含固定 username 与 占位符,且不进入 Kustomize resources。

5. 安装和激活有固定顺序

部署顺序为:

  1. 以 cluster-admin authority 安装并验证锁定的 CloudNativePG
  2. 创建 namespace 和由 Secret manager 生成的十二个 role Secret、control runtime Secret 与 Worker ingress Secret
  3. 应用 Cluster、DatabaseRole 和 Database
  4. 等待三个实例、-rw Service、十二个 role、Database 和 -ca Secret ready
  5. 创建固定名称的 one-shot migration Job,等待 migration_completed,随后删除或留给 TTL 清理;
  6. 才应用 cluster-control runtime overlay。

应用 readiness 不能替代 operator readinessoperator ready 也不能替代 QL3 schema/role readiness。重新运行 migration Job 前必须确认旧 Job 已删除。

备份、TLS 与故障边界

CloudNativePG 自动维护 server/client certificate 不等于完成 CA rollover 证明。 QL3 仍要求 ADR-0127 的 old → overlap → new → rollback contract,每阶段创建新 activation 并重跑可写主库/schema/role/recovery gate。真实 operator endpoint 上的 轮换尚未执行。

ADR-0130 已定义 Barman CNPG-I、私有 ObjectStore、连续 WAL、每日 base backup 与隔离恢复 Cluster 的静态合同,并锁定 Barman v0.13.0 candidate release、 controller/sidecar 及双平台 digestcertificate authority 供应链和真实对象存储 restore evidence 仍未完成。三副本和可渲染清单都不能冒充备份。基础设施 STONITH、Kubernetes control-plane 故障、Pod/节点网络分区、存储故障和 raw PostgreSQL response loss 仍是独立 Release Gate。

替代方案

  • QingLong 内建 Patroni/选主或轮询多个 host:拒绝。复制数据库控制面并扩大 split-brain 风险。
  • 默认同时支持多个 PostgreSQL operator:拒绝。3.0 首发会把 CRD、Secret、 Service、证书和升级矩阵成倍放大;其他 operator 后续只能通过独立 ADR/overlay 加入。
  • operator role 成为 superuser,由应用启动时自动 GRANT:拒绝。常驻进程会 获得 DDL/role authority,副本并发启动还会把 migration 变成隐式副作用。
  • 在一个 Secret 中保存 runtime、migration、admin 和 worker-ingress DSN 拒绝。会合并独立 authority,并在 URL 中复制用户名、密码、host 和 TLS 选择。
  • 单实例 operator 清单作为生产默认值:拒绝。它只能证明 CRD 可启动,不能 支撑 D-123 的 failover/RPO 声明。
  • 三副本等同于备份:拒绝。复制会同步删除和逻辑破坏,不能替代离线恢复点。

验证

  • pnpm audit:cloudnativepg:ql3
  • node --test test/back/ql3CloudNativePgDeploymentAudit.test.cjs
  • kubectl kustomize deploy/kubernetes/ql3-cluster/operators/cloudnative-pg
  • kubectl kustomize deploy/kubernetes/ql3-cluster/overlays/cloudnative-pg
  • kubectl kustomize deploy/kubernetes/ql3-cluster/operations/cloudnative-pg
  • pnpm --filter @qinglong/cluster-postgres test
  • pnpm --filter @qinglong/cluster-control test
  • pnpm test:postgres-ha:ql3
  • QL3_CLOUDNATIVEPG_LIVE=1 pnpm test:cloudnativepg-live:ql3

静态负向门必须拒绝单实例、未锁 digest、特权 role、错误 Database owner、把 credential example 加入 Kustomize、runtime/migration Secret 串用、重新引入 DSN、 非 -rw endpoint 或错误 CA。live contract 必须保存 operator/operand 实际 platform imageID、三实例跨 worker 调度、migration/runtime ready、主 worker 停止后的 Lease/timeline promotion、旧主回归和最小权限 role 复验;脚本和 CI 定义本身不构成成功证据。发布前还必须保存一次成功记录,并独立完成 CA 轮换/回退和备份恢复证据。