Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

系统架构总览

本章用一张图说清楚 K3s 运行时模块在整个系统中的位置,以及各个组件之间的关系。


1. 整体系统组成

整个智能体商店系统由四个主要部分组成:

graph TB
    subgraph 用户侧["🖥️ 用户侧(macOS 本地)"]
        User["用户"]
        Helper["Helper(本地桥接服务)"]
        UI["Web UI(浏览器界面)"]
    end

    subgraph 后端控制面["☁️ 后端控制面"]
        API["HTTP API 路由层"]
        Service["应用服务层<br/>ApplicationService"]
        Store["状态存储<br/>FileBackedStore"]
        DataGateway["数据访问网关<br/>统一查库/写库"]
        PackageCatalog["Agent 包目录索引"]
        ProfileCatalog["运行时配置索引"]
    end

    subgraph K3s运行时["⚙️ K3s 运行时模块"]
        Orchestrator["K3s 编排器<br/>K3sOrchestrator"]
        K3sAPI["Kubernetes API"]
    end

    subgraph 执行层["📦 容器执行层(K3s 集群)"]
        DEP1["Deployment(长驻部署)"]
        SVC1["Service(网络服务)"]
        Pod1["Pod(容器组)"]
        AgentCore["agentcore<br/>(智能体核心运行时)"]
    end

    User -->|"发送消息/上传文件"| UI
    UI -->|"HTTP 请求"| Helper
    Helper -->|"转发 API 请求"| API
    API -->|"调用"| Service
    Service -->|"读写状态"| Store
    Service -->|"统一数据访问"| DataGateway
    Service -->|"查询包"| PackageCatalog
    Service -->|"查询配置"| ProfileCatalog
    Service -->|"提交运行"| Orchestrator
    Orchestrator -->|"创建资源"| K3sAPI
    K3sAPI -->|"调度执行"| DEP1
    DEP1 -->|"创建"| Pod1
    SVC1 -->|"路由流量 :8081"| Pod1
    Pod1 -->|"运行"| AgentCore

各组件职责一句话总结

组件职责
Helper(本地桥接服务)运行在用户 macOS 上,提供 Web UI,将用户操作转化为 API 请求发送到后端
后端控制面(Backend)接收请求、管理会话/文件/运行记录、组装启动计划、持久化所有状态,并统一负责数据库查询与写入
K3s 编排器(K3sOrchestrator)将启动计划渲染成 Kubernetes 资源(Deployment + Service + ConfigMap + Secret),提交到集群,监控运行状态
K3s 集群真正调度和运行容器的底层系统
agentcore(智能体核心运行时)容器内的执行程序,负责推理、工具调用、文件读写

2. 控制面统一数据访问

当前方案有一个必须先记住的原则:

所有数据库访问都由 Backend 负责,容器内的 Worker 不直接连接数据库。

这包括三类数据:

  1. 会话数据库:对话历史、RunRecord、SessionRuntimeState 等
  2. 检查点数据库:checkpoint、恢复快照、执行中间状态
  3. 业务数据库:PostgreSQL / MySQL / Redis / 向量库等外部数据源

对应关系如下:

graph LR
    H["Helper / 用户请求"] --> B["Backend"]
    W["Worker / agentcore"] -->|"协议请求"| B
    B -->|"查询 / 写入"| DB1["会话数据库"]
    B -->|"查询 / 写入"| DB2["检查点数据库"]
    B -->|"查询 / 写入"| DB3["业务数据库"]

这样设计有四个直接好处:

  • 安全更简单:数据库凭据只保留在 Backend,不进容器
  • 协议更稳定:Worker 只需要理解“协议”,不需要关心数据库类型和地址
  • 审计更集中:所有查库、写库都可以统一记录和限流
  • 同步/异步更清晰:哪些操作必须等结果,哪些可以异步流式返回,都由 Backend 统一定义

3. 两层架构:控制面 + 执行面

当前系统采用**“单进程控制面 + K3s 执行面”**的架构:

graph LR
    subgraph 控制面["控制面(Backend 进程)"]
        direction TB
        A1["接收 API 请求"]
        A2["管理会话、文件和数据库访问"]
        A3["组装 LaunchPlan(启动计划)"]
        A4["持久化运行记录与检查点"]
    end

    subgraph 执行面["执行面(K3s 集群)"]
        direction TB
        B1["创建 ConfigMap / Secret / Deployment / Service"]
        B2["调度 Pod 到节点"]
        B3["拉取镜像、挂载目录"]
        B4["启动 agentcore,通过协议与 Backend 通信"]
    end

    控制面 -->|"LaunchPlan"| 执行面
    执行面 -->|"运行状态 / WebSocket 事件"| 控制面

关键理解:后端(Backend)不会直接创建容器。它只负责创建四种“声明式资源“——ConfigMap(配置映射)、Secret(密钥资源)、Deployment(部署)、Service(服务)。真正把这些声明变成运行中容器的,是 K3s 系统内部的控制器和节点代理程序。

同时,Backend 也不会把数据库直接暴露给容器。容器只拿到:

  • 运行上下文文件(run-context.json
  • 必要的文件挂载
  • 与 Backend 通信所需的协议地址

4. 同步 / 异步的总分工

从系统层面看,操作被分成三类:

操作语义例子
同步发起方必须等待结果创建会话、读取会话详情、Worker 请求 Backend 查库
异步发出后继续执行,结果稍后返回流式输出、状态变化、心跳、工具进度
混合提交同步,执行异步创建 Run、取消 Run、ask_user 等待用户回复

详细矩阵见:同步与异步语义


5. 代码模块分层

从代码角度看,K3s 相关的逻辑分成了两个独立的层:

graph TB
    subgraph Backend应用层["Backend 应用层 (app crate)"]
        SVC["service.rs<br/>应用服务层"]
        K8S["k8s/mod.rs<br/>适配层"]
        DOM["domain.rs<br/>领域类型"]
    end

    subgraph K3s运行时层["K3s 运行时 crate"]
        LIB["lib.rs — 编排器门面"]
        TYPES["types.rs — 输入输出类型"]
        APPLY["apply.rs — 资源创建与清理"]
        INSPECT["inspect.rs — 状态观察"]
        WL_WK["workload_worker.rs — SessionWorker 渲染"]
        VOL["volumes.rs — 卷布局"]
        PKG["package_bundle.rs — ConfigMap/Secret 渲染"]
        NAM["naming.rs — 资源命名"]
        SB["service_bindings.rs — 外部服务绑定"]
    end

    SVC -->|"组装 LaunchPlan"| K8S
    K8S -->|"转换成 crate 输入"| LIB
    LIB --> APPLY
    LIB --> INSPECT
    LIB --> WL_WK
    LIB --> VOL
    LIB --> PKG
    LIB --> NAM
    WL_WK --> VOL
    WL_WK --> PKG
    WL_WK --> NAM

为什么要分成两层

这种分层设计带来三个明确的好处:

  1. 职责清晰:Backend 可以独立演进会话管理、权限校验等业务逻辑,不需要了解 Kubernetes API 的细节。
  2. 可替换执行层:如果未来需要把 K3s 替换成其他容器编排系统,只需要替换 K3s 运行时 crate,Backend 的代码基本不用改。
  3. 便于并行开发:不同开发者可以同时修改不同模块而不互相冲突。

6. 适配层的桥梁作用

Backend 和 K3s 运行时之间通过一个适配层k8s/mod.rs)连接。适配层只做四件事:

序号工作内容方向
1把 Backend 的进程配置(AppConfig)转换成编排器配置Backend → K3s
2把 Agent 包、运行时模板、挂载授权转换成 K3s crate 能理解的 DTO(数据传输对象)Backend → K3s
3把 K3s crate 返回的渲染结果、集群状态、运行状态转换回 Backend 领域对象K3s → Backend
4把 K3s crate 的错误映射成 Backend 的 HTTP/API 错误K3s → Backend

7. 一次运行涉及的 Kubernetes 资源

每次用户发起一个运行请求,K3s 编排器会创建以下四种资源:

graph TB
    subgraph 一次Run的K8s资源["一次 Run(运行)对应的 K8s 资源"]
        CM["ConfigMap<br/>📋 agent-pkg-&lt;run-id&gt;<br/>存放 Agent 包的文本文件"]
        SEC["Secret<br/>🔒 agent-env-&lt;run-id&gt;<br/>存放 API 密钥等敏感信息"]
        DEP["Deployment<br/>⚙️ agent-worker-&lt;run-id&gt;<br/>定义长驻 Worker 容器"]
        SVC["Service<br/>🌐 agent-worker-svc-&lt;run-id&gt;<br/>暴露 8081 控制端口"]
        POD["Pod<br/>📦 由 Deployment 自动创建<br/>运行 agentcore 的容器"]
    end

    CM -->|"挂载为文件目录"| POD
    SEC -->|"注入为环境变量"| POD
    DEP -->|"自动创建"| POD
    SVC -->|"路由 :8081 流量"| POD

重要:Backend 只负责创建前四个(ConfigMap、Secret、Deployment、Service)。Pod(容器组)是由 Kubernetes 的 Deployment Controller(部署控制器)自动创建的,Backend 不直接操控 Pod。Deployment 通过 OwnerReference(所有者引用)级联管理所有关联资源——删除 Deployment 会自动清理 Service、ConfigMap 和 Secret。


8. 当前部署模型

当前系统采用本地部署 + 单节点 K3s 模式:

  • 用户的本地机器就是宿主机——Backend 进程、K3s 集群、Helper 前端都运行在同一台机器上
  • 用户通过本机浏览器访问 Helper 提供的 Web UI
  • 所有工作区文件和会话状态存储在本机磁盘,容器通过 hostPath 直接读写
graph LR
    subgraph LOCAL["用户的本地机器"]
        H["Helper + Web UI<br/>(本地前端)"]
        B["Backend 进程<br/>(本地后端)"]
        K["K3s 集群<br/>(本地容器引擎)"]
        D["本地磁盘<br/>uploads / workspaces / sessions"]
    end

    H -->|"localhost"| B
    B -->|"Kubernetes API"| K
    B -->|"读写文件"| D
    K -->|"hostPath 挂载"| D

本地部署的优势

  • 零网络延迟:Helper → Backend → 容器全部通过 localhost 通信
  • 文件无需传输:用户的本地文件可以直接通过 hostPath 挂载进容器
  • 部署简单:用户只需安装一次,无需维护远程服务器
  • 数据私密:所有数据留在用户本地机器,不经过网络

未来扩展:如果要支持远程部署或多节点集群,需要把文件存储从本地磁盘升级为共享存储(如 PVC 或网络文件系统),后续章节会详细分析这一点。


下一步

理解了整体架构后,请继续阅读 运行生命周期 了解一次运行从开始到结束的完整流程。