尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

FastGPT 中 OpenSandbox 的 Kubernetes PVC 生命周期管理:竞态修复与归档链路设计

FastGPT 中 OpenSandbox 的 Kubernetes PVC 生命周期管理:竞态修复与归档链路设计 FastGPT 中 OpenSandbox 的 Kubernetes PVC 生命周期管理竞态修复与归档链路设计【免费下载链接】FastGPTFastGPT is a knowledge-based platform built on the LLMs, offers a comprehensive suite of out-of-the-box capabilities such as data processing, RAG retrieval, and visual AI workflow orchestration, letting you easily develop and deploy complex question-answering systems without the need for extensive setup or configuration.项目地址: https://gitcode.com/GitHub_Trending/fa/FastGPT导读本文基于 FastGPT 仓库中的 OpenSandbox 设计文档系统讲解 volume-manager 服务在 Kubernetes 环境下对 PVCPersistentVolumeClaim的生命周期管理方案。文章聚焦于一个真实存在的竞态问题——PVC 对象删除返回 2xx 并不代表底层卷已卸载GET 返回 200 也不代表 PVC 可挂载——并给出 ensure/remove 的完整收敛算法、Sandbox 归档archive与恢复restore状态机、兼容性与迁移边界。读完本文你将掌握如何在 FastGPT 的 OpenSandbox 沙箱链路中正确处理 PVC 的 generation 竞态并理解 volume-manager 与 Sandbox 生命周期服务之间如何协作。竞态的本质PVC 删除不是瞬时完成的OpenSandbox 的 Kubernetes 归档链路中存在一个真实的竞态但它的形态不是两个同名 PVC 同时存在。设计文档明确给出两个 Kubernetes 事实作为定论旧 PVC 处于Terminating状态时Kubernetes 不会让引用它的新 Pod 正常运行——即你无法通过再创建一个同名 PVC来绕过删除PVC 对象删除成功DELETE 返回 2xx不等于PV、VolumeAttachment 或存储后端已完成卸载——对象删除只是 API 层面的开始底层的 detach/unmount 是异步的。原实现把 DELETE 的 2xx 当作删除完成、把任意 GET 200 当作可用 PVC并且在 lifecycle lease 之外预取 restore volume 配置因此可能过早发布archived状态或把正在删除的 claim 带入恢复流程。这构成了本次设计的全部出发点。目标与边界设计目标共 5 条前三条直指竞态修复后两条划定范围删除完成条件与 PVC API 对象生命周期一致避免同名 PVC 的 generation 竞态restore 获取 volume 配置必须发生在 Sandbox lifecycle lease 和 operation claim 之后不能在锁外预取archive 的 Provider 删除、volume 删除分别持久化 checkpoint支持中断后恢复Kubernetes PVC generation 生命周期处理不改变 Docker 的删除完成语义Docker 侧无 generation 概念当前只保证 PVC API generation 结束不承诺底层存储 detach/unmount 已完成文档特别注明若未来复用静态 PV 或后端卷需要增加 provider-specific 完成条件。核心不变量设计以 6 条不变量作为实现与测试的验收基准remove()返回时调用开始时锁定的 PVC UID 已消失或已被新 UID 替换DELETE 携带 UID precondition不能误删 GET 之后新建的同名 PVCensure()不返回带deletionTimestamp的 PVC并发 ensure 通过 Kubernetes API 的 404/409/UID 状态收敛不依赖进程内锁restore 在 lease 内、claim 成功后获取 volume并复用本次实际配置archive 只有完成 Provider 和 volume 两个 checkpoint 后才进入archived。第 1、2 条对应UID 即 generation的核心思想同名对象 UID 变化代表旧 generation 已结束后续操作必须基于新 UID 重新开始而不是继续对旧对象做假设。实现一K8s volume-manager 的 PVC 状态收敛算法状态归一只认 uid 与 deletionTimestampvolume-manager 的 Kubernetes 驱动实现位于 K8sVolumeDriver.ts。它只读取metadata.uid和metadata.deletionTimestamp两个字段见K8sPvcSchema并统一归一为三种状态type K8sPvcState | { state: absent } | { state: active; uid: string } | { state: deleting; uid: string };关键语义在 readPvc404归为absentdeletionTimestamp非空归为deleting(uid)否则active(uid)。注释明确写道避免把 Terminating 对象当成可挂载资源。其余错误码直接抛出不猜测状态。等待旧 generation 结束的逻辑在waitForPvcGenerationEnd轮询readPvc只要状态变为absent或uid 已与目标不同就返回——同名对象 UID 变化表示旧 generation 已完成删除此时必须停止等待不能继续操作新 PVC。ensure四种路径的收敛ensure 的收敛路径与设计文档一一对应活动 PVC直接复用返回{ claimName, created: false }删除中的 PVC等待目标 UID 消失或被替换后回到循环重新读取不存在POST 创建201返回成功created: true创建冲突409退避后重读可能已被并发 ensure 创建也可能仍在删除中继续循环其他错误立即失败。removeUID precondition 防误删remove 的核心是先读 UID再带 UID 删除不存在幂等成功返回删除中等待目标 UID 结束活动 PVC使用DeleteOptions.preconditions.uid携带目标 UID 发起 DELETE。若返回409重读最新状态——若已是absent或 UID 已变化则安全返回否则抛出错误避免误删 GET 之后新建的同名 PVC。默认参数在源码中为常量最长等待 5 分钟DEFAULT_PVC_WAIT_TIMEOUT_MS 5 * 60 * 1000、轮询间隔 500 毫秒DEFAULT_PVC_POLL_INTERVAL_MS 500且构造函数校验两者必须为正数。超时后不自行重试而是交给上层 durable lifecycle 记录失败并重试。进程边界HTTP 合同与鉴权volume-manager 是一个独立 HTTP 服务入口在 index.tsGET /health无鉴权健康检查/v1/*统一校验Authorization: Bearer ${VM_AUTH_TOKEN}按VM_RUNTIME选择驱动docker用DockerVolumeDriver默认kubernetes用K8sVolumeDriver。路由定义在 volumes.tsPOST /v1/volumes/ensure新创建返回 201复用返回 200、DELETE /v1/volumes/:claimName幂等删除返回 204。请求/响应使用 Zod schema 校验定义见 volume.ts其中SandboxVolumeNameSchema强制 DNS label 子集正则^a-z0-9?$Kubernetes PVC 与 Docker named volume 统一遵守同一命名约束。运行态环境变量在 env.ts 中统一声明PORT默认 3000、VM_AUTH_TOKEN必填、VM_RUNTIME、VM_DOCKER_SOCKET/VM_DOCKER_API_VERSION、VM_K8S_NAMESPACE默认opensandbox、VM_K8S_PVC_STORAGE_CLASS、VM_LOG_LEVEL。实现二Sandbox 生命周期中的归档状态机archive 阶段双 checkpoint 持久化archive 生命周期定义位于 archive.ts阶段流转为claimed - archiveUploaded - providerDeleted - volumeDeleted - archivedarchiveUploaded连接沙箱、打包工作区并上传归档S3providerDeleted只删除 Provider 资源deleteSandboxProviderResourcevolumeDeleted删除并等待 OpenSandbox volume 完成其他 Provider 通过空操作完成该 checkpointarchivedfinish 步骤记录默认镜像并完成。两个 checkpointproviderDeleted、volumeDeleted分别持久化其价值在于旧 operation 停在providerDeleted时重试会继续 volume 删除而不重放归档上传——避免了重复打包、重复上传 S3 的浪费。删除链路delete的 checkpoint资源删除定义在 resource.ts阶段为claimed - providerDeleted - volumeDeleted - archiveDeleted其中volumeDeleted步骤对opensandboxProvider 使用getSessionVolumeClaimName(claimed.storage)从 Mongo 持久化的 storage 中取出完整claimName再调用deleteSessionVolume(claimName)若没有持久化的 claimName 则抛出错误OpenSandbox has no persisted workspace claimName这正是设计文档删除调用使用 Mongo 持久化的完整 claimName的落地。restore 不再预取 volume旧实现会在调用 restore 前预取 volume 配置这在 lease 外读取容易拿到过期或正在删除的 claim。新设计规定创建恢复 Sandbox 的 step 在lease、状态重读和 operation claim 完成后才调用getSessionVolumeConfig()恢复函数返回实际VolumeManagerResultruntime client 直接复用本次配置避免再次读取造成不一致仅当恢复没有执行创建 step 时才在外层获取当前配置。这对应不变量第 5 条restore 在 lease 内、claim 成功后获取 volume并复用本次实际配置。兼容性与发布边界HTTP 合同升级volume HTTP API 从sessionId切换为 app 预先持久化的claimNameFastGPT app 与 volume-manager按同一版本整体升级不支持混用版本claimName合同不增加旧版sessionId兼容层配置迁移旧VM_VOLUME_NAME_PREFIX配置需以原值迁移到AGENT_SANDBOX_OPENSANDBOX_VOLUME_NAME_PREFIXcompose、Helm、环境变量模板和中英文部署文档需同步更新Docker 语义不变DockerVolumeDriver不执行 Kubernetes 状态解析、轮询或 UID precondition见 DockerVolumeDriver.ts删除时 404 视为幂等成功与 K8s 路径保持同一幂等删除语义但实现完全不同运行态分流Sandbox application 只对opensandbox使用 volume-managerDocker 不产生额外 volume 请求。运行态 storage 并发保护running 快路径设计文档补充了一个易被忽略的并发点running 快路径touch只能在Mongo 中的 storage 与 client 预读 storage 一致时刷新活跃时间并且不能通过 touch 回写 storage。若 CAS 失败进入 lifecycle lease在锁内重读实例以当前已提交的 workspace claim 重建 OpenSandbox provider。这样设计的原因在于旧 client 既不能覆盖 restore 提交的新 generation也不能继续用旧 generation 自愈远端资源——防止读旧、写旧导致恢复被破坏。旧迁移 checkpoint 恢复针对旧版本可能停在legacyMigrating/targetEnsured但尚未把旧确定性 volume 名写入 storage 的中间态新版本的处理策略是检测到该 checkpoint 且缺少 workspace claim 时按旧命名规则恢复 claim以同阶段 CAS 原子补写 storage继续安装归档claimed阶段仍使用 generation0的新命名规则。这一路径保证了升级过程中不丢卷、不重复建卷。镜像环境变量边界AGENT_SANDBOX_OPENSANDBOX_IMAGE是 OpenSandbox唯一的运行态镜像配置入口必须配置完整镜像地址包括 tag。AGENT_SANDBOX_OPENSANDBOX_IMAGE_REPO与AGENT_SANDBOX_OPENSANDBOX_IMAGE_TAG已移除不再作为兼容回退启用opensandbox时缺少完整镜像变量必须阻止服务启动避免运行到一半才发现镜像缺失。volume 删除边界命名与归属分离claimName由 app 生成并持久化volume-manager不恢复VM_VOLUME_NAME_PREFIX配置也不参与命名或资源归属判断volumeNamePrefix只用于生成新 generation的claimName删除时直接使用 Mongo 中持久化的完整claimName不依赖当前 prefix 配置——这样配置变更不会阻断旧 PVC 的清理Kubernetes 和 Docker driver 不写入或检查 managed label只保留名称合法性、幂等删除以及 Kubernetes UID precondition 等底层资源生命周期约束。验证与完成度设计文档标注状态为已完成并给出验证结论volume-manager 与 Sandbox service 相关测试通过TypeScript、构建和格式检查通过变更通过 ESLint、Prettier 和git diff --checkTODO 列表中 running touch storage CAS、旧targetEnsuredcheckpoint 恢复路径、镜像环境变量兼容层、完整 claimName 删除调用、并发/兼容/权限边界单元测试、全量测试与差异检查均已勾选完成。结合仓库源码可验证的实现事实包括K8sVolumeDriver.ts 的readPvc/waitForPvcGenerationEnd/ensure/remove与设计完全对应archive.ts 的归档状态机与 resource.ts 的删除状态机均落实了双 checkpoint 语义。小结OpenSandbox 的 PVC 生命周期修复本质上是一次以 UID 为 generation 锚点、以 API 对象生命周期为完成标准的重构volume-manager 通过absent / active(uid) / deleting(uid)三态归一和 UID precondition 保证不误删、不早删、不把 Terminating 对象当作可用资源Sandbox 生命周期通过providerDeleted / volumeDeleted双 checkpoint 保证归档中断可恢复restore 将 volume 配置获取推迟到 lease 与 claim 之后同时用严格的版本同步发布边界和配置迁移路径保证升级安全。这套设计对任何在 Kubernetes 上管理有状态沙箱/工作负载的生命周期代码都有直接的借鉴意义。【免费下载链接】FastGPTFastGPT is a knowledge-based platform built on the LLMs, offers a comprehensive suite of out-of-the-box capabilities such as data processing, RAG retrieval, and visual AI workflow orchestration, letting you easily develop and deploy complex question-answering systems without the need for extensive setup or configuration.项目地址: https://gitcode.com/GitHub_Trending/fa/FastGPT创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表