Skip to main content

---

  1. ---
    title: DSec 深潜:从 create() 到沙盒跑起来
    subtitle: 四条路径 · 事实核查 · 实现细节
    source: arXiv 2609.22978v1 精读
    theme: auto
    template: sheet
    ---
    
    这一页把论文第 3、5、6、7 节串成四条路径:控制、数据、内存、抢占。每条路径都标了出处,并把论文事实与解读推断分开。
    
    ## 事实核查:转述 vs 论文
    
    逐条对照 arXiv:2609.22978,多数说法准确,个别需要修正。
    
    | 说法 | 判定 | 论文口径 |
    | --- | --- | --- |
    | 生产规模:约 160 节点、30K 核、250 TB、380K 并发、5K 每秒、3M 每天 | ok | §2.4;指每个规模单元,多个单元共享同一套 3FS |
    | CPU 超卖超过 50 倍 | warn | 论文未给该数字;只给九成沙盒 ≤5% 与单节点密度 |
    | 容器直接跑在宿主机 | warn | 容器与 FnCall 跑在 QEMU/libvirt 虚拟机内,多一层隔离 |
    | 四种后端;FnCall 复用预建容器 | ok | §2.2;FnCall 不走 aether 与 chronus |
    | EROFS 元数据本地、数据在 3FS、写留本地 | ok | §5.3;另有层折叠与 file-backed mount |
    | OverlayBD 与 ublk 存储已开源 | ok | §7;Rust 版在 AgentENV 仓库 |
    | Rollout 解耦与 pause/resume | ok | §6.2、§6.3 |
    | 评测未验证模型能力提升 | ok | §8 只评四个基础设施机制 |
    
    ## 一次 create 请求的全景
    
    信任侧与不可信侧只有一条通道:apiserver。
    
    ```flow LR
    (libdsec) -> IAM: 鉴权与配额
    IAM -> Placement: 批准后选节点
    Placement -> Watcher: 拉取健康与负载快照
    Placement -> apiserver: 返回目标节点
    apiserver -> edge: 转发,沙盒 ID 含 owner edge
    edge -> (容器 / 微虚拟机 / Full VM): 启动运行时
    edge -> aether -> chronus: 会话与命令通道
    


    - apiserver 不保存沙盒状态,任意实例可直接路由。
    - placement 先按能力过滤,再在随机样本里选最闲节点。
    - edge 做本地容量终审,拒绝时由上层改选。
    - FnCall 走旁路,不经过 aether 与 chronus。

    ## Path A 控制路径

    
    participants: libdsec, IAM, Placement, Watcher, apiserver, edge, aether, chronus
    == 创建 ==
    libdsec -> IAM: create 请求
    IAM --> libdsec: 鉴权与配额通过
    libdsec -> apiserver: 创建沙盒
    apiserver -> Placement: 请求选节点
    Placement -> Watcher: 集群快照
    Placement --> apiserver: 目标 edge
    apiserver -> edge: 转发创建请求
    edge -> edge: 本地容量终审
    edge -> aether: 启动代理
    aether -> chronus: 建立 shell 会话
    edge --> libdsec: sandbox ready
    == 运行 ==
    libdsec -> apiserver: run_shell
    apiserver -> edge: 按 ID 直接路由
    edge -> aether: Unix socket 或 vsock
    aether -> chronus: 定位或新建会话
    chronus --> aether: stdout 与退出码
    


    aether 是每沙盒代理;chronus 是每会话 shell 抽象,可并发多个。

    ## Path B 数据路径

    3FS 擅长大的顺序 I/O,弱于小的随机 I/O。读写分工由此决定。

    
    group 容器路径: 容器运行时, OverlayFS 组合, 本地元数据
    (容器运行时) -> OverlayFS 组合: lower 为 EROFS 只读层
    OverlayFS 组合 -> 本地元数据: 启动前预取
    OverlayFS 组合 -> [(3FS 数据)]: 按需批量读
    group 微虚拟机路径: 微虚拟机运行时, ublk 块设备, 本地二级缓存
    (微虚拟机运行时) -> ublk 块设备: OverlayBD 可写 ext4
    ublk 块设备 -> [(3FS 数据)]: 256 KiB 块按需读
    ublk 块设备 -> 本地二级缓存: 页缓存淘汰后兜底
    


    | 原则 | 做法 |
    | --- | --- |
    | 写留本地 | 可写层放节点本地盘,避开 3FS 的小写惩罚 |
    | 读按需且批量 | 只读数据按需读,内核预读合并成大请求 |
    | 元数据留本地 | EROFS 多设备模式分离元数据与数据 |

    - 相邻层合计不超过约 3 GB 时离线折叠成一对镜像,保留 whiteout 语义。
    - 容器侧用 file-backed mount,去掉 loop 设备映射层。
    - 微虚拟机侧:EROFS 只读层加 OverlayBD 可写盘,经 ublk 暴露给 guest。

    ## Path C 内存路径

    微虚拟机有两类内存浪费:宿页缓存重复、guest 空闲页不归还。

    
    (guest 读只读层) -> virtio-pmem 与 DAX: 直接映射宿主页
    virtio-pmem 与 DAX -> 宿主页缓存: 多个微虚拟机共享一份
    (guest 冷页) -> DAMON: 采样识别冷页
    DAMON -> buddy 分配器: 走内核回收路径
    buddy 分配器 -> balloon 空闲页报告: 报告中释放页
    balloon 空闲页报告 -> 宿主: MADV_DONTNEED 释放内存
    


    | 机制 | 效果 | 代价与边界 |
    | --- | --- | --- |
    | virtio-pmem + DAX | 峰值宿主内存下降 40.2% | 冷访问同步缺页;guest 元数据约为容量 1/64 |
    | DAMON + balloon 空闲页报告 | 时间累计内存下降 21.2% | 单独使用峰值内存基本不变 |
    | 两者组合 | 总体内存消耗最低 | 峰值 CPU 从 26.5% 升到 41.4% |

    生产配置:只读 EROFS 层用 DAX,较大的可写盘用 DAMON 与空闲页报告。

    ## Path D 抢占路径

    
    participants: RL 框架, DSec edge, 容器, 微虚拟机
    == 抢占:暂停该任务全部沙盒 ==
    RL 框架 -> DSec edge: pause 请求
    DSec edge -> 容器: docker pause + 回收内存
    DSec edge -> 微虚拟机: 保存快照并终止 Firecracker 进程
    note DSec edge: 内存被回收,执行状态保留
    == 恢复:下一次请求即透明恢复 ==
    RL 框架 -> DSec edge: 新请求
    DSec edge -> 容器: MADV_WILLNEED 预取 + unpause
    DSec edge -> 微虚拟机: 新进程恢复快照
    DSec edge --> RL 框架: 从断点继续,无需重放命令日志
    


    - 状态真源是 worker container 与 agent sandbox,两者都在可抢占 GPU 池外。
    - 旧方案要在恢复时重放命令日志,避免非幂等命令的重复副作用。

    ## 实现细节速览

    
    * 放置策略: power-of-k + 本地在途视图 + edge 终审;用户隔离限制爆炸半径
    * dockerd 改动: 动态插入 EROFS 下层,约 30 行 Go;相邻层可折叠
    * 微虚拟机存储: Rust 版 OverlayBD 与 ublk 库,支持 3FS、OSS、registry
    * 3FS 硬件: 每台存储服务器 20 × 15 TB SSD 与 2 × 400 Gbps RDMA
    * GPU FnCall: MIG 分区 + CPU 编译转发 + 预热进程池
    * 内核: 宿主 Linux 7.0、guest Linux 6.1,全部使用现有机制
    


    ## 下一站:你来选

    
    下一站先拆哪条路径?
    * 数据路径 | EROFS、3FS、OverlayBD 的完整读写分工
    - 控制路径 | 从 create 到 ready 的每个 RPC 与进程
    - 内存路径 | DAX、FPR、QoS 的调参与边界
    - 抢占路径 | pause/resume 的状态一致性
    

    `