feat: scaffold job execution API #1
@@ -3,6 +3,9 @@
|
|||||||
- 本仓库是 ddupan.top homelab 的内部基础设施控制平面,不以通用发行版为初期目标。
|
- 本仓库是 ddupan.top homelab 的内部基础设施控制平面,不以通用发行版为初期目标。
|
||||||
- 提交、文档和代码注释优先使用中文;公共 API 标识符和代码遵循对应语言惯例。
|
- 提交、文档和代码注释优先使用中文;公共 API 标识符和代码遵循对应语言惯例。
|
||||||
- 不要重新实现已有成熟后端的核心能力;新增实现前先确认能否通过稳定 API 进行薄适配。
|
- 不要重新实现已有成熟后端的核心能力;新增实现前先确认能否通过稳定 API 进行薄适配。
|
||||||
|
- 在自行设计通用控制循环、资源生命周期、调度、回收或故障恢复机制前,先调查 Kubernetes
|
||||||
|
核心及成熟开源 controller/operator 的实现;优先复用经过验证的模式,并记录有意偏离的
|
||||||
|
理由。
|
||||||
- 不要引入统一包装所有能力的 Application CRD;应用应直接组合正交的平台资源。
|
- 不要引入统一包装所有能力的 Application CRD;应用应直接组合正交的平台资源。
|
||||||
- 所有 controller 必须考虑幂等、observe、finalizer、conditions、删除策略和恢复行为。
|
- 所有 controller 必须考虑幂等、observe、finalizer、conditions、删除策略和恢复行为。
|
||||||
- Secret、token、kubeconfig 及具体生产凭据不得提交到仓库。
|
- Secret、token、kubeconfig 及具体生产凭据不得提交到仓库。
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ Ayatori 将逐步提供任务执行、虚拟机、数据库、负载均衡、对
|
|||||||
另一方面,在首个领域能力完成前就拆分为多个独立服务,会立即引入镜像与部署管理、服务
|
另一方面,在首个领域能力完成前就拆分为多个独立服务,会立即引入镜像与部署管理、服务
|
||||||
间认证、版本兼容、分布式观测和故障处理成本,而这些成本尚未由真实运行需求证明。
|
间认证、版本兼容、分布式观测和故障处理成本,而这些成本尚未由真实运行需求证明。
|
||||||
|
|
||||||
Run 是首个领域对象。它既是最初的单次任务调度 API,也用于验证领域状态机与 Kubernetes
|
Job 是首个领域对象。它既是最初的单次任务调度 API,也用于验证领域状态机与 Kubernetes
|
||||||
Job、OpenSandbox 和未来执行后端之间的适配边界。
|
Job、OpenSandbox 和未来执行后端之间的适配边界。
|
||||||
|
|
||||||
## 决策
|
## 决策
|
||||||
@@ -99,11 +99,11 @@ controller manager 应支持按领域或 controller 集合选择性启用。初
|
|||||||
|
|
||||||
## 结果
|
## 结果
|
||||||
|
|
||||||
- 首个 Run 实现需要同时建立 execution 状态机和 adapter 边界,不能把 Kubernetes Job
|
- 首个 Job 实现需要同时建立 execution 状态机和 adapter 边界,不能把 Kubernetes Job
|
||||||
细节写入领域模型。
|
细节写入领域模型。
|
||||||
- 初期避免承担不必要的微服务运维成本,同时保留按权限、网络位置和故障域拆分的路径。
|
- 初期避免承担不必要的微服务运维成本,同时保留按权限、网络位置和故障域拆分的路径。
|
||||||
- Kubernetes API 成为领域间异步协作和恢复边界,领域 controller 必须正确处理最终一致性。
|
- Kubernetes API 成为领域间异步协作和恢复边界,领域 controller 必须正确处理最终一致性。
|
||||||
- 部分机械代码会有意保留重复,直到共享语义被至少两个真实实现证明。
|
- 部分机械代码会有意保留重复,直到共享语义被至少两个真实实现证明。
|
||||||
- 代码评审需要检查跨领域 import、对象写入所有权和后端类型泄漏。
|
- 代码评审需要检查跨领域 import、对象写入所有权和后端类型泄漏。
|
||||||
- 当 Run 同时拥有 Kubernetes Job 与 OpenSandbox adapter 后,应复审 adapter contract,确认
|
- 当 Job 同时拥有 Kubernetes Job 与 OpenSandbox adapter 后,应复审 adapter contract,确认
|
||||||
它来自真实后端差异而非单一实现假设。
|
它来自真实后端差异而非单一实现假设。
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
# ADR-0005:Job 使用短生命周期控制对象与 TTL 回收
|
||||||
|
|
||||||
|
- 状态:Accepted
|
||||||
|
- 日期:2026-09-17
|
||||||
|
|
||||||
|
## 背景
|
||||||
|
|
||||||
|
Ayatori 的 `Job` 表达一次有限时长、有退出结果的执行。CI、基础设施 controller 和用户可能
|
||||||
|
持续创建大量 Job。若所有 Job CR、后端 Kubernetes Job、Pod、Event 和日志都长期保存在
|
||||||
|
Kubernetes 中,etcd、apiserver list/watch、controller cache、备份及恢复会持续承担历史
|
||||||
|
数据成本。
|
||||||
|
|
||||||
|
Kubernetes API 适合作为活动执行的在线控制与协调面,但不应在没有明确产品需求时兼任无限
|
||||||
|
增长的执行历史数据库。当前也尚未证明 Ayatori 必须独立于调用者提供长期历史或审计检索。
|
||||||
|
Gitea Actions 等调用方已经拥有自己的执行历史;基础设施 controller 也应把 Job 结果转化为
|
||||||
|
所属领域资源的 status。执行日志属于观测数据,应进入统一 observability 平台,而不是由
|
||||||
|
Job CR 或专用执行历史存储重复保存。
|
||||||
|
|
||||||
|
Kubernetes 原生 `batch/v1 Job` 使用独立的 TTL-after-finished controller 回收完成对象。
|
||||||
|
该 controller 只支持原生 Job,不能直接处理 Ayatori CRD,但其基于 informer 与延迟工作队列
|
||||||
|
的实现模式可以复用。
|
||||||
|
|
||||||
|
## 决策
|
||||||
|
|
||||||
|
Ayatori 提供 `execution.ayatori.ddupan.top` API group 下的 `Job` Kind。与 Kubernetes
|
||||||
|
`batch/v1 Job` 同名不构成冲突,完整 GVK 明确资源身份。
|
||||||
|
|
||||||
|
Ayatori Job 是短生命周期控制对象,不是永久执行记录。首版不要求将结果归档到 PostgreSQL,
|
||||||
|
也不引入 `Archived` condition 或 `JobRecord` CRD。
|
||||||
|
|
||||||
|
### 终态与 TTL
|
||||||
|
|
||||||
|
Job 到达成功、失败或取消终态后保留有限时间,随后由 Ayatori 自己的 TTL controller 删除。
|
||||||
|
API 提供与原生 Job 语义一致的 `spec.ttlSecondsAfterFinished`;未设置时是否允许无限保留由平台
|
||||||
|
准入策略决定,而不是隐式默认永久保存。
|
||||||
|
|
||||||
|
TTL 从 controller 写入的可信终态时间开始计算。TTL controller:
|
||||||
|
|
||||||
|
1. watch Job 的新增和更新;
|
||||||
|
2. 只处理已终止、设置 TTL 且尚未删除的对象;
|
||||||
|
3. 未到期时使用延迟工作队列在到期时间重新入队;
|
||||||
|
4. 到期时重新读取最新对象并复核 UID、终态和 TTL;
|
||||||
|
5. 使用 UID precondition 发起删除,防止删除同名重建对象;
|
||||||
|
6. 由 Job finalizer 完成实际执行后端与临时凭据清理。
|
||||||
|
|
||||||
|
Controller 重启后,informer 的初始 LIST 会重新触发现存对象的 reconcile 并重建内存中的延迟
|
||||||
|
任务,因此不以周期性全量扫描作为正确性基础。
|
||||||
|
|
||||||
|
### 结果消费
|
||||||
|
|
||||||
|
调用者必须在 TTL 窗口内观察 Job 终态,并把需要长期存在的业务事实写入自身状态。例如 VM
|
||||||
|
provision Job 成功后,VM controller 更新 `Provisioned` condition;之后删除 Job 不影响 VM
|
||||||
|
状态。CI 系统负责保存自身 workflow 历史。
|
||||||
|
|
||||||
|
Job status 只保存控制和短期诊断需要的结构化结果,不保存完整日志、大型输出或 artifact。
|
||||||
|
|
||||||
|
### 日志与 artifact
|
||||||
|
|
||||||
|
各 execution adapter 必须为执行实例注入稳定的关联信息,使 stdout/stderr 能由共享
|
||||||
|
observability 管道采集,并能够按 Ayatori Job 的 namespace、name 和 UID 查询。Job status
|
||||||
|
可以保存查询观测数据所需的关联标识或受控链接,但日志内容及其索引、保留和查询能力属于
|
||||||
|
observability 平台。
|
||||||
|
|
||||||
|
Job 与后端执行对象的 TTL 应为日志采集提供合理窗口,但 GC 不以日志归档成功作为前置条件,
|
||||||
|
避免观测平台故障阻塞控制面资源回收。日志采集延迟、丢失和后端不可用通过 observability
|
||||||
|
自身的监控和告警处理。
|
||||||
|
|
||||||
|
Artifact 与日志语义不同。调用者需要消费的构建产物、状态文件或结构化输出必须显式写入
|
||||||
|
对象存储等持久后端,并通过引用交付;不能依赖日志系统作为 artifact 存储。
|
||||||
|
|
||||||
|
### GitOps 边界
|
||||||
|
|
||||||
|
一次性 Job 不由 Flux 持续管理。否则 TTL 删除会被视为漂移并重新创建,从而重复执行。GitOps
|
||||||
|
可以管理 Job template、schedule、execution class 和策略;CI、CLI、UI 或其他 controller
|
||||||
|
通过 Kubernetes API 命令式创建 Job。
|
||||||
|
|
||||||
|
### 未来归档
|
||||||
|
|
||||||
|
只有出现长期历史查询、统一审计、调用者无法及时消费结果等真实需求时,才引入
|
||||||
|
外部 `JobRecord`/History API。届时可以为需要持久化的 retention policy 增加归档流程,并将
|
||||||
|
归档成功作为删除前置条件;不要求所有 Job 无条件承担该成本。
|
||||||
|
|
||||||
|
## 结果
|
||||||
|
|
||||||
|
- etcd 中只保留活动 Job、短期已完成 Job 和需要人工处理的异常 Job。
|
||||||
|
- 首版不依赖 PostgreSQL 和对象存储即可完成 Job 纵向切片。
|
||||||
|
- 调用者必须正确 watch 或轮询结果;TTL 配置必须为其提供足够消费窗口。
|
||||||
|
- 历史日志由共享 observability 平台查询,Job CR 只提供执行关联信息。
|
||||||
|
- Job 删除后的历史默认不可从 Kubernetes API 恢复,这是有意接受的语义。
|
||||||
|
- TTL controller 是 execution 领域的一部分,可以和其他 controller 编译、部署在同一个
|
||||||
|
controller manager 中。
|
||||||
|
- 若未来增加归档,应作为独立产品能力和 retention policy 演进,不改变 Job 作为短生命周期
|
||||||
|
控制对象的基本定位。
|
||||||
|
|
||||||
|
## 参考
|
||||||
|
|
||||||
|
- [Kubernetes Automatic Cleanup for Finished Jobs](https://kubernetes.io/docs/concepts/workloads/controllers/ttlafterfinished/)
|
||||||
|
- [Kubernetes TTL-after-finished controller](https://github.com/kubernetes/kubernetes/blob/master/pkg/controller/ttlafterfinished/ttlafterfinished_controller.go)
|
||||||
Reference in New Issue
Block a user