docs: 完善 v1alpha1 设计与运维合同
This commit is contained in:
+45
-21
@@ -17,7 +17,7 @@
|
||||
## 1. 背景
|
||||
|
||||
homelab 中的大部分应用共享一个运行在独立 VM 上的 PostgreSQL DBMS。应用需要各自
|
||||
独立的 database、owner role、login role 和密码,但不需要独立 PostgreSQL 实例。
|
||||
独立的 database、作为 owner 的 login role 和密码,但不需要独立 PostgreSQL 实例。
|
||||
目前这些资源依靠人工 SQL 和人工 Secret 管理,难以重复、审计和检测漂移。
|
||||
|
||||
本系统使用 Kubernetes CRD 作为声明式 API,持续协调外部 PostgreSQL 与 OpenBao:
|
||||
@@ -69,9 +69,10 @@ v1alpha1 不负责:
|
||||
| 对象 | 事实来源 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| 期望状态 | Kubernetes CR `spec` | 用户声明的合同 |
|
||||
| 最近观察结果 | Kubernetes CR `status` | 可以丢失并重建,不是外部事实来源 |
|
||||
| 最近观察结果与当前阶段 | Kubernetes CR `status` | 可以丢失并重建,不是外部事实来源 |
|
||||
| database/role/grant/extension | PostgreSQL catalog | 每轮 reconcile 必须重新读取 |
|
||||
| 受管资源所有权与协调阶段 | PostgreSQL controller registry | 与受管 DBMS 一起备份和恢复 |
|
||||
| 受管资源所有权与保留标记 | PostgreSQL controller registry | 与受管 DBMS 一起备份和恢复 |
|
||||
| controller 工作流阶段 | Kubernetes CR `status.phase` | 状态机 checkpoint;可由外部事实保守重建 |
|
||||
| 应用凭据 | OpenBao KV v2 | Kubernetes API 中不得出现明文 |
|
||||
| Kubernetes 凭据投射 | External Secrets Operator | ExternalSecret 由本 controller 管理 |
|
||||
| PostgreSQL 管理凭据 | OpenBao KV v2 | 由 `PostgreSQLInstance` 引用 |
|
||||
@@ -106,7 +107,7 @@ PostgreSQL 管理 role。应用或 GitOps 流程在获得 namespace RBAC 后管
|
||||
- 一个 database;
|
||||
- 一个同时作为 database owner、供应用使用的 `LOGIN` role;
|
||||
- 零个或多个 extension;
|
||||
- 一个 OpenBao KV v2 凭据位置。
|
||||
- 一个 OpenBao KV v2 凭据位置;
|
||||
- 一个同 namespace ExternalSecret 及其目标 Kubernetes Secret。
|
||||
|
||||
Tenant 的 namespace 用于 Kubernetes RBAC 和身份识别,不代表 PostgreSQL schema。
|
||||
@@ -233,19 +234,36 @@ label、trace、CR spec/status 或测试快照。
|
||||
|
||||
## 9. Reconcile 行为
|
||||
|
||||
系统采用最终一致性模型。Kubernetes、PostgreSQL 和 OpenBao 可以短暂处于不同阶段;
|
||||
controller 不尝试实现跨系统事务,而是通过 PostgreSQL 中持久化的协调阶段、幂等外部
|
||||
操作和每轮回读验证最终收敛。
|
||||
系统采用最终一致性模型。Kubernetes、PostgreSQL、OpenBao 和 ESO 可以短暂处于不同
|
||||
阶段;controller 不尝试实现跨系统事务,而是以 Kubernetes CR `status.phase` 作为
|
||||
工作流 checkpoint,通过幂等外部操作和每轮回读验证最终收敛。
|
||||
|
||||
每个 Tenant 的 registry 记录至少经历以下单向阶段:
|
||||
两个 CR 的状态机权威记录都在 `status.phase`。controller 根据 phase 选择下一项候选
|
||||
动作,但 phase 不能替代外部状态检查:执行前后仍须回读 PostgreSQL catalog、registry、
|
||||
OpenBao 和 Kubernetes/ESO。外部写入成功但 status 更新失败时,下一轮必须识别已完成
|
||||
事实并推进 phase,不得重复生成密码或报告虚假冲突。
|
||||
|
||||
status 丢失时,controller 必须从 registry 的所有权记录和各外部系统实际状态保守重建
|
||||
phase。若 status 被伪造或领先于实际状态,controller 必须纠正到安全阶段并补齐资源,
|
||||
不能跳过验证。registry 不保存或驱动协调 phase。
|
||||
|
||||
Instance phase 按当前 generation 表示连接与初始化进度:
|
||||
|
||||
```text
|
||||
Planned -> CredentialCreated -> RoleCreated -> DatabaseCreated
|
||||
-> ExternalSecretCreated -> CredentialProjected -> Ready
|
||||
Pending -> Validating -> InitializingRegistry -> Ready
|
||||
(any phase) --------------------------------> Deleting
|
||||
```
|
||||
|
||||
阶段用于恢复进度,但不能替代实际状态检查。controller 重启后必须同时检查 registry、
|
||||
PostgreSQL catalog 和 OpenBao,再决定继续、保持 Ready 或报告 Conflict。
|
||||
spec generation 改变后可以从 `Ready` 回到 `Validating`。Tenant phase 如下:
|
||||
|
||||
```text
|
||||
Pending -> Planned -> CredentialCreated -> RoleCreated -> DatabaseCreated
|
||||
-> ExternalSecretCreated -> CredentialProjected -> Ready -> Deleting
|
||||
```
|
||||
|
||||
失败不增加 `Failed` phase;phase 保留在无法推进的步骤,由 `Ready=False` 的 Reason 和
|
||||
message 表达 `Conflict`、认证失败或依赖不可用。Retain 删除完成后 CR 已不存在,因此
|
||||
没有持久的 `Retained` phase。
|
||||
|
||||
每轮 Tenant reconcile 必须按以下逻辑执行:
|
||||
|
||||
@@ -266,7 +284,8 @@ PostgreSQL catalog 和 OpenBao,再决定继续、保持 Ready 或报告 Confli
|
||||
要求:
|
||||
|
||||
- 所有步骤必须幂等;
|
||||
- 每个外部写入前必须先持久化足够的操作意图,写入后必须回读并推进 registry 阶段;
|
||||
- 每个外部写入前必须先在 CR status 持久化足够的操作意图,写入后必须回读并推进
|
||||
`status.phase`;
|
||||
- 暂时性网络、锁和依赖错误必须重试;
|
||||
- 输入错误、资源冲突和禁止操作不得忙循环重试,只在 generation 或依赖状态变化后
|
||||
重试;
|
||||
@@ -274,7 +293,7 @@ PostgreSQL catalog 和 OpenBao,再决定继续、保持 Ready 或报告 Confli
|
||||
- 用户从 `spec.extensions` 移除 extension 时不得执行卸载,必须报告该字段在 v1alpha1
|
||||
中只允许追加;
|
||||
- controller 重启不得影响已经签发的应用密码;
|
||||
- `status` 丢失后必须可以从 PostgreSQL 和 OpenBao 重建。
|
||||
- `status` 丢失后必须可以从 registry、PostgreSQL、OpenBao 和 Kubernetes/ESO 重建。
|
||||
|
||||
## 10. Condition 合同
|
||||
|
||||
@@ -363,8 +382,9 @@ v1alpha1 不接管现有 database 或 role,但必须提供可重复、可回
|
||||
11. 保留旧 database、role 和备份直到回滚窗口结束,再由管理员手工清理。
|
||||
|
||||
回滚时停止新应用写入、恢复原名称或连接配置,并重新使用旧凭据。迁移工具不得把旧
|
||||
密码、管理凭据或 dump 文件提交到 Git。真实命令、锁定方式和各现有应用验证项在实现
|
||||
首个可用版本前写入独立 `docs/migration.md` 并通过临时 PostgreSQL 实例演练。
|
||||
密码、管理凭据或 dump 文件提交到 Git。真实命令、锁定方式和各现有应用验证项见
|
||||
[`migration.md`](migration.md),并必须在实现首个可用版本前通过临时 PostgreSQL 实例
|
||||
演练。
|
||||
|
||||
## 13. 安全要求
|
||||
|
||||
@@ -382,7 +402,7 @@ v1alpha1 不接管现有 database 或 role,但必须提供可重复、可回
|
||||
7. controller 不得通过 shell 或 `psql` 子进程执行用户输入。
|
||||
8. 错误包装、结构化日志和 tracing 必须经过 Secret 泄露测试。
|
||||
|
||||
详细威胁模型和部署 policy 将在 `docs/security.md` 中定义。
|
||||
详细威胁模型和部署 policy 见 [`security.md`](security.md)。
|
||||
|
||||
## 14. 可观测性要求
|
||||
|
||||
@@ -425,6 +445,8 @@ v1alpha1 至少必须提供:
|
||||
URL。
|
||||
17. DNS 不可用时,使用输出的 `hostaddr` 可以连接 PostgreSQL;server 证书同时覆盖
|
||||
`host` 的 DNS SAN 和 `hostaddr` 的 IP SAN,两种连接目标均可通过 `verify-full`。
|
||||
18. 两个 CR 的 `status.phase` 都能反映当前协调步骤;清空 status 后可以从外部事实重建,
|
||||
且伪造或过期 phase 不会使 controller 跳过验证或外部操作。
|
||||
|
||||
单元测试验证纯决策逻辑,adapter 集成测试使用 Docker PostgreSQL/OpenBao,controller
|
||||
集成测试使用 envtest,完整网络路径使用 Kind E2E。
|
||||
@@ -445,8 +467,9 @@ v1alpha1 至少必须提供:
|
||||
bundle,不接触 CA 私钥。bundle 可以由 ConfigMap 或现有证书同步机制投射,不允许
|
||||
Tenant 或 Instance 选择其他 CA;开发环境可以显式使用 `sslMode: disable`。
|
||||
- 每个 PostgreSQLInstance 在其管理 database 中维护 controller 专用 registry schema。
|
||||
registry 是受管资源所有权和协调阶段的权威记录;Tenant status 只是观察缓存,
|
||||
Instance status 不聚合 Tenant 清单。
|
||||
registry 是受管资源所有权、安装身份和 Retain 后 unmanaged 标记的权威记录;两个
|
||||
CR 的 `status.phase` 是 controller 状态机的权威 checkpoint,Instance status 不聚合
|
||||
Tenant 清单。
|
||||
- PostgreSQL database 和 role identifier 必须匹配 `^[a-z][a-z0-9_]{0,62}$`,不支持
|
||||
需要双引号的大小写或特殊字符名称。
|
||||
- External Secrets Operator 是 v1alpha1 的运行依赖。controller 管理同 namespace
|
||||
@@ -458,7 +481,8 @@ v1alpha1 至少必须提供:
|
||||
## 17. 批准状态
|
||||
|
||||
具体设计决策和本文整体已于 2026-09-10 获得批准,可以进入 API reference、测试和
|
||||
实现阶段。
|
||||
实现阶段。同日确认状态机修订:两个 CR 的 `status.phase` 是 controller 工作流的权威
|
||||
checkpoint;PostgreSQL registry 只承担所有权、安装身份和保留状态。
|
||||
|
||||
## 18. 与当前脚手架的已知差异
|
||||
|
||||
@@ -471,7 +495,7 @@ v1alpha1 至少必须提供:
|
||||
- 删除独立 `ownerRole` 字段,使 login role 成为 database owner;
|
||||
- 为 Instance 增加 `hostaddr`,为 Tenant 增加目标 Secret 配置及凭据输出 status;
|
||||
- 按已确认的 identifier 合同收紧校验;
|
||||
- 增加 PostgreSQL controller registry,记录基于 UID 的所有权和最终一致性协调阶段;
|
||||
- 增加 PostgreSQL controller registry,记录基于 UID 的所有权、安装身份和保留状态;
|
||||
- 修正凭据 type 中遗留的 rotation 注释;
|
||||
- 使 Condition、不可变字段和 extension 追加语义具备 API 校验或明确的 reconcile
|
||||
结果。
|
||||
|
||||
Reference in New Issue
Block a user