mirror of
https://github.com/whyour/qinglong.git
synced 2026-09-22 19:02:22 +08:00
feat(ql3): establish 3.0 incubation baseline
This commit is contained in:
@@ -0,0 +1,191 @@
|
||||
# ADR-0129:CloudNativePG Operator 与数据库角色权威
|
||||
|
||||
- 状态:Accepted(operator/operand digest lock、三实例 HA 清单、十二角色
|
||||
DatabaseRole、独立 Database owner、runtime/migration 离散凭据、CA/主节点
|
||||
endpoint 绑定、静态负向门及显式 opt-in 的四节点 Kind/CNPG live contract
|
||||
已完成;成功的远端 live 记录、CA 轮换和备份恢复仍是 Release Gate)
|
||||
- 日期:2026-07-24
|
||||
- 关联 RFC:QL-RFC-0001 D-06、D-34、D-105、D-123、D-124、D-125、D-127
|
||||
- 关联 ADR:ADR-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/amd64` 和 `linux/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: 3`,required hostname anti-affinity;
|
||||
- `enableSuperuserAccess: false`;
|
||||
- `synchronous_commit=remote_apply`;
|
||||
- synchronous `ANY 1`、`dataDurability: required`、`failoverQuorum: 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 role,migration 管理对象 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`,且显式禁止 `SUPERUSER`、`CREATEDB`、`CREATEROLE`、
|
||||
`REPLICATION` 和 `BYPASSRLS`;删除 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=5432`、`DATABASE=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 readiness;operator 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 及双平台 digest;certificate 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
|
||||
轮换/回退和备份恢复证据。
|
||||
Reference in New Issue
Block a user