本文通过“一个任务只读取部分镜像数据”的例子,浅谈 DSec 的 Scalable Image Distribution and On-Demand Loading(可扩展的镜像分发与按需加载)。

为便于理解,下面以容器的 EROFS 镜像路径为例,不展开 microVM 的块设备实现、配置参数和性能测试。DSec 的设计依据论文 §4.4、§5.3;文末的组件资料用于补充基础概念。

What

先把最容易混淆的一点说清楚:

1
2
3
沙箱已经可以开始运行
≠
整个镜像已经下载到运行节点

DSec 将镜像存放在 3FS(Fire-Flyer File System) 中,让运行节点按需获取镜像数据,而不是先完整下载再启动。

3FS 是共享的分布式文件系统,可以汇聚多台存储节点的容量与带宽。DSec 复用这套已有基础设施,不再单独部署一套镜像分发系统。

可以把两个部分分开理解:

1
2
3
4
5
镜像分发:
由共享的 3FS 为运行节点提供镜像数据

按需加载:
运行节点需要哪些数据,再读取相应部分

所以:

不必先把整套环境搬到本地,才能开始使用其中的一部分。

Why

论文观察到,沙箱需要的镜像种类很多,但单个任务往往只访问镜像中的一小部分内容。

假设每个节点都先下载完整镜像,就可能发生:

1
大量传输 → 本地保存完整镜像 → 实际只用其中一部分

这里浪费的不只是启动等待时间,还有传输、写盘和本地存储空间。

提前把完整镜像下载好,只是把这笔开销提前支付,并没有消除它。

因此,这套方案的目的可以概括为:

不仅让沙箱更早开始运行,也减少为未用到的镜像内容付出的代价。

这里少占的是运行节点上的完整镜像副本空间,不是从 3FS 中删除暂时没有访问的原始数据。

基础 Example

假设把一个镜像的数据部分简化成 8 个区域:

1
A  B  C  D  E  F  G  H

任务启动需要 A、B,后续运行还会读取 E,其他区域不会主动访问。

下面只说明加载顺序,暂不考虑预读;字母与数量均为示意,不是论文中的测试数据。

先完整下载

1
2
3
4
5
6
7
下载 A、B、C、D、E、F、G、H
↓
完成镜像准备
↓
使用 A、B 启动
↓
运行过程中读取 E

即使 C、D、F、G、H 最后没有用到,也已经先传输了。

按需加载

1
2
3
4
5
6
7
先准备镜像元数据
↓
读取启动需要的 A、B
↓
开始运行
↓
运行到需要 E 时,再读取 E

在这个简化例子中,没有必要把其余区域全部拉到本地。

区别就在于:

不是把“下载整个镜像”挪到启动之后,而是不再要求整个镜像都必须下载。

实际系统会按块读取,并可能预读附近的数据,因此不能把“按需”理解为只传输应用明确读取的那几个字节。

How

只看三个配合的动作。

1. 镜像元数据先放本地

先区分两类信息:

1
2
3
4
5
元数据:
目录结构、文件属性、文件内容的位置等信息

文件数据:
文件中真正保存的内容

EROFS 的多设备模式允许将文件数据放到独立的后端中。

DSec 利用这一能力,先把镜像元数据下载到运行节点,把文件数据留在 3FS。

可以把它类比为一本书:

1
2
3
目录与索引 → 先拿到手

具体正文 → 需要哪一部分,再取哪一部分

这样,查找镜像里的文件,不必每走一级目录都去远端读取相应的目录信息。

2. 文件数据按需读取,尽量批量传输

读取只读层的文件内容时,已经缓存在本地的数据可以复用;需要的镜像数据尚未就绪时,再从 3FS 获取。

论文指出,3FS 更适合较大的 I/O。因此,这条路径还利用内核的 readahead(预读),把相邻数据块组织成较大的读取请求。

1
2
3
4
5
需要某段文件内容
↓
读取对应数据块,并可能预读相邻块
↓
供当前和后续读取使用

这里两个动作并不矛盾:

1
2
3
按需:不要求先下载整个镜像

批量:一次读取不必小到只有几个字节

可以简单理解为:

不搬整本书,但也不必每次只取一个字。

3. 运行时写入留在本地

DSec 将容器的可写上层放在节点本地磁盘,避免把写日志等细碎操作都交给 3FS。

这与前面介绍的 OverlayFS 配合:

1
2
3
只读镜像层:提供初始内容

本地可写层:保存运行中的新增和修改

需要修改下层文件时,OverlayFS 按需执行 copy-up,再修改上层副本;不会直接改写共享的只读镜像。

因此,这里不是“所有读写都走远端”,而是将只读镜像数据的获取与运行时写入分开。

一个简单的取舍

按需加载不等于读取没有等待。

根据前面的流程,如果需要的数据还不在本地,当前读取仍然要等数据取回来。

1
2
3
4
5
先完整下载:
先等待整套镜像准备好,再使用

按需加载:
不等整套镜像准备好,但首次读取缺失数据时可能等待

省掉的是不必要的完整准备,不是所有的数据访问开销。

记忆图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
                 运行节点
│
容器访问合并后的目录
│
OverlayFS
│
┌─────────────┴─────────────┐
▼ ▼
本地可写上层 EROFS 只读层
保存新增与修改 │
┌───────────┴───────────┐
▼ ▼
本地镜像元数据 所需文件数据
▲
│ 按需读取
│
共享的 3FS

可以简单记成:

1
2
3
4
5
6
7
镜像:共享存放

查找:元数据先准备

读取:需要时成批取

写入:留在本地上层

一句话概括:

镜像保存在共享存储中,运行节点不必先搬来全部内容:先准备查找信息,再按需读取,把自己的改动留在本地。


参考资料:

  1. DeepSeek Elastic Compute (DSec): A Sandbox Infrastructure for Effective Agentic Training at Scale — §4.4、§5.3
  2. 3FS: Fire-Flyer File System
  3. Linux Kernel Documentation: EROFS
  4. Linux Kernel Documentation: Overlay Filesystem
  5. Linux Kernel: Readahead 实现与设计说明