Compare commits
3
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb87316773
|
||
|
|
a0afbf992c
|
||
|
|
953878ac47
|
+19
-8
@@ -37,17 +37,22 @@ cluster-scoped,short name 为 `pginstance`。
|
||||
| `spec.endpoint.port` | int32 | `5432` | 1–65535 |
|
||||
| `spec.endpoint.database` | string | `postgres` | 管理连接 database;合法 PostgreSQL identifier |
|
||||
| `spec.endpoint.sslMode` | enum | `verify-full` | `disable`、`require`、`verify-ca`、`verify-full` |
|
||||
| `spec.adminCredentialRef.path` | string | 必填 | 部署级 KV mount 内的 mount-relative path |
|
||||
| `spec.adminCredentialRef.usernameKey` | string | `username` | OpenBao record 中的键名 |
|
||||
| `spec.adminCredentialRef.passwordKey` | string | `password` | OpenBao record 中的键名 |
|
||||
| `spec.adminCredentialRef.name` | string | 必填 | controller namespace 内的管理 Secret 名称 |
|
||||
| `spec.adminCredentialRef.usernameKey` | string | `username` | Secret data 中的键名 |
|
||||
| `spec.adminCredentialRef.passwordKey` | string | `password` | Secret data 中的键名 |
|
||||
| `spec.allowedExtensions` | set[string] | 空集合 | 合法 extension 名称的 allowlist |
|
||||
|
||||
`adminCredentialRef.path` 不以 `/` 开头,不含空段、`.`、`..`,也不包含 KV v2 API 的
|
||||
`data`/`metadata` 层。它只定位既有管理凭据;controller 不创建或修改该记录。
|
||||
`adminCredentialRef` 不接受 namespace 或 Bao path。管理 Secret 固定在 controller
|
||||
namespace,名称须合法,两个字段须存在且非空。管理员维护 ExternalSecret,由 ESO
|
||||
同步;controller 只读管理 Secret,不创建或修改它。此为 2026-09-13 批准的修订,
|
||||
现有 API types、生成 CRD 和 samples 尚未更新。
|
||||
|
||||
Instance endpoint、管理凭据引用和 allowlist 可以修改。修改后 controller 重新验证;
|
||||
删除 allowlist 项目不会自动从已有 Tenant database 删除 extension。
|
||||
|
||||
endpoint 由管理员负责,不校验变更前后是否同一物理服务器/registry,只重验新配置
|
||||
的连接与管理能力。新 UID 按新 Instance 处理,不授权接管旧 UID 的 Tenant 资源。
|
||||
|
||||
### Status
|
||||
|
||||
| JSON path | 类型 | 含义 |
|
||||
@@ -62,6 +67,9 @@ print columns:`Endpoint=.spec.endpoint.host`、`Phase`、`Ready`、`Age`。
|
||||
Instance `Ready=True` 要求管理凭据可读、TLS/认证成功、server metadata 可读、registry
|
||||
可访问且权限预检成功。它不代表数据库已经备份或高可用。
|
||||
|
||||
管理凭据从 Kubernetes Secret 装配;已有有效凭据可访问 PostgreSQL 时,Bao/ESO
|
||||
暂时不可用不单独撤销 Instance Ready。Tenant 凭据操作仍依赖 Bao。
|
||||
|
||||
## PostgreSQLTenant
|
||||
|
||||
namespaced,short name 为 `pgtenant`。
|
||||
@@ -142,8 +150,11 @@ phase 用于进度展示、恢复和排障。
|
||||
|
||||
- `Retain` 不需要等待外部依赖;删除 CR 后外部记录保留原 UID 并标记 unmanaged。
|
||||
- `Delete` 添加 finalizer,严格按规格的所有权验证和清理顺序执行;失败保持 finalizer。
|
||||
- controller 不为 `PostgreSQLInstance` 级联删除 Tenant 或外部资源;存在引用时 Instance
|
||||
删除应被 finalizer 阻止,直到 Tenant 被删除或管理员使用运维逃生流程。
|
||||
- Instance 开始受管时即添加并保存 finalizer;删除时停止新供应,存在 Tenant 引用
|
||||
(包括正在删除的 Tenant)就保留 finalizer,无引用才移除。引用查询失败时继续等待。
|
||||
不级联删除 Tenant 或外部资源;管理员可使用运维逃生流程。
|
||||
- finalizer 不禁止创建 Tenant CR;并发创建者遇到删除中或不存在的 Instance 不得
|
||||
开始供应。首版不增加跨对象锁或准入控制,不承诺跨对象原子删除。
|
||||
|
||||
## 示例
|
||||
|
||||
@@ -160,7 +171,7 @@ spec:
|
||||
database: postgres
|
||||
sslMode: verify-full
|
||||
adminCredentialRef:
|
||||
path: infrastructure/postgresql/shared/admin
|
||||
name: shared-postgresql-admin
|
||||
allowedExtensions: [pg_trgm]
|
||||
---
|
||||
apiVersion: database.ddupan.top/v1alpha1
|
||||
|
||||
@@ -35,9 +35,13 @@ controller 不运行 PostgreSQL/OpenBao,不管理 VM、存储、备份或 Open
|
||||
## 资源模型
|
||||
|
||||
`PostgreSQLInstance` 是 cluster-scoped,由平台管理员创建,描述外部 PostgreSQL 的
|
||||
DNS host、IP host address、端口、管理 database、TLS 模式、OpenBao 管理凭据引用和
|
||||
DNS host、IP host address、端口、管理 database、TLS 模式、管理 Secret 引用和
|
||||
extension allowlist。
|
||||
|
||||
管理连接使用管理员维护的 ExternalSecret 经 ESO 同步到 controller namespace 的
|
||||
Secret;Instance 只选择 Secret 名称与字段,controller 只读,不直接从 Bao 获取
|
||||
管理凭据。Tenant 凭据的创建、读取与销毁仍由 controller 直接访问 Bao。
|
||||
|
||||
`PostgreSQLTenant` 是 namespaced。一个 Tenant 对应一个 database、一个同时作为 owner
|
||||
的 login role、一组只允许追加的 extension、一个由 controller 推导的 OpenBao KV
|
||||
记录,以及同 namespace 的 ExternalSecret 和目标 Secret。
|
||||
|
||||
+12
-9
@@ -17,7 +17,9 @@
|
||||
3. 创建 PostgreSQL controller 管理 role 和管理 database 连接权限。
|
||||
4. 在 OpenBao KV v2 写入管理 role 凭据。
|
||||
5. 配置 OpenBao Kubernetes auth、controller policy 和面向 ESO 的读取 policy。
|
||||
6. 在 Kubernetes 安装 ESO,创建可读取租户路径的 `ClusterSecretStore`。
|
||||
6. 安装 ESO,配置独立的管理凭据同步身份和租户凭据读取身份。管理员在 controller
|
||||
namespace 创建管理 ExternalSecret,确认管理 Secret 已同步;另创建供租户使用的
|
||||
`ClusterSecretStore`。
|
||||
7. 创建公开 CA bundle ConfigMap,并挂载到 controller 和需要直接验证数据库的应用。
|
||||
8. 部署 controller,再创建 Instance;等待 Ready 后才创建 Tenant。
|
||||
|
||||
@@ -78,13 +80,12 @@ controller 权限。最终可执行 SQL grant 将随 PostgreSQL adapter 集成
|
||||
|
||||
## OpenBao 与 ESO
|
||||
|
||||
controller policy 分成两个范围:
|
||||
controller policy 仅允许在固定 tenant base path 下 create/read/update/delete KV v2
|
||||
data 和 metadata,Delete 必须能永久删除全部版本及 metadata;不读取管理凭据路径。
|
||||
|
||||
- 只读 Instance 管理凭据路径;
|
||||
- 在固定 tenant base path 下 create/read/update/delete KV v2 data 和 metadata,Delete
|
||||
必须能永久删除全部版本及 metadata。
|
||||
|
||||
ESO 使用独立身份,只需读取 tenant base path;它不应读取 PostgreSQL 管理凭据。
|
||||
管理凭据由管理员维护的 ExternalSecret 同步到 controller namespace;其 ESO 身份
|
||||
只读对应管理路径,不能供 Tenant 使用。租户 ESO 身份只读 tenant base path,不得
|
||||
读取 PostgreSQL 管理凭据。controller 不创建或修改管理 ExternalSecret/Secret。
|
||||
`ClusterSecretStore` 由平台管理员创建,controller 只引用,不创建或修改 Store。
|
||||
controller 创建的 ExternalSecret 与 Tenant 同 namespace,并设置 ownerReference;目标
|
||||
Secret 包含固定七键:`username`、`password`、`database`、`host`、`hostaddr`、`port`、
|
||||
@@ -97,8 +98,10 @@ Secret 包含固定七键:`username`、`password`、`database`、`host`、`hos
|
||||
对应 Secret 是否完成投射。
|
||||
- namespace 用户可以管理本 namespace Tenant,但不能管理 Instance、Store、controller
|
||||
配置或其他 namespace 的 ExternalSecret。
|
||||
- controller 无需读取目标 Secret 的 data;验证登录使用从 OpenBao 读取的应用凭据,
|
||||
对 Secret 只检查存在性和 ESO 状态。
|
||||
- controller 只在自身 namespace 读取所引用管理 Secret 的 data,不获得跨 namespace
|
||||
的管理 Secret 读取权限。Instance 不允许自选 Secret namespace。
|
||||
- 对应用目标 Secret,controller 无需读取 data;验证登录使用从 OpenBao 读取的应用
|
||||
凭据,只检查 Secret 存在性和 ESO 状态。
|
||||
|
||||
## 升级与回滚
|
||||
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
# Instance 领域对象规格
|
||||
|
||||
状态:Draft,含已确认决策。日期:2026-09-13。
|
||||
|
||||
上层边界见 [领域模型](domain-model.md)。本文只展开 Instance,不包含 Tenant 的供应
|
||||
实现,也不新增 CRD 字段。设计签名用于评审职责与行为,不是待复制的 Go 接口代码。
|
||||
|
||||
## 1. 对象职责与生命周期
|
||||
|
||||
Instance 表示一次登记的 PostgreSQL 管理对象,是聚合根。它负责字段与策略校验、
|
||||
根据观察结果判断能力是否满足要求、保护状态转换规则;不登录数据库,不读取 Bao,
|
||||
不查询权限或初始化 registry。
|
||||
|
||||
本草案选择:**领域对象只接收数据并做业务决策,不直接或通过端口、回调访问外部。**
|
||||
应用层调用适配器获取事实、执行被允许的操作,并将观察结果交回对象。Instance 不接收
|
||||
context、客户端或 IO 接口。领域行为不是公共 SetReady:调用方提供事实,不能指定结论。
|
||||
|
||||
每轮从 CR 重建一个 Instance;对象不跨 reconcile 缓存,也不是线程共享单例。
|
||||
管理连接可由装配层跨轮次复用,但连接复用不代表上次能力验证仍然成立。
|
||||
|
||||
身份与 endpoint 以管理员声明为准。改变 endpoint 不验证是否同一物理服务器或
|
||||
registry,不增加安装身份连续性检查;只使旧观察失效,按新配置重验管理能力。
|
||||
新 CR 是新 Instance,不自动获得旧 UID 资源的所有权,也不迁移或清理旧目标。
|
||||
下文“观察绑定匹配”仅指结果属于本轮身份/配置,不是物理服务器身份认证协议。
|
||||
|
||||
## 2. 字段与值对象
|
||||
|
||||
所有可变状态封装在对象内部。构造后身份和本轮 definition 不可变;配置变更通过
|
||||
下一轮装载新的 definition 处理,不提供任意 SetPhase/SetReady/SetEndpoint。
|
||||
|
||||
| 字段 | 类型与内容 | 来源/持久化 | 修改规则 |
|
||||
| --- | --- | --- | --- |
|
||||
| identity | InstanceIdentity:UID、name | CR metadata | 本次对象身份内不可变;同名新 UID 是新对象 |
|
||||
| revision | 正整数,期望配置版本 | metadata.generation | 本轮不可变;不是物理服务器版本 |
|
||||
| definition.endpoint | Endpoint:host、hostaddr、port、managementDatabase、tlsMode | CR spec | 本轮不可变;新配置重验 |
|
||||
| definition.adminCredential | CredentialReference:name、usernameKey、passwordKey | CR spec | 只引用 controller namespace 的管理 Secret,不存明文 |
|
||||
| definition.allowedExtensions | 去重的 ExtensionName 集合 | CR spec | 本轮不可变;不因 allowlist 缩小卸载扩展 |
|
||||
| checkpoint | Pending/Validating/InitializingRegistry/Ready/Deleting | CR status.phase | 只能由领域动作变更,应用层负责持久化 |
|
||||
| observedRevision | 最近完成有结论协调的版本 | CR status.observedGeneration | 成功或已知失败时更新,单纯记录意图不更新 |
|
||||
| readiness | Unknown/Ready/NotReady,加安全失败类别和操作说明 | 由 status Ready Condition 重建,结果再映射回 Condition | 方法更新;不是第二套持久化状态 |
|
||||
| reportedVersion | 可选服务器版本字符串 | status.postgresqlVersion;验证后从服务器更新 | 仅供展示,不能证明连接成功 |
|
||||
| deleting | 是否已请求删除 | metadata.deletionTimestamp 映射 | 本轮不可变;优先于其他动作 |
|
||||
| evidence | 可选 CapabilityEvidence | 本轮外部回读;不新增 status 字段 | 重建时始终为空,不能从 Ready Condition 伪造 |
|
||||
|
||||
Endpoint 的构造约束沿用 API:非空 host、合法 IP、1–65535 端口、合法 PostgreSQL
|
||||
identifier、显式 TLS mode,禁止隐式降级。CredentialReference 包含合法 Secret 名称
|
||||
及非空字段名,不包含 namespace 或 Bao path;namespace 由应用层固定为 controller
|
||||
自身 namespace。这里校验领域值,不在对象里校验整个 controller 部署配置。
|
||||
|
||||
CapabilityEvidence 包含本轮目标绑定(Instance UID、revision、endpoint、凭据引用)、
|
||||
server version、管理能力检查结果、registry 观察结果。registry 结果区分
|
||||
Absent/NeedsMigration/Usable;连接失败不能当作 Absent。它不包含密码、token 或 DSN。
|
||||
|
||||
管理能力要求来自规格中的 role/database/grant/extension 操作,不等价于“能执行
|
||||
SHOW server_version”。具体权限探测矩阵需在 PostgreSQL 适配器规格中定义,不能
|
||||
让一个没有定义检查内容的布尔值承担验收。
|
||||
|
||||
不属于 Instance 的字段:Tenant 清单、客户端、连接池、token TTL、CA 文件句柄、
|
||||
Kubernetes resourceVersion。resourceVersion 留在应用层作为乐观并发保存的前提。
|
||||
|
||||
## 3. 设计签名
|
||||
|
||||
```text
|
||||
Reconstitute(identity, revision, definition, checkpointSnapshot, deleting)
|
||||
-> Instance | InvalidDefinition
|
||||
|
||||
Instance.BeginValidation() -> Outcome
|
||||
Instance.AssessManagement(observation: CapabilityObservation) -> Outcome
|
||||
Instance.PlanRegistryPreparation(observation: CapabilityObservation)
|
||||
-> AlreadyUsable | PreparationAllowed | PreparationDenied
|
||||
Instance.AssessRegistryResult(result: RegistryPreparationResult) -> Outcome
|
||||
Instance.AssessReadiness(observation: CapabilityObservation) -> Outcome
|
||||
Instance.CheckExtensions(requested: ExtensionSet) -> Accepted | ExtensionsDenied
|
||||
Instance.RequireProvisioningReady() -> Accepted | InstanceNotReady
|
||||
Instance.BeginDeletion() -> Outcome
|
||||
Instance.Snapshot() -> InstanceSnapshot
|
||||
```
|
||||
|
||||
Outcome 是正常推进、已知失败或方法前提不成立,不包含重试秒数、Kubernetes patch
|
||||
或原始驱动错误。InstanceSnapshot 只包含 checkpoint、observedRevision、readiness、
|
||||
reportedVersion,不能序列化 evidence。快照与集合访问返回值副本。
|
||||
|
||||
CapabilityObservation 是不可变的事实输入:目标绑定、服务器版本、管理能力检查项和
|
||||
registry 观察结果;各检查项区分成功、失败、未观察,未观察不视为成功。失败只含安全
|
||||
类别,不含驱动异常或凭据。对象校验目标绑定与当前身份/配置一致,拒绝不匹配输入,
|
||||
不改变状态;完整性不足不能产生 Ready。观察结果由应用层收集,对象不能自行证明
|
||||
这些事实的真实性或实时性;采集来源、同轮次关联和并发检查由应用层保证。
|
||||
|
||||
RegistryPreparationResult 为操作失败(目标绑定、安全失败类别)或操作后的完整回读
|
||||
观察。单独的“迁移调用成功”不是就绪证据。CapabilityEvidence 是对象接受并判定满足
|
||||
要求的观察值,不是调用方传入的 Ready 布尔值。
|
||||
|
||||
### 构造与恢复
|
||||
|
||||
Reconstitute 校验期望 definition;无效输入不构造一个可参与用例决策的 Instance。
|
||||
入口把 InvalidDefinition 映射成 InvalidSpec,不必为了报告坏 CR 而制造非法领域对象。
|
||||
checkpoint 缺失或未知时保守使用 Pending;reportedVersion 和 Ready 都只是旧观察,
|
||||
evidence 为空。若 observedRevision 与 revision 不一致,旧 Ready 不得通过供应检查。
|
||||
|
||||
### 方法合同
|
||||
|
||||
| 方法 | 前置条件/输入 | 行为与状态变化 | 失败语义 |
|
||||
| --- | --- | --- | --- |
|
||||
| BeginValidation | 未删除;初次登记、配置变更或需重建 checkpoint | 转 Validating,readiness=Unknown,清空 evidence;不做外部 IO,不推进 observedRevision | deleting 时不启动验证 |
|
||||
| AssessManagement | 未删除;Validating;目标匹配的观察 | 判定管理访问、metadata、权限是否满足;registry 可用或可安全准备时转 InitializingRegistry,仍为 Unknown;不执行探测 | 失败保持 Validating,NotReady,observedRevision=当前版本 |
|
||||
| PlanRegistryPreparation | 未删除;InitializingRegistry;本轮前置观察 | 根据管理能力及 registry 现状决定无需写入、允许准备或禁止准备;返回决策,不执行迁移、不标 Ready | 访问失败、不兼容或证据不足时禁止写入,NotReady;保持阶段,更新 observedRevision |
|
||||
| AssessRegistryResult | 未删除;InitializingRegistry;准备结果或无需写入时的完整回读 | 按全部就绪条件判断回读结果;全满足才 Ready,并更新 observedRevision/version/evidence | 操作失败或回读不满足时保持 InitializingRegistry、NotReady;不得提前 Ready |
|
||||
| AssessReadiness | 未删除;Ready;本轮观察 | 配置版本不一致时仅 BeginValidation;否则根据全部观察判断是否仍满足就绪条件 | 访问失败转 Validating/NotReady;registry 缺失或需迁移时转 InitializingRegistry,保存后下一轮修复 |
|
||||
| CheckExtensions | 一组规范化 extension 名称 | 检查请求是否为当前 allowlist 子集,返回不允许的名称;无 IO、无状态修改 | ExtensionsDenied;不卸载已存在 extension |
|
||||
| RequireProvisioningReady | 供 Tenant 用例使用 | 要求未删除、Ready、observedRevision 匹配,并有本次调用链的新鲜完整 evidence | 不满足即 InstanceNotReady;持久化 Ready 本身不构成授权 |
|
||||
| BeginDeletion | deleting=true | 转 Deleting,清除供应能力,Unknown;不执行任何数据库或凭据删除 | 引用检查/finalizer 处理失败不得恢复成可供应 |
|
||||
| Snapshot | 任意合法对象状态 | 返回可安全持久化的结果值 | 不触发 IO,也不改变状态 |
|
||||
|
||||
领域方法只检查对象状态,不知道 checkpoint 是否已落盘。“已持久化 checkpoint”是
|
||||
应用用例执行外部写入的前提。内存字段变成 InitializingRegistry 不代表已保存成功;不能
|
||||
在同一轮无条件接着执行迁移。通过用例测试验证此约束,而不是伪造一个内存事务。
|
||||
|
||||
AssessManagement 成功只是中间步骤,observedRevision 不前移;完成就绪判定或
|
||||
明确失败才产生相应有结论结果。旧版本字符串可供诊断,但失败会清空 evidence。
|
||||
|
||||
Instance 不在本轮暴露 CreateDatabase/DeleteDatabase:Tenant 的供应/销毁授权来自
|
||||
Tenant 和 OwnershipClaim,不是从 Instance.Ready 推导。数据库执行能力如何承接
|
||||
已授权动作,留到 Tenant 对象规格,不在这里设计第二个万能 service。
|
||||
|
||||
## 4. 应用层与外部访问边界
|
||||
|
||||
```text
|
||||
应用层依赖的适配器能力(不传入 Instance):
|
||||
InspectManagement(context, target) -> ManagementObservation | AccessFailure
|
||||
InspectRegistry(context, target) -> RegistryObservation | AccessFailure
|
||||
EnsureRegistry(context, target) -> Completed | AccessFailure
|
||||
```
|
||||
|
||||
应用层在 IO 前绑定目标并关联结果,领域对象在接受观察时检查身份和配置匹配;旧
|
||||
endpoint 的成功结果不得用于新 endpoint。Inspect 是只读;EnsureRegistry 是幂等初始化/迁移,
|
||||
不能顺带建立 Tenant 数据库或接管未知 schema。Completed 不足以推进 Ready,必须回读。
|
||||
|
||||
适配器由装配层绑定管理连接;Secret 读取与连接池释放留在该边界之后,Instance
|
||||
管理连接不涉及 Bao token。适配器不得把基础设施异常转换成 Ready。失败区分依赖不可用、
|
||||
认证失败、权限不足和 registry 不兼容;不兼容属于不可安全继续,不自动覆写。
|
||||
registry 不兼容的具体 Condition 映射须在接口规格中确定,不能统一误报权限不足。
|
||||
|
||||
管理连接由应用层从 controller namespace 的 Secret 装配;管理员维护 ExternalSecret,
|
||||
ESO 负责同步。Instance 路径不直接访问 Bao,也不以 Bao/ESO 当前可用性作为就绪条件。
|
||||
首次装配缺少有效 Secret 时失败;已有凭据可正常访问 PG 时继续按 PG 能力判定。
|
||||
检测到所引用 Secret 的有效用户名或密码变化时,应用/基础设施层使用新值重建连接池
|
||||
并重新采集管理能力观察;metadata 或无关字段变化不重建。不要求 Instance generation
|
||||
变化,也不能复用旧连接的成功观察来证明新凭据有效。Secret 变化监听、连接释放和
|
||||
刷新均不进入领域对象;应用层保证旧连接观察不混入刷新后的调用链。
|
||||
controller 不修改 PostgreSQL 密码、不回写 Secret 或 Bao 管理凭据。
|
||||
|
||||
## 5. 状态转换与初始化走查
|
||||
|
||||
```text
|
||||
Pending --BeginValidation/保存--> Validating
|
||||
Validating --AssessManagement(观察)/保存--> InitializingRegistry
|
||||
InitializingRegistry --AssessRegistryResult(回读结果)/保存--> Ready
|
||||
Ready --配置变化或访问失败/保存--> Validating
|
||||
Ready --registry 需修复/保存--> InitializingRegistry
|
||||
任意阶段 --删除请求/保存--> Deleting
|
||||
```
|
||||
|
||||
1. 入口读取 CR,装配 definition、checkpointSnapshot;客户端不注入领域对象。
|
||||
2. 应用层按 checkpoint 协调用例;首次调用 BeginValidation,没有 IO。
|
||||
3. 保存 Validating。若保存失败,结束本轮,不执行 registry 写入。
|
||||
4. 下一轮应用层调用适配器探测实例,将观察交给 AssessManagement;领域判定通过后
|
||||
保存 InitializingRegistry,保存失败则停止,不进行迁移。
|
||||
5. 再下一轮应用层采集前置观察,调用 PlanRegistryPreparation。仅在意图已持久化且
|
||||
领域允许时调用 EnsureRegistry;AlreadyUsable 则跳过写入,PreparationDenied 则
|
||||
保存失败结果并停止。允许的操作完成后回读,交给 AssessRegistryResult 决定能否
|
||||
Ready;操作失败也用安全结果交回,不在应用层直接修改 phase。
|
||||
6. 入口用原 resourceVersion 前提保存快照;并发变更导致冲突时重新装载,不覆盖新状态。
|
||||
7. 后续 Ready 检查先由应用层探测,再调用 AssessReadiness;Tenant 用例同样获取当前事实,不能
|
||||
仅凭另一个 CR 的 Ready Condition 永久缓存授权。实际资源写入仍须处理并发变化。
|
||||
|
||||
阶段调度和外部操作顺序在应用层;“观察是否满足业务要求、是否允许准备 registry、
|
||||
哪些结果算完成、失败退到哪里”在 Instance 方法内。controller 不重复这些规则,
|
||||
也不直接把 phase 设置成 Ready。领域允许操作并不锁住外部世界,适配器仍须保障幂等
|
||||
和并发安全;禁止把旧观察当成永久授权。
|
||||
|
||||
## 6. 不变量与恢复验收
|
||||
|
||||
- UID 不随名称复用;不同 UID 的 evidence/结果不可互用。
|
||||
- 未完成当前配置的能力回读,不能新产生 Ready,也不能通过供应检查。
|
||||
- checkpoint 可以落后或被伪造;每次初始化/供应前都核对事实。status 清空只需重新
|
||||
验证和幂等准备,不删除 registry,更不能重新生成 Tenant 密码。
|
||||
- 迁移成功而 status 保存失败:重试回读已存在 registry,安全完成,不重复破坏性写入。
|
||||
- registry 在 Ready 后消失:下一次回读撤销 Ready,保存修复意图后才能重新准备。
|
||||
- 外部 IO 超时:产生安全失败结果;保存 status 使用仍有效的外层上下文,不能复用
|
||||
已超时的 IO 上下文而丢失失败状态。
|
||||
- 已请求删除的 Instance 不允许新供应;BeginDeletion 不删除 PostgreSQL、Tenant 或
|
||||
Bao。应用层在开始受管时添加并保存 finalizer,而非出现 Tenant 后再添加。
|
||||
删除时查询所有引用它的 Tenant(含删除中的对象);有引用或查询失败就保留
|
||||
finalizer,确认无引用才移除。引用查询、finalizer 写入和本地连接释放均不属于
|
||||
领域 IO,Instance 只根据删除请求禁用供应能力。
|
||||
- 首版不为 Instance 删除增加跨对象锁或准入控制。并发创建的 Tenant CR 不被
|
||||
finalizer 拦截,但遇到删除中/不存在的 Instance 不得开始供应;不承诺取消
|
||||
已在途的外部操作,也不声称引用查询与移除 finalizer 是跨对象原子事务。
|
||||
- CheckExtensions 失败不能产生任何外部写入;修改 allowlist 不会自行卸载扩展。
|
||||
- Snapshot、错误、日志和领域对象格式化不输出明文凭据或 token。
|
||||
- 领域测试只提供观察值,无需数据库、网络、context 或 IO mock;相同状态和输入
|
||||
得到相同决策。缺少检查项、目标不匹配和旧配置结果不得产生 Ready。
|
||||
|
||||
上述每条都对应领域或用例测试;真实权限检查、迁移与并发保障由适配器集成测试
|
||||
验证。本文为设计文档,未执行或宣称通过这些测试。
|
||||
|
||||
## 7. 本轮待评审与后续阻塞项
|
||||
|
||||
本轮请先确认字段归属、应用层采集事实/Instance 纯决策的分工、方法与状态转换合同。
|
||||
管理 Secret 来源、Bao 故障不单独撤销 Instance Ready,以及管理用户名/密码变化时
|
||||
重建连接池,以及管理员声明的 Instance 身份/endpoint 和简化 finalizer 删除规则
|
||||
均已确认。其他决策及未决项见总体草案,不增加后台清扫器或状态字段。
|
||||
|
||||
批准本对象结构不等于批准这些未决行为,也不意味着立刻实现完整供应链路。
|
||||
@@ -0,0 +1,149 @@
|
||||
# 领域模型设计草案
|
||||
|
||||
状态:Draft,含已确认决策。日期:2026-09-13。
|
||||
|
||||
本文定义领域职责、身份与一致性边界,并用对象规格细化字段和方法合同;方法使用
|
||||
设计签名,不固定 Go 目录、SDK 或框架,也不批准实现。外部行为以
|
||||
[系统规格](specification.md) 为准;下列未决问题不能由实现自行决定。
|
||||
PR #6 的代码和已有 registry 表结构是可评估的实现素材,不反向决定领域模型。
|
||||
|
||||
## 1. 领域与统一语言
|
||||
|
||||
本系统的领域是“在共享 PostgreSQL 上供应并管理应用租户”,不是数据库服务器运维。
|
||||
v1alpha1 先采用一个限界上下文,不把 PostgreSQL、Bao、Kubernetes 各自当成业务上下文。
|
||||
|
||||
| 术语 | 含义 | 不是什么 |
|
||||
| --- | --- | --- |
|
||||
| Instance | 平台登记的外部 PostgreSQL 管理对象及其供应策略 | 连接池、VM 或 controller 单例 |
|
||||
| Tenant | 一个应用的数据库使用合同及受管资源生命周期 | PostgreSQL database 的别名 |
|
||||
| Database | 租户数据库的名称、owner、扩展等期望描述与实际观察 | 包含 Bao 登录与连接关闭的操作接口 |
|
||||
| LoginRole | 同时作为 database owner 和应用登录身份的角色 | 额外的 NOLOGIN owner |
|
||||
| OwnershipClaim | 某个 Tenant 身份对一组资源名称与凭据位置的所有权声明 | 工作流阶段或仅凭名称推断的归属 |
|
||||
| CredentialLocation | 固定推导的凭据位置及所有权关联 | 密码本身或用户可任意选择的 KV path |
|
||||
| CredentialProjection | 把既定凭据交付到目标 Secret 的要求与观察结果 | controller 直接写入明文 Secret |
|
||||
|
||||
UID 表示一次 Kubernetes 对象身份;namespace/name 用于定位,不足以证明归属。
|
||||
database OID 是诊断观察值,不充当本系统的租户身份。
|
||||
|
||||
## 2. 候选聚合边界
|
||||
|
||||
### Instance:实例能力与供应策略
|
||||
|
||||
Instance 是候选聚合根,持有自身身份、endpoint、管理凭据引用、extension allowlist,
|
||||
以及用于判断当前能力的观察结果。它不持有所有 Tenant 对象的集合。
|
||||
|
||||
其行为包括:
|
||||
|
||||
- 判断租户申请是否符合本实例的 extension 策略。
|
||||
- 根据管理连接、服务器信息、registry 和权限检查结果判断是否具备供应能力。
|
||||
- 判断配置变化使哪些能力观察过期,禁止以旧 generation 的 Ready 证明新配置可用。
|
||||
- 在 registry 初始化完成并回读验证后,接受新的就绪结果。
|
||||
|
||||
“探测实例”“准备管理 registry”是应用用例协调的外部操作,不是 Instance 的 IO 方法。
|
||||
领域对象只接收观察值,负责前提、规则和状态决策;应用层调用适配器获取事实与执行
|
||||
获准操作。领域对象不持有或调用外部访问端口、客户端或回调。具体选择见
|
||||
[Instance 字段与行为](domain-instance.md),仍处于待评审状态。
|
||||
|
||||
### Tenant:供应合同与资源生命周期
|
||||
|
||||
Tenant 是另一个候选聚合根,通过身份引用 Instance,而不是 Instance 的聚合成员。
|
||||
操作一个 Tenant 不应要求装载、锁定或保存整个实例的租户集合。
|
||||
|
||||
Tenant 持有有效的 database/role 名称、请求的扩展、凭据交付目标、删除策略,以及
|
||||
已建立的资源绑定。它负责:
|
||||
|
||||
- 检查绑定后的不可变字段、extension 只追加规则。
|
||||
- 判断外部部分状态属于本 Tenant、尚不存在,还是与未知资源冲突。
|
||||
- 决定是否允许继续供应、何时达到 Ready、是否允许释放受管资源。
|
||||
- 按 Retain/Delete 合同限制行为,禁止把保留资源自动认领给同名新 UID。
|
||||
|
||||
Database、LoginRole 和 CredentialProjection 暂不设独立聚合根或独立 CRUD 用例。
|
||||
它们可作为 Tenant 内的资源描述与观察值;有规则才增加行为,不为了“充血”添加方法。
|
||||
真实 PostgreSQL database/role 的存在不意味着内存中必须各有一个有身份的实体。
|
||||
|
||||
聚合边界是业务规则的保护边界,不表示 Tenant 对应的 PostgreSQL、Bao、ESO 资源
|
||||
能够一次事务提交。跨系统供应必须允许部分完成。
|
||||
|
||||
### OwnershipClaim:跨租户唯一性与持久证据
|
||||
|
||||
名称唯一性不可能只靠某个 Tenant 的内存检查保证。需要一项领域能力,在持久化边界
|
||||
原子认领资源;已有 registry 是其适配器候选,仍需结合 catalog 和 Bao metadata 检查。
|
||||
|
||||
Claim 与 Tenant 关联,但不随 Tenant CR 消失:Retain 后证据必须继续存在。因此不能
|
||||
把它仅视为 CR 的附属 status。是否作为独立的小聚合,先以“可独立持久化、保留并保护
|
||||
归属不变量的声明”建模;不因此引入新的 CRD。
|
||||
|
||||
- 同一身份、同一绑定的重复认领可以成功;不同 UID 或不同绑定不能覆盖。
|
||||
- Claim 预留名称不等于证明同名外部资源由本 controller 创建。
|
||||
- 实际写入仍须核对所有权,不能把先查后建当成并发安全保证。
|
||||
- 当前 registry 的数据库事务不能覆盖 Bao;跨实例的凭据路径竞争也不能靠单个
|
||||
registry 的唯一约束解决。写入前提与条件创建协议需单独设计和验收。
|
||||
|
||||
## 3. 领域、用例与适配器的分工
|
||||
|
||||
| 层 | 承担的职责 | 禁止承揽的职责 |
|
||||
| --- | --- | --- |
|
||||
| 领域对象/策略 | 身份、有效合同、归属判断、允许的动作、完成条件 | 外部 IO(包括通过接口间接调用)、解析 CLI、生成 Kubernetes Condition |
|
||||
| 应用用例 | 装载模型与事实、持久化意图、调用能力、回读、提交结果 | 另写一套绕过领域规则的判断流程 |
|
||||
| controller 入口 | CR 映射、调度、watch、重试、status/finalizer 写入 | 在 reconcile 中重新定义业务规则 |
|
||||
| 基础设施适配器 | PostgreSQL、registry、Bao、ESO 的实际读写与并发保障 | 自行决定接管、改密码或扩大删除范围 |
|
||||
| 启动装配 | 校验部署配置,创建共享客户端、连接管理器及用例依赖 | 把连接生命周期当成 Instance 的业务状态 |
|
||||
|
||||
领域可使用独立的身份、endpoint、identifier、extension 集合等值对象,不依赖 CRD
|
||||
类型、pgx pool 或 Bao SDK。Kubernetes 对象的存取与 registry 的存取不是一个通用
|
||||
`Save(Tenant)` 可以原子完成的事情;不虚构跨系统 Unit of Work。
|
||||
|
||||
暂不引入事件总线、事件溯源、通用聚合框架或全套 Repository CRUD。领域建模的依据
|
||||
是业务规则,而不是接口和目录数量。
|
||||
|
||||
## 4. 状态与恢复
|
||||
|
||||
CR `status.phase` 仍是已批准的工作流 checkpoint,不在内存对象或 registry 再建一套
|
||||
权威 phase。领域对象可以由 CR 的期望状态、checkpoint 和外部观察重新构造。
|
||||
|
||||
phase 只决定候选步骤,外部证据决定该步骤是否允许执行、是否已经完成。应用层在
|
||||
写操作前保存意图,调用幂等操作后回读,再保存下一 checkpoint。status 写入失败时,
|
||||
下次从外部事实识别完成结果;不能重发密码,也不能相信伪造的 Ready。
|
||||
|
||||
业务失败区分 InvalidSpec、ImmutableField、Conflict 等;依赖故障由适配器转换成
|
||||
安全的能力失败,应用层决定重试并映射 Condition。凭据不进入模型序列化、status、
|
||||
事件或错误明细;只能在实际需要它的执行边界短暂传递。
|
||||
|
||||
## 5. 用例走查与验收方向
|
||||
|
||||
| 场景 | 领域判定 | 应用与适配器执行/恢复 |
|
||||
| --- | --- | --- |
|
||||
| 登记 Instance | 当前配置的能力要求是否满足 | 读取管理凭据,验证连接与权限,准备并回读 registry;完成后才 Ready |
|
||||
| 供应 Tenant | Instance 策略、绑定与归属允许供应 | 保存意图,认领资源,先写并回读 Bao 凭据,再创建 role/database,登录验证和 ESO 投射 |
|
||||
| Bao 写入后进程中断 | 同一身份的部分状态可继续 | 回读原凭据继续,不生成第二份密码 |
|
||||
| 两个 Tenant 竞争名称 | 只有匹配所有权的一方可继续 | 持久化认领和条件写入裁决竞争,失败方 Conflict,不覆盖资源 |
|
||||
| Delete 中断 | 已消失资源可视为完成;剩余资源仍须归属正确 | 按规格顺序继续删除,全部回读不存在后才清 registry 和 finalizer |
|
||||
| Retain 后同名 CR 重建 | 新 UID 不等于原所有者 | Conflict,不恢复管理、不改密码 |
|
||||
|
||||
领域测试验证规则与决策;adapter 测试验证锁、条件写入、SQL 与协议行为;controller
|
||||
测试验证 checkpoint 持久化和重启恢复;E2E 验证最终合同。不能只验证一串 mock 调用
|
||||
就声称实现了最终一致性。
|
||||
|
||||
## 6. 决策记录与待细化边界
|
||||
|
||||
1. **Instance 身份与物理目标(已确认)**:以管理员声明为准,endpoint 变更不验证
|
||||
物理服务器/registry 连续性,不增加安装身份绑定检查;旧观察失效,重验新配置
|
||||
的连接与管理能力。新 CR 视为新 Instance,不自动接管旧 UID 资源或迁移数据。
|
||||
2. **Retain 完成条件**:外部依赖不可用不能永久阻止 CR 删除,但 registry 又需标记
|
||||
unmanaged。需定义 CR 消失后的补偿/清扫入口及所需身份依据,不能承诺同时原子
|
||||
完成两者,也不能在没有回读时声称已写入保留标记。
|
||||
3. **管理凭据来源与 Ready(已确认)**:Instance 引用 controller namespace 内的
|
||||
管理 Secret 名称和字段;管理员维护 ExternalSecret,ESO 同步。controller 不直接
|
||||
从 Bao 读取管理凭据。已有凭据仍可访问 PG 时,Bao/ESO 故障不撤销 Instance Ready;
|
||||
首次装配无有效 Secret 则失败。Secret 的有效用户名/密码变化时重建管理连接池并
|
||||
重验,不因无关字段变化重建;controller 不修改 PG 密码,不回写 Secret 或 Bao。
|
||||
4. **绑定时机**:系统规格写“首次成功后不可变”,API 文档写“首次创建外部状态后
|
||||
不可变”。应明确绑定在认领、首次外部写入还是 Ready 时固定,及如何在 status 丢失
|
||||
后恢复;否则供应中途改名称可能产生无人管理的资源。
|
||||
|
||||
5. **Instance 删除(已确认)**:开始受管即添加 finalizer;删除期间停止新供应,
|
||||
有 Tenant 引用就等待,无引用才解除,不级联删除外部资源。首版采用 finalizer
|
||||
与引用检查,不引入跨对象锁/准入控制;不保证并发创建与删除的原子性。
|
||||
|
||||
Tenant 的 Retain 等待决行为留到 Tenant 设计,不属于本轮 Instance 设计范围。
|
||||
相关用例在决策批准前不进入实现,不同时实现整套模型。
|
||||
+6
-3
@@ -24,7 +24,8 @@ VM/磁盘备份会包含 PostgreSQL registry 和租户数据,但不应包含 O
|
||||
## 凭据处理
|
||||
|
||||
- controller 使用 Kubernetes auth 获取短期 OpenBao token,不配置长期静态 token。
|
||||
- 管理凭据只从 Instance 引用读取,不复制到 CR/status/Event/metric/trace。
|
||||
- 管理凭据只从 Instance 引用的 controller namespace Secret 读取,不复制到
|
||||
CR/status/Event/metric/trace;管理员维护 ExternalSecret,由 ESO 同步该 Secret。
|
||||
- 租户密码使用密码学安全随机源生成一次;中断恢复必须复用 OpenBao 现值。
|
||||
- controller 创建 ExternalSecret,不直接创建含 data/stringData 的 Secret。
|
||||
- 日志字段允许 namespace/name、UID、generation、阶段和错误类别;禁止记录请求/响应体、
|
||||
@@ -41,8 +42,10 @@ VM/磁盘备份会包含 PostgreSQL registry 和租户数据,但不应包含 O
|
||||
|
||||
## 最小权限
|
||||
|
||||
OpenBao controller identity 只能读取管理凭据范围并管理固定 tenant base path;ESO
|
||||
identity 只能读取 tenant base path。两者不得共用可访问管理凭据的 policy。
|
||||
OpenBao controller identity 只管理固定 tenant base path,不读取管理凭据。管理凭据
|
||||
ESO 身份只读管理路径,租户 ESO 身份只读 tenant base path,二者隔离,Tenant 不得
|
||||
使用管理凭据 Store。controller 对管理 Secret 的读取限于自身 namespace,Instance
|
||||
不能指定其他 namespace;controller 不创建或修改管理 Secret/ExternalSecret。
|
||||
|
||||
PostgreSQL 管理 role 不应是 superuser。若平台选择 SECURITY DEFINER 函数承载创建或
|
||||
删除操作,函数必须固定 `search_path`、严格校验 identifier、拒绝任意 SQL,并仅向
|
||||
|
||||
+39
-8
@@ -4,7 +4,7 @@
|
||||
| --- | --- |
|
||||
| 状态 | Approved |
|
||||
| 目标 API | `database.ddupan.top/v1alpha1` |
|
||||
| 最后更新 | 2026-09-10 |
|
||||
| 最后更新 | 2026-09-13 |
|
||||
| 批准日期 | 2026-09-10 |
|
||||
| 规范范围 | 首次注册外部 PostgreSQL 实例并创建一个应用租户 |
|
||||
|
||||
@@ -75,7 +75,7 @@ v1alpha1 不负责:
|
||||
| controller 工作流阶段 | Kubernetes CR `status.phase` | 状态机 checkpoint;可由外部事实保守重建 |
|
||||
| 应用凭据 | OpenBao KV v2 | Kubernetes API 中不得出现明文 |
|
||||
| Kubernetes 凭据投射 | External Secrets Operator | ExternalSecret 由本 controller 管理 |
|
||||
| PostgreSQL 管理凭据 | OpenBao KV v2 | 由 `PostgreSQLInstance` 引用 |
|
||||
| PostgreSQL 管理凭据 | controller namespace 的 Kubernetes Secret | 管理员维护 ExternalSecret,由 ESO 同步;Instance 只引用 Secret |
|
||||
|
||||
平台管理员管理 `PostgreSQLInstance`、controller 部署配置、OpenBao policy 和
|
||||
PostgreSQL 管理 role。应用或 GitOps 流程在获得 namespace RBAC 后管理
|
||||
@@ -93,12 +93,24 @@ PostgreSQL 管理 role。应用或 GitOps 流程在获得 namespace RBAC 后管
|
||||
- PostgreSQL host、port 和管理连接使用的 database;
|
||||
- PostgreSQL host address,供无法解析 DNS 的消费者使用;
|
||||
- TLS mode;
|
||||
- PostgreSQL 管理凭据在 OpenBao 中的位置和字段名;
|
||||
- controller namespace 中 PostgreSQL 管理 Secret 的名称和字段名;
|
||||
- 租户允许申请的 extension 集合。
|
||||
|
||||
实例 Ready 不代表 PostgreSQL 数据有备份或高可用,只表示 controller 当前可以安全
|
||||
建立管理连接、读取 server metadata、访问 controller registry 并使用所需管理能力。
|
||||
|
||||
Instance 身份和 endpoint 以管理员声明为准。修改 endpoint 不验证是否仍是原物理
|
||||
服务器或原 registry,不增加服务器/安装身份绑定检查;但旧配置观察失效,必须按
|
||||
新配置重新检查连接和管理能力。新 CR 按新 Instance 处理,不自动接管旧 UID 的租户
|
||||
资源。controller 不迁移旧服务器上的数据,也不清理旧目标,影响由管理员负责评估。
|
||||
|
||||
Instance 开始受管时即添加 finalizer,成功保存后才参与供应,不等发现 Tenant 后
|
||||
再补加。删除期间停止新供应;仍有引用它的 Tenant(包括正在删除的 Tenant)时保留
|
||||
finalizer,无引用后才移除。不级联删除 Tenant 或任何外部数据库、角色、凭据。
|
||||
引用检查失败不得当作无引用。首版不引入跨对象锁或准入控制:finalizer 不禁止同时
|
||||
创建 Tenant CR,新 Tenant 遇到正在删除或已不存在的 Instance 时不得开始供应。
|
||||
这不保证列表检查、CR 创建和在途外部操作之间的原子性;不是严格的跨对象事务。
|
||||
|
||||
### 5.2 PostgreSQLTenant
|
||||
|
||||
`PostgreSQLTenant` 是 namespaced 资源。v1alpha1 中,一个 Tenant 精确对应:
|
||||
@@ -174,8 +186,20 @@ Token 禁止写入 Deployment、CR 或镜像。
|
||||
|
||||
### 8.2 管理凭据
|
||||
|
||||
`PostgreSQLInstance` 只引用 PostgreSQL 管理用户名和密码所在的 OpenBao KV v2
|
||||
mount-relative path。controller 对该路径只需要读取权限。
|
||||
`PostgreSQLInstance` 只引用 controller 自身 namespace 中 Kubernetes Secret 的名称及
|
||||
用户名、密码字段名,不允许指定 namespace 或 Bao path。endpoint 仍由 Instance 声明。
|
||||
平台管理员维护 ExternalSecret,将 OpenBao 管理凭据同步到该 Secret;controller 只读
|
||||
Secret,不创建或修改管理 Secret、其 ExternalSecret 或上游管理凭据。
|
||||
|
||||
Instance 管理连接不直接访问 Bao,不负责管理密码轮换。已装配的凭据仍可访问
|
||||
PostgreSQL 且满足 registry/权限要求时,Bao 或 ESO 暂时不可用不使 Instance NotReady。
|
||||
首次装配无法取得有效 Secret 时不能 Ready。检测到所引用 Secret 的有效用户名或密码
|
||||
变化时,controller 使用新值重建管理连接池并重新检查管理能力;仅 metadata 或无关
|
||||
字段变化不触发重建。刷新不依赖 Instance generation 变化,新连接验证失败按实际
|
||||
故障报告,不能用旧连接的成功结果证明新凭据可用。
|
||||
controller 不修改 PostgreSQL 密码、不回写 Secret,也不修改 Bao 管理凭据;数据库侧
|
||||
凭据变更由管理员负责。这是跟随已提供凭据的连接刷新,不是自动密码轮换。
|
||||
Tenant 凭据管理仍直接依赖 Bao。
|
||||
|
||||
### 8.3 租户凭据
|
||||
|
||||
@@ -410,8 +434,9 @@ v1alpha1 不接管现有 database 或 role,但必须提供可重复、可回
|
||||
明文连接。
|
||||
3. PostgreSQL 管理 role 应使用满足本规格的最小权限,不应使用 PostgreSQL
|
||||
superuser;若 extension 安装需要额外权限,必须单独记录例外。
|
||||
4. OpenBao policy 必须限制为:读取已登记的管理凭据范围,以及创建/读取本 controller
|
||||
管理的租户 KV 范围。
|
||||
4. controller 的 OpenBao policy 仅覆盖受管租户 KV 操作,不授予管理凭据路径权限。
|
||||
管理凭据的 ESO 同步身份与应用凭据的 ESO 读取身份隔离。controller 只在自身
|
||||
namespace 获得管理 Secret 读取权限,不因此扩大跨 namespace Secret data 访问范围。
|
||||
5. namespace 用户不得修改 cluster-scoped Instance。
|
||||
6. 所有 identifier、extension name 和引用字段必须在发起外部调用前校验。
|
||||
7. controller 不得通过 shell 或 `psql` 子进程执行用户输入。
|
||||
@@ -435,7 +460,9 @@ v1alpha1 至少必须提供:
|
||||
实现 v1alpha1 第一条完整纵向切片前,测试必须覆盖:
|
||||
|
||||
1. 有效 Instance 可以建立 TLS 管理连接并变为 Ready。
|
||||
2. PostgreSQL 或 OpenBao 暂时不可用时 Ready=False,恢复后自动变为 Ready。
|
||||
2. PostgreSQL 管理能力不可用时 Instance Ready=False,恢复后自动变为 Ready;已有
|
||||
管理凭据可正常使用时,Bao/ESO 故障不单独影响 Instance Ready。首次装配缺少有效
|
||||
管理 Secret 时不能 Ready;Tenant 的 Bao 操作失败按其自身依赖故障报告。
|
||||
3. 有效 Tenant 创建 database、作为 owner 的 login、grant、extension 和 OpenBao
|
||||
记录。
|
||||
4. 应用凭据可以实际连接且不能创建其他 database/role。
|
||||
@@ -496,6 +523,10 @@ v1alpha1 至少必须提供:
|
||||
|
||||
## 17. 批准状态
|
||||
|
||||
2026-09-13 已确认管理连接修订:Instance 引用 controller namespace 内的管理 Secret,
|
||||
管理员维护 ExternalSecret,由 ESO 同步;controller 不再从 Bao 直接读取管理凭据。
|
||||
此项是已批准行为,现有 API types 与实现尚待后续修改。
|
||||
|
||||
具体设计决策和本文整体已于 2026-09-10 获得批准,可以进入 API reference、测试和
|
||||
实现阶段。同日确认状态机修订:两个 CR 的 `status.phase` 是 controller 工作流的权威
|
||||
checkpoint;PostgreSQL registry 只承担所有权、安装身份和保留状态。
|
||||
|
||||
Reference in New Issue
Block a user