feat: 接入 Database 三资源 API 与分层绑定协调
确定单库单账号、集群级 Database、资源侧先写绑定和凭据定位合同。领域层承载纯规则,service 协調流程,Kubernetes adapter 负责资源呈现与版本保护。 验证:全量 make test、三轮 race、真实 API server 并发与重启补写、最小 RBAC/watch、lint 和文档检查通过。供应、凭据交付及删除清理尚未实现,保留 DeletionPending/finalizer 边界。
This commit is contained in:
@@ -2,17 +2,70 @@
|
||||
|
||||
| 项目 | 内容 |
|
||||
| --- | --- |
|
||||
| 状态 | 三资源模型已批准;新增字段与绑定协议待评审 |
|
||||
| 状态 | API schema 与绑定 controller 已实现;供应、交付与删除清理未接入 |
|
||||
| API group/version | `database.ayatori.ddupan.top/v1alpha1` |
|
||||
| 最后更新 | 2026-09-24 |
|
||||
| 最后更新 | 2026-09-25 |
|
||||
|
||||
以 [系统规格](specification.md) 与
|
||||
[ADR-0009](../decisions/0009-database-resource-and-claim.md) 为准。尚未实现新 API,
|
||||
本页不提供可直接 apply 的三资源 YAML,以免把工作名称和未决字段当作已发布合同。
|
||||
[ADR-0009](../decisions/0009-database-resource-and-claim.md) 为准。类型与生成的 CRD 已纳入源码,
|
||||
尚未发布为可用 DBaaS。示例可进入绑定协调,但不代表创建对象后会供应数据库或交付凭据。
|
||||
|
||||
## 当前 API 切片
|
||||
|
||||
Go 类型位于 `api/database/v1alpha1`,CRD 随 `config/crd` 发布;manager 已注册 Scheme 和
|
||||
`internal/database/controller` 的绑定 controller。以下字段是本切片的具体实现:
|
||||
|
||||
| 资源 | 字段 | 含义 |
|
||||
| --- | --- | --- |
|
||||
| Database | `spec.instanceRef.name` | 所属集群级 Instance |
|
||||
| Database | `spec.database`、`spec.loginRole` | 实际数据库与唯一登录 owner,必填 |
|
||||
| Database | `spec.source` | 必填 `Provision` 或 `Import`,不隐式认领 |
|
||||
| Database | `spec.credentialRef.mount/path` | Import 必填的已有 KV v2 凭据位置;Provision 禁止指定 |
|
||||
| Database | `spec.reclaimPolicy` | Retain 默认或 Delete |
|
||||
| Database | `spec.tenantRef.namespace/name/uid` | controller 写入的完整绑定身份,不是允许名单 |
|
||||
| Database | `status.instanceUID` | 观察时的 Instance 身份 |
|
||||
| Tenant | `spec.provision.instanceRef.name` | 动态申请来源,与 `spec.databaseRef` 互斥且必须二选一 |
|
||||
| Tenant | `spec.provision.database/loginRole` | 可省略,语义默认值由 controller 解析,不由 CRD 推导 |
|
||||
| Tenant | `spec.databaseRef.name` | 显式申请已有 Database,不额外指定 Instance |
|
||||
| Tenant | `spec.extensions`、`spec.secretName` | 扩展集合与同 namespace 的交付目标 |
|
||||
| Tenant | `status.databaseRef.name/uid` | 资源侧绑定成功后写入 |
|
||||
| Tenant | `status.secretName`、`status.credentialURL` | 交付观察,不包含密码或认证信息 |
|
||||
|
||||
三资源均有 status subresource、observedGeneration 和按 type 唯一的 Conditions。
|
||||
Instance phase 沿用已批准枚举;Database/Tenant phase 暂不冻结供应子阶段枚举。
|
||||
`credentialRef.path` 是 mount 内逻辑路径,不包含 KV v2 的 `data/` 前缀。
|
||||
其部署允许范围、实际凭据读取和 URL 安全构造仍由后续 adapter/controller 验证。
|
||||
|
||||
示例:[Instance](../../config/samples/database_v1alpha1_postgresqlinstance.yaml)、
|
||||
[导入 Database](../../config/samples/database_v1alpha1_postgresqldatabase.yaml)、
|
||||
[动态/已有资源申请](../../config/samples/database_v1alpha1_postgresqltenant.yaml)。
|
||||
|
||||
当前 schema 验证名称、端口、IP、TLS 枚举、申请互斥、导入凭据要求和绑定 UID 完整性。
|
||||
API 接受两个 Tenant 引用同一 Database 不表示允许双重绑定;排他绑定由 controller 协调。
|
||||
绑定 controller 解析动态 database/loginRole 的 Tenant 名称默认值;动态资源 CR 名称为
|
||||
`tenant-<Tenant UID>`,首次创建即包含资源侧绑定与 finalizer,不带 Tenant ownerReference。
|
||||
已有资源必须有当前版本 Ready 观察、匹配的 Instance UID,并处于未绑定的 Available 状态。
|
||||
同一 Tenant 的资源侧记录已写入时,允许回读后补齐申请侧,不重新争抢资源。
|
||||
|
||||
Tenant 进入 `status.phase=Binding` 后由 CEL 固定申请目标;Database 有实例身份观察或
|
||||
绑定后固定实际 database、loginRole、来源和凭据引用,回收策略仍可修改。
|
||||
读取绑定判断使用 APIReader,写入依靠 resourceVersion;watch/cache 负责触发协调。
|
||||
绑定顺序由 application service 协调,纯资格规则在领域层;Kubernetes adapter 负责快照
|
||||
映射、finalizer 和状态呈现。呈现前若资源版本已变化,返回冲突供下一轮重读,不覆盖其他修改。
|
||||
双向记录完成后 Tenant 为 Bound,Ready=False/BindingComplete,明确尚未供应或交付。
|
||||
生成的 manager RBAC 仅授予绑定所需资源读写,不包含 Secret 读取或后端凭据权限。
|
||||
|
||||
当前有 Tenant/Database finalizer 保护,但**删除清理尚未实现**:Tenant 删除报告
|
||||
Ready=False/DeletionPending 并保留绑定与 finalizer,Database 的保护也不会被自动移除。
|
||||
还未实现删除流程开始后的回收策略固定、Retain 释放、Released 重新开放、外部清理、
|
||||
扩展只追加、Secret 默认名称解析与凭据交付。在后续清理协议和真实后端验收完成前,
|
||||
不能作为可用 DBaaS 部署,也不能通过强行移除 finalizer 把它视为已完成清理。
|
||||
|
||||
## 通用约定
|
||||
|
||||
- Instance 是 cluster-scoped;Tenant 是 namespaced;Database scope 待字段评审。
|
||||
- Instance 与 Database 是 cluster-scoped;Tenant 是 namespaced。
|
||||
- Tenant 按名称引用 Database,不提供 Database namespace;Database 绑定记录包含
|
||||
Tenant namespace/name/UID。字段见当前 API 切片;绑定采用下述资源侧先写顺序。
|
||||
- 每类资源提供唯一的 Ready Condition、observedGeneration;phase 用于进度展示,
|
||||
不能单独作为写权限或所有权证明。
|
||||
- 引用必须区分定位名称与已绑定 UID;同名新对象不继承绑定。
|
||||
@@ -57,21 +110,30 @@ Tenant 引用。无引用才解除,不级联删除资源;查询失败不能
|
||||
|
||||
## Database 资源(工作 Kind:PostgreSQLDatabase)
|
||||
|
||||
以下是字段职责,不是已批准的 JSON schema:
|
||||
v1alpha1 以一个 database、一个兼任 owner 的 login role 及其应用凭据作为 Database 的
|
||||
生命周期边界;不提供多账号字段或独立 Role/Credential CRD。多账号需求留待后续 API 版本。
|
||||
此决定不改变导入只读验证和显式管理授权的要求。
|
||||
|
||||
Database 是平台管理的集群级资源,不归属于应用 namespace,也不需要资源专用 namespace。
|
||||
普通申请者通过 Tenant 申请使用,不能自行修改 Database 回收策略或将 Released 资源重新开放;
|
||||
这些资源管理操作由平台管理员授权。controller 的绑定协调权限与用户申请权限分别配置。
|
||||
|
||||
以下是行为合同,具体 schema 见当前 API 切片与生成的 CRD;后端行为尚未实现:
|
||||
|
||||
| 内容 | 合同 |
|
||||
| --- | --- |
|
||||
| `instanceRef` | Database 自身必填;定位来源并记录绑定的 Instance UID,不依赖 Tenant 补齐 |
|
||||
| 外部目标 | 实际 database 名称及已确认的管理范围;操作开始后不可隐式改目标 |
|
||||
| 来源 | 区分动态供应与管理员显式导入;不能从同名存在推断导入授权 |
|
||||
| 申请预留/绑定 | 至多一个 Tenant,含 namespace/name/UID;Released 保留旧身份 |
|
||||
| 绑定 | 至多一个 Tenant,含 namespace/name/UID;Released 保留旧身份;无允许绑定名单 |
|
||||
| 回收策略 | 资源侧 Retain(默认)或显式 Delete;普通 Tenant editor 不得扩大授权 |
|
||||
| 观察与进度 | 实际目标、当前阶段、条件和安全诊断,不保存秘密 |
|
||||
|
||||
概念生命周期包含供应/验证、可绑定、已绑定、Released 和删除;最终 phase 枚举待协议评审。
|
||||
Released 不自动变成可绑定。Database 不以 Tenant 为 GC owner;使用中的资源受删除保护。
|
||||
|
||||
导入的初始检查只读;存在不等于 Ready,也不等于有权交付给任意 Tenant。
|
||||
导入的初始检查只读;存在不等于 Ready。未绑定且可用的资源允许 Tenant 显式申请,
|
||||
不要求管理员逐 Tenant 授权;已占用或 Released 的资源不能直接绑定。
|
||||
默认保留不隐含密码、owner、授权或删除的变更许可。
|
||||
|
||||
## PostgreSQLTenant
|
||||
@@ -90,16 +152,34 @@ Released 不自动变成可绑定。Database 不以 Tenant 为 GC owner;使用
|
||||
仅按 Tenant namespace/name 派生凭据路径的规则不再是实现合同。已有代码没有兼容负担,
|
||||
不保留两套相互覆盖的策略字段。
|
||||
|
||||
## 绑定协议评审要求
|
||||
## 已确认的绑定顺序
|
||||
|
||||
1. 动态申请按 Tenant UID 确定 Database 名称并创建记录;已有资源申请使用指定的 Database,
|
||||
检查资源未绑定且可用,不增加反向授权名单。动态创建重试遇到同名记录时需核对身份与目标。
|
||||
2. 使用 resourceVersion 并发控制,先在 Database 记录 Tenant namespace/name/UID。
|
||||
已绑定其他 Tenant 时报告 Conflict,不抢占;版本冲突后重新读取、重新判断。
|
||||
3. 在 Tenant status 记录 Database name/UID。若上一步成功、本步失败,后续 reconcile
|
||||
核对身份后补齐,不回滚已经成功的资源侧绑定。
|
||||
4. 双向记录一致才允许动态供应或凭据交付;实际数据库与凭据验证通过后才可 Ready。
|
||||
|
||||
此顺序借鉴 PV/PVC 的资源侧先写模式,行为依据见
|
||||
[系统规格](specification.md#5-动态供应与排他绑定)。Retain 释放时保留旧绑定身份并进入
|
||||
Released,不自动清空后重新分配。API 记录部分写入由 reconcile 重试;外部创建结果
|
||||
无法确认时仍报告 Conflict,交给人工,不新增事务队列或 registry。
|
||||
|
||||
## 绑定协议剩余评审要求
|
||||
|
||||
实现前必须明确:
|
||||
|
||||
1. 资源 scope 与 typed reference 格式,管理员预留/导入与普通申请者的 RBAC 边界。
|
||||
2. 资源侧排他记录的写入点、双向绑定顺序、API 冲突重试与单边完成恢复。
|
||||
1. 引用字段的最终格式,以及落实管理员资源管理、controller 协调与普通申请权限的 RBAC 规则。
|
||||
2. 绑定记录的最终字段及校验规则,落实上述写入顺序与恢复行为。
|
||||
3. Tenant UID 变化、对象删除、Released 旧引用与管理员重新授权的判断。
|
||||
4. 同一物理数据库重复登记的冲突处理;列表查询不是原子认领。
|
||||
5. Database 的 role/凭据管理范围、稳定凭据定位、旧访问处置与投射清理顺序。
|
||||
6. 删除开始后的策略固定点和 Tenant/Database finalizer 配合。
|
||||
5. 已有凭据关联字段、旧访问处置与投射清理顺序;动态凭据路径已确定按 Database UID 定位。
|
||||
6. Tenant/Database finalizer 配合;回收策略默认 Retain,删除流程前可改,进入后固定。
|
||||
|
||||
资源管理者设置 Delete 即表示删除授权,不增加额外审批字段。导入显式关联已有凭据;
|
||||
Released 不自动改密,管理员处理旧访问后才重新开放。Tenant 不得自选任意 OpenBao 路径。
|
||||
|
||||
该协议使用 Kubernetes API 持久化,不为它新增 PostgreSQL registry。
|
||||
未完成一致绑定不得供应或交付;外部创建结果不确定按 Conflict 人工处理。
|
||||
|
||||
@@ -18,7 +18,20 @@
|
||||
需故障注入外部成功而 API 写入失败、后端响应丢失、双 Tenant 竞争、同名新 UID、依赖稍后出现、
|
||||
Instance 删除与 Released 引用。冲突必须给出可操作而不泄密的诊断;不要求自动认领不确定结果。
|
||||
envtest 不运行 GC 或 ESO;这些行为必须由测试集群验证。
|
||||
新增资源 API 尚未实现,本轮没有完成或运行这些新增行为测试。
|
||||
三资源 API 类型与 CRD 已实现,`make test` 包含真实 API server 验证:作用域、
|
||||
静态默认值、非法声明、status 写入隔离、Condition 唯一性、resourceVersion 冲突与绑定记录回读。
|
||||
另有绑定 controller 的真实 API server 测试:动态记录幂等、资源侧写入后故障注入、
|
||||
新 reconciler 回读补齐、双 Tenant 竞争、Released/旧 UID 拒绝、目标固定、陈旧观察、
|
||||
删除期间 finalizer 保留。实际 manager 在生成的 RBAC 角色下通过 watch/cache 处理依赖
|
||||
稍后出现,绑定角色不具备 Secret 读取权限。没有 PostgreSQL/OpenBao 写入;后端 Ready
|
||||
在测试中由 fixture 提供,不能把它当成完整 Instance/Database 观察验证。
|
||||
|
||||
Retain 释放和 Delete 清理仍未实现,当前删除会保持 DeletionPending 与 finalizer。
|
||||
真实后端供应、凭据交付与上述完整删除矩阵仍待后续切片验收。
|
||||
|
||||
绑定规则另有不依赖 Kubernetes 的单元测试;service 测试只验证操作顺序、失败停止与最终
|
||||
身份回读,不模拟 API server。原真实 API controller 测试覆盖完整分层调用,另验证 service
|
||||
返回后发生并发修改时,资源呈现拒绝过期结果,重试完成绑定且保留其他字段。
|
||||
|
||||
## Ayatori 已接入的凭据与 metadata 切片测试
|
||||
|
||||
@@ -53,7 +66,8 @@ metadata 测试验证版本与可用扩展的只读查询,包括未安装扩
|
||||
Instance 领域测试不再提供 registry 状态,初次验证与 Ready 重验分别覆盖所有管理检查项的
|
||||
未观察、不可用、认证失败、权限不足及未知值,并验证依赖恢复;完整管理观察可直接 Ready。
|
||||
|
||||
这些测试尚不包含 Instance CRD/controller、Secret watch、status/finalizer 事件链、权限探测矩阵、ESO 或 Tenant 供应。版本查询成功不意味着 Instance Ready。
|
||||
PostgreSQL adapter 测试不包含 controller、Secret watch、status/finalizer 事件链、权限探测矩阵、ESO 或 Tenant 供应。
|
||||
CRD 基础语义由前述 API 测试覆盖;版本查询成功不意味着 Instance Ready。
|
||||
|
||||
本项目同时依赖 Kubernetes API、PostgreSQL、OpenBao 和 ESO。日常开发不连接 homelab
|
||||
中的真实服务:Kubernetes 使用 envtest 或一次性 Kind,另外两个依赖使用一次性
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Database 领域模型
|
||||
|
||||
状态:资源模型已确认,字段与绑定协议待细化。日期:2026-09-24。
|
||||
状态:资源模型已确认,字段与绑定协议待细化。日期:2026-09-25。
|
||||
行为以 [系统规格](specification.md) 为准;决策依据见
|
||||
[ADR-0009](../decisions/0009-database-resource-and-claim.md)。
|
||||
|
||||
@@ -19,6 +19,10 @@
|
||||
Instance 一对多 Database;每个 Database 同时零或一个 Tenant,Tenant 最多一个 Database。
|
||||
Instance 不持有全部资源的内存集合。三者以引用关联,操作一个资源无需加载整个实例集合。
|
||||
|
||||
Instance 与 Database 是集群级资源,Tenant 位于 namespace。Tenant 按名称引用 Database,
|
||||
Database 记录所绑定 Tenant 的 namespace/name/UID。Database 不属于应用 namespace;
|
||||
平台管理员管理资源及回收策略,普通申请者不能自行将 Released 资源重新开放。
|
||||
|
||||
Database 的 instanceRef 表达资源归属,手工登记时也必须提供,不从 Tenant 反推。
|
||||
Tenant 动态申请才选择 Instance;引用已有 Database 时使用资源声明的 Instance。
|
||||
释放使用绑定不改变 Database 的实例归属,修改引用不能实现外部数据库迁移。
|
||||
@@ -35,19 +39,26 @@ registry。管理凭据来源和连接刷新由应用层协调,连接池由 pg
|
||||
Database 保护目标和管理范围、排他绑定、导入验证与 Retain/Delete 规则。资源首次外部操作前
|
||||
必须已有持久记录;完成记录与外部存在性分别检查。数据库名称不是归属证明。
|
||||
|
||||
Tenant 表达申请与交付要求;显式选择已有资源不自动授权使用。绑定后检查数据库满足要求、
|
||||
Tenant 表达申请与交付要求;可显式申请未绑定且可用的资源,不增加反向授权名单。
|
||||
绑定后检查数据库满足要求、
|
||||
应用凭据可登录且 ESO 投射完成,才可 Ready。Tenant 删除意味着释放使用关系。
|
||||
|
||||
LoginRole 与 CredentialLocation 的生命周期必须随独立资源保留,不能因为 Tenant 消失就
|
||||
失去定位或未经授权被删除;具体字段归属及导入时的管理范围需继续评审。不要因此新增 Role、
|
||||
Credential 或 Claim CRD。当前首版仍是单 database + 单 login owner。
|
||||
第一版 Database 的生命周期边界包含一个 database、一个兼任 owner 的 LoginRole 及其
|
||||
应用凭据。LoginRole 与 CredentialLocation 随 Database 保留,不能因为 Tenant 消失就
|
||||
失去定位或未经授权被删除;导入时的管理授权与具体字段仍需评审。不新增 Role、Credential
|
||||
或 Claim CRD,也不预留多账号集合;若出现一库多账号的实际需求,再通过后续 API 版本演进。
|
||||
|
||||
## 生命周期与恢复
|
||||
|
||||
- 动态创建与显式导入最终形成同一种 Database 资源,但导入本身不允许改密、改 owner 或删除。
|
||||
- Retain 后 Database 保持 Released 与旧绑定身份,人工确认数据、权限和凭据后才可重新绑定。
|
||||
- 回收策略属于资源侧;Tenant 与 Database 不是可随申请级联 GC 的父子关系。
|
||||
- 回收策略默认 Retain,进入删除流程前可由资源管理者修改,进入后固定;Delete 无额外审批。
|
||||
- 动态凭据位置按 Database UID 确定,导入显式关联已有凭据;Released 不自动改密。
|
||||
- 绑定 UID 防止同名新申请继承权限。双向记录的单边写入不代表绑定完成。
|
||||
- 动态 Database 名称由 Tenant UID 确定;先持久化资源侧 Tenant 引用,再更新 Tenant status
|
||||
的 Database 引用。后一写入失败由 reconcile 核对身份后补齐,不回滚资源侧记录;
|
||||
其他 Tenant 已占用则报冲突。双向一致后才供应或交付,绑定不等于 Ready。
|
||||
- 普通失败按 reconcile 重试;可靠确认的步骤幂等继续;不确定创建/未知同名对象报告 Conflict。
|
||||
- Kubernetes status 是持久进度和观察,不是外部事实,也不是 controller 内存。
|
||||
不引入“status 任意丢失后自动恢复所有权”的附加要求。
|
||||
@@ -58,18 +69,25 @@ Credential 或 Claim CRD。当前首版仍是单 database + 单 login owner。
|
||||
| --- | --- |
|
||||
| 领域 | 值、身份、允许动作、不变量、完成与冲突判定;不做 IO |
|
||||
| 应用 | 装载记录与事实、协调 API 更新和 adapter、回读、交回领域判定 |
|
||||
| controller | watch/调度、映射、conditions/status/finalizer;不重写领域规则 |
|
||||
| adapter | Kubernetes、PostgreSQL、OpenBao、ESO 的具体访问与安全错误分类 |
|
||||
| controller | watch/调度、调用用例、请求资源呈现与安排重试;不判断绑定资格 |
|
||||
| adapter | Kubernetes 资源映射与呈现(含 conditions/status/finalizer)、后端访问与安全错误分类 |
|
||||
| 装配 | 客户端与成熟连接池的生命周期,不是领域状态 |
|
||||
|
||||
不引入通用 Repository CRUD、跨系统 Unit of Work、事务队列或第二套 phase 存储。
|
||||
resourceVersion 解决 API 对象并发更新,不宣称 PostgreSQL 与 Kubernetes 原子提交。
|
||||
|
||||
绑定实现中,`domain/binding` 承载请求默认值、资源身份匹配、实例就绪与排他绑定规则;
|
||||
`application/BindingService` 协调固定申请、资源侧写入和回读确认,返回待呈现结果。
|
||||
两层均不依赖 Kubernetes API 类型。`adapter/kubernetes/BindingResources` 将 CR 转换为事实
|
||||
快照,并负责保留其他字段、检查快照版本、写入 finalizer 和呈现 Conditions/status。
|
||||
controller 仅连接事件、service 与呈现层,不把资源写入细节和领域判断塞进 Reconcile。
|
||||
这里的接口只列出绑定用例所需操作,不扩展成通用 CRUD、Repository 或事务框架。
|
||||
|
||||
## API 切片前需明确
|
||||
|
||||
- Database 的 scope、引用格式、谁可以预留/绑定/释放,以及绑定字段和更新顺序。
|
||||
- 引用与绑定字段的最终格式及校验、管理员与 controller 的权限落实。
|
||||
- 资源侧回收策略与 Tenant/Database finalizer 配合。
|
||||
- 导入时角色/凭据的管理范围,稳定凭据定位、旧使用者撤权及新投射授权。
|
||||
- 导入时角色/凭据的管理范围及关联字段、旧使用者撤权及投射清理。
|
||||
- 绑定/导入同一实际目标的重复声明如何拒绝,且不引入 registry。
|
||||
- 管理员确认冲突、解除旧绑定的具体可审计操作入口。
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
| 最后更新 | 2026-09-24 |
|
||||
|
||||
当前设计支持管理员显式登记已有 Database;未知同名资源仍不得自动认领。
|
||||
导入不要求移动数据,不隐含改密码、owner、授权或删除权限。API 尚未实现,以下导入步骤
|
||||
导入不要求移动数据,不隐含改密码、owner、授权或删除权限。API schema 与绑定协调已实现,
|
||||
但导入观察和凭据交付尚未实现,以下导入步骤
|
||||
是验收要求而非可直接执行的命令。
|
||||
|
||||
## 显式导入与保留资源复用
|
||||
@@ -15,7 +16,7 @@
|
||||
1. 核对 Instance、数据库、owner、角色权限、扩展、使用者与备份,确定允许管理的范围。
|
||||
2. 由管理员声明 Database,指定已有目标,回收策略默认 Retain;导入验证初始只读。
|
||||
3. 安全关联现有应用凭据;具体 API 待定,不把密码写入 CR,不因验证失败重置密码。
|
||||
4. 管理员授权目标 Tenant;controller 验证资源与申请符合要求并建立排他绑定。
|
||||
4. Tenant 显式引用未绑定且可用的 Database;controller 验证要求并建立排他绑定,无额外名单审批。
|
||||
5. 验证实际登录与 ESO 交付;不满足时停止,不以修改原数据库作为默认修复。
|
||||
|
||||
Released 资源复用前另需核实旧使用者的访问权限、数据交接与投射处置。保留旧绑定身份直到
|
||||
@@ -135,7 +136,7 @@ extension 应由 Tenant spec 创建。若 dump 仍包含 extension 定义,预
|
||||
|
||||
发布首个可用版本前,必须在临时 PostgreSQL/OpenBao/Kind 环境执行本文并记录:
|
||||
|
||||
- 显式导入与 Released 重新绑定的授权、旧访问处置和失败不修改原资源;
|
||||
- 显式导入的管理权限、Released 重新开放前的旧访问处置和失败不修改原资源;
|
||||
- 使用的 PostgreSQL major version 和命令版本;
|
||||
- dump/restore 返回码和对象差异;
|
||||
- DNS/IP TLS 登录结果;
|
||||
|
||||
@@ -3,6 +3,15 @@
|
||||
状态:设计合同,操作入口待 API 实现与隔离环境演练。日期:2026-09-24。
|
||||
依据 [系统规格](specification.md),不再查询或维护 PostgreSQL registry。
|
||||
|
||||
## 当前绑定切片的限制
|
||||
|
||||
源码已接入绑定 controller,未接入 PostgreSQL 供应、OpenBao/ESO 交付或删除清理。
|
||||
Bound/BindingComplete 只表示 Kubernetes 双向记录一致,Ready 仍为 False。
|
||||
Tenant 删除会保留 `database.ayatori.ddupan.top/tenant-protection` 并报告 DeletionPending;
|
||||
Database 的 `database.ayatori.ddupan.top/database-protection` 也尚无清理后移除路径。
|
||||
这是未完成能力的明确边界,不是已经实现的 Retain/Delete 恢复逻辑。不要将此切片部署为
|
||||
业务 DBaaS,也不要为了消除等待状态直接移除 finalizer;后续必须补齐清理与验收。
|
||||
|
||||
## 日常检查
|
||||
|
||||
先看 Instance、Database、Tenant 的 Ready Condition、绑定 UID、阶段与 observedGeneration,
|
||||
|
||||
@@ -51,8 +51,9 @@ PostgreSQL 管理 role 不应是 superuser。若平台选择 SECURITY DEFINER
|
||||
删除操作,函数必须固定 `search_path`、严格校验 identifier、拒绝任意 SQL,并仅向
|
||||
controller role 授予 EXECUTE。controller 不调用 shell 或 `psql` 拼接用户输入。
|
||||
|
||||
Kubernetes RBAC 应把 Instance 管理、Database 导入、预留、重新绑定授权和回收限制给平台管理员。
|
||||
知道 Database 名称不等于有权使用;Tenant editor
|
||||
Kubernetes RBAC 应把 Instance 管理、Database 导入、Released 重新开放和回收限制给平台管理员。
|
||||
有权创建 Tenant 的申请者可显式申请未绑定且可用的 Database,不增加资源侧允许绑定名单
|
||||
或逐 Tenant 审批。Released 必须先由管理员处理旧访问并重新开放。Tenant editor
|
||||
不自动获得 Secret read;是否读取目标 Secret 由 namespace 内独立 RBAC 决定。
|
||||
|
||||
## 删除保护
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
| --- | --- |
|
||||
| 状态 | 资源模型与生命周期已批准;字段协议待 API 评审 |
|
||||
| 目标 API | `database.ayatori.ddupan.top/v1alpha1` |
|
||||
| 最后更新 | 2026-09-24 |
|
||||
| 最后更新 | 2026-09-25 |
|
||||
| 决策 | [ADR-0009](../decisions/0009-database-resource-and-claim.md) |
|
||||
|
||||
本文是当前行为合同,替代旧的 Tenant 同时承担申请与资源生命周期、PostgreSQL registry
|
||||
@@ -34,9 +34,16 @@ Instance
|
||||
| Database | 描述外部数据库、管理范围、绑定与回收策略 | 充当第二套 registry 或通用资源框架 |
|
||||
| Tenant | 声明需求或显式选择资源,申请使用并交付凭据 | 删除时隐式销毁独立资源记录 |
|
||||
|
||||
Instance 保持 cluster-scoped,Tenant 保持 namespaced。Database 的工作名称是
|
||||
PostgreSQLDatabase;scope、字段拼写和管理角色/凭据的具体边界待 API 评审。
|
||||
单 database + 单 login owner 的首版使用场景不变,不新增独立 Role 或 Claim CRD。
|
||||
Instance 与 Database 为 cluster-scoped,Tenant 为 namespaced。Database 的工作名称是
|
||||
PostgreSQLDatabase;字段拼写与导入授权细节待 API 评审。
|
||||
Database 由平台管理员管理,不属于应用 namespace,不引入资源专用 namespace。
|
||||
Tenant 按名称引用 Database;Database 绑定记录包含 Tenant 的 namespace/name/UID。
|
||||
普通申请者通过 Tenant 申请使用,不能自行修改 Database 回收策略或将 Released 资源重新开放。
|
||||
|
||||
2026-09-25 确认:第一版以一个 database、一个兼任 owner 的 login role 及其应用凭据
|
||||
作为 Database 的生命周期边界,Tenant 负责申请与交付,不单独拥有账号或凭据生命周期。
|
||||
不预留多账号字段,不新增独立 Role、Credential 或 Claim CRD。一库多账号若出现实际需求,
|
||||
通过后续 API 版本演进处理,不纳入 v1alpha1。此边界不扩大导入资源的管理授权。
|
||||
|
||||
Database 自身必须声明 `instanceRef`,手工登记时同时指定实际数据库名;无需先存在 Tenant,
|
||||
即可通过 Instance 验证目标。动态申请由 Tenant 选择 Instance,供应时把该引用写入 Database;
|
||||
@@ -81,15 +88,25 @@ endpoint 变更由管理员负责评估,不验证物理服务器连续性,
|
||||
## 5. 动态供应与排他绑定
|
||||
|
||||
1. 校验 Tenant 请求、Instance 能力、名称和扩展要求。
|
||||
绑定 controller 在触及资源侧绑定前将 Tenant 进度记为 Binding,固定申请目标,
|
||||
避免两次绑定写入之间修改引用占用第二个资源;该进度不是已绑定的声明。
|
||||
2. 在首次外部写入前持久化独立 Database 记录、确定目标与管理范围。
|
||||
3. 建立带 UID 的排他预留/绑定,避免两个 Tenant 同时使用同一 Database。
|
||||
动态创建的 Database 名称由 Tenant UID 确定;重试复用同一记录,不重复创建。
|
||||
3. 先在 Database 写入 Tenant namespace/name/UID,再在 Tenant status 写入 Database
|
||||
name/UID;双向记录一致后才允许供应或交付。
|
||||
4. 按已确认步骤建立凭据、role、database、授权和扩展,逐步回读。
|
||||
5. 验证应用登录与 ESO 投射后,Tenant 才可 Ready。
|
||||
|
||||
绑定前固定有效目标;绑定或开始外部供应后不得通过修改名称或引用实施隐式迁移。
|
||||
每个 Database 最多一个使用者,每个 Tenant 最多一个 Database。
|
||||
绑定 API 写入采用 resourceVersion 并发控制;双向记录不原子,单边完成不得授予使用权限。
|
||||
具体字段、写入顺序与重启恢复协议须在 API 切片定义,并由真实 API server 验证。
|
||||
采用 Kubernetes PV/PVC 的资源侧先写模式,参考
|
||||
[官方 bind 实现](https://github.com/kubernetes/kubernetes/blob/master/pkg/controller/volume/persistentvolume/pv_controller.go)。
|
||||
Database 已绑定其他 Tenant 时报告 Conflict,不抢占;API 更新版本冲突时重新读取并判断,
|
||||
不能盲目覆盖。资源侧成功而 Tenant status 写入失败时,下一次 reconcile 核对双方身份后
|
||||
补写,不因单次失败撤销资源侧绑定。普通 controller 重启沿用这些持久记录继续协调。
|
||||
这只处理 Kubernetes 绑定记录的部分完成,不提供外部数据库不确定创建结果的自动认领。
|
||||
绑定成功不代表 Ready,具体字段及并发、重启、单边写入恢复必须由真实 API server 测试验证。
|
||||
|
||||
不同 Database 记录请求同一外部名称仍可能竞争,不能仅靠 Kubernetes 中的列表检查保证
|
||||
PostgreSQL 名称唯一。后端创建时的重名失败报告 Conflict,失败方不得接管胜方资源。
|
||||
@@ -102,12 +119,16 @@ PostgreSQL 名称唯一。后端创建时的重名失败报告 Conflict,失败
|
||||
不得通过重置密码、改变 owner 或撤销现有访问来“完成导入”。
|
||||
|
||||
未显式导入的同名数据库一律 Conflict。导入资源默认 Retain,不隐含 Delete 授权。
|
||||
Tenant 显式引用已登记资源仍需通过绑定资格与授权检查;知道资源名称不等于有权使用。
|
||||
资源侧预留/授权的具体 API 和已有凭据的安全关联入口待细化,完成前不能宣称可用。
|
||||
有权创建 Tenant 的申请者可以显式引用已登记、未绑定且可用的 Database;不增加资源侧
|
||||
允许绑定名单或逐 Tenant 的管理员审批。绑定仍检查目标、可用状态与排他关系。
|
||||
Released 不在可申请范围,必须由管理员处理旧访问并重新开放。导入时显式关联已有凭据,
|
||||
不通过隐式改密生成替代凭据;具体关联字段在 API 中定义。
|
||||
|
||||
## 7. Retain、重新绑定与 Delete
|
||||
|
||||
回收策略属于 Database,默认 Retain;Tenant 删除是释放申请,不是独立资源的 GC 授权。
|
||||
有资源管理权限的主体可在进入删除流程前修改 Retain/Delete;进入删除流程后策略固定。
|
||||
显式设置 Delete 就是删除授权,不增加第二次审批或确认字段。
|
||||
Database 不得设置会让它随 Tenant 消失的 ownerReference。
|
||||
|
||||
### Retain
|
||||
@@ -164,7 +185,8 @@ Kubernetes 应用由 ESO 投射同 namespace Secret,controller 不直接写明
|
||||
凭据仍输出 username/password/database/host/hostaddr/port/sslmode 七键,不生成带密码 URI。
|
||||
Tenant status 提供 Secret 引用与无认证信息的 OpenBao API URL。
|
||||
mount/base path 属部署配置,Tenant 不得自选任意路径;原按 Tenant namespace/name 固定
|
||||
推导路径的规则需修订为可支持资源保留与重新绑定的定位协议,本轮不定字段或新路径格式。
|
||||
推导路径的规则撤除。动态供应的凭据路径按 Database UID 确定;导入时显式关联已有凭据
|
||||
位置,不要求搬迁已有凭据。Released 不自动改密,管理员处理旧访问后才重新开放资源。
|
||||
不得因换 Tenant、改部署参数或重新绑定就隐式搬迁凭据或改密。
|
||||
|
||||
TLS、OpenBao Kubernetes auth、controller/ESO 身份隔离、Secret 读取范围和防泄漏要求
|
||||
@@ -189,7 +211,7 @@ ProvisioningFailed、CredentialProjectionFailed。Released 应明确显示未可
|
||||
| --- | --- |
|
||||
| Instance 登记与重验 | 无 registry 依赖;真实凭据/TLS/管理权限检查 |
|
||||
| 动态供应与重复 reconcile | 独立资源记录、排他绑定、密码不变、实际登录与投射成功 |
|
||||
| 显式导入 | 无数据/密码/owner 隐式修改;错误目标及未经授权申请被拒绝 |
|
||||
| 显式导入 | 无数据/密码/owner 隐式修改;错误目标、已占用或 Released 资源的申请被拒绝 |
|
||||
| 同名未知资源 | Conflict,原数据库/角色/凭据不变 |
|
||||
| 并发申请与单边绑定 | 最多一个使用者;失败方不能开始危险外部操作 |
|
||||
| controller 重启 | 已确认步骤正常继续;不确定创建报告人工可诊断冲突 |
|
||||
|
||||
Reference in New Issue
Block a user