快照、commit、diff 与 export

定义

工作负载的文件系统除了运行期读写之外,还支持四类产品操作。它们经常被放在同一组 CLI 下,但语义不可互换。

操作 输入 输出 目的
snapshot 一个已停止(或按契约可静默)的 box 版本化、可恢复的文件系统检查点 以后把该 box 恢复到这一时刻
commit 一个 box 的当前根文件系统 新的镜像 把实例变成可再次 run 的镜像
diff 一个 box 与其启动基线 文件增删改列表 审查运行期改动了什么
export 一个 box 的根文件系统 tar 等归档 把当前根拷贝到宿主,而不创建镜像元数据

此外还有内存级的 snapshot-fork,属于运行中的 MicroVM,不是本页的文件系统检查点。

问题背景

容器可写层默认是易失的。开发与运维仍然需要三种能力:看清改动、把改动变成新镜像、在不创建镜像的情况下留下可回滚点。若只用 cp 往宿主拷文件,则丢失元数据与可复现的恢复路径。把这四类操作做成一等命令,是为了让「文件系统历史」进入产品状态,而不是散落在临时目录。

机制说明

snapshot:检查点

a3s-box snapshot create data-app --name checkpoint-1 把干净的文件系统世代克隆到完整性受检的 bundle,并在恢复时给出私有可写克隆。Box 在 macOS 上的当前实现针对干净的 raw ext4 世代,创建、恢复与删除不要求宿主挂载客户机磁盘,恢复后的 box 也不依赖快照存储继续存在。快照 freezer 会持久化「运行时变更是否已应用」,以免崩溃恢复重放已经完成的 thaw。

commit:实例镜像化

commit 读取当前根(含可写层与已应用的修改),写出新的镜像配置与层。此后应通过新镜像启动,而不是假设旧 box 会永远活着。commit 不会自动代替卷:数据库若只写在卷里,未包含进根的数据不会进入新镜像。

diff:相对基线的变化

diff 需要一条基线。Box 在工作负载启动前捕获 guest 可见的 Linux 元数据,并由宿主原子发布;之后的启动不再重扫整个 rootfs。比较的是「现在」与「那条基线」,不是与 registry 里的原镜像做层哈希对比。日志脏磁盘在恢复完成前会被拒绝参与维护操作。

export:归档

export 把当前根打包给宿主。它不注册为镜像,因此没有标签与配置对象。适合取证或迁移到不理解 Box 快照格式的工具。macOS 上,干净停止的 box 通过一次性、无网络的维护 MicroVM 提供 diff / export / commit:维护 init 从临时目录根启动,只读附加用户磁盘,以 ro,noload 挂载,只暴露归档、心跳与关机控制。

在 Box 中的位置

  • 核心类型:src/core/src/snapshot.rsrootfs_baseline.rs
  • 运行时:src/runtime/src/snapshot/local_execution/snapshot.rs
  • CLI:snapshot.rscommit/diff.rsexport.rs
  • 客户机基线:src/guest/init/src/diff_baseline.rs
  • 设计:docs/guest-native-rootfs-design.mddocs/cow-snapshot-fork-design.md

验证命令

a3s-box volume create data
a3s-box run -d --name data-app -v data:/data alpine:3.20 -- sleep 3600
a3s-box exec data-app -- sh -lc 'echo x > /tmp/only-in-writable.txt'
a3s-box stop data-app
a3s-box snapshot create data-app --name checkpoint-1
a3s-box diff data-app

/tmp/only-in-writable.txt 应出现在 diff 中;卷 data 的内容则属于卷,不因 snapshot 名称而自动并入镜像。

相关与易混

  • 相关:rootfs卷与挂载镜像与层Warm pool 与 snapshot-fork
  • 易混:snapshot 恢复的是文件系统世代,不是 Kubernetes VolumeSnapshot。commit 产生镜像,不产生可回滚的命名检查点。save / load 作用于镜像归档,作用于仓库对象,而不是正在运行的根。