深入理解 OverlayFS:用分层的方式重新组织 Linux 文件系统
深入理解 OverlayFS:用分层的方式重新组织 Linux 文件系统
在我第一次真正接触 OverlayFS 时,它给我的感觉是——“复杂得像魔术,简单得像贴膜”。
文件系统这种东西,本来就该是稳稳当当的,不应该随便动。但 OverlayFS 偏偏反其道而行之:它不改底层数据,不动磁盘原本结构,只是用一个“叠加层”的方式,把多个目录合在一起,变成一个统一的挂载点,像给文件系统加了一层透明胶膜。
后来我才明白,Docker 镜像的分层、容器写时复制、系统无损更新、Rootfs 临时叠加、LiveCD 的持久化……这些我们以为“理所当然”的能力,其实都有 OverlayFS 的影子。
所以这一篇博客,我会从“原理—路径解析—写时复制—白名单文件—应用场景”这条主线,把 OverlayFS 的运行机制讲到你能真正理解其内部逻辑,而不是停留在“知道怎么用”的表层。
文章比较长,但如果你想真正了解为什么 OverlayFS 能成为 Linux 主流的联合文件系统实现,这五千字不会浪费你的时间。
一、OverlayFS 要解决的核心问题:多层目录合并
先从最朴素的问题说起:我们能不能把多个目录叠成一个?
例如:
lower1/bin/lib/
lower2/etc/
upper/home/
work/
我们想要一个最终呈现给用户的目录:
merged/bin/lib/etc/home/
这些目录分别来自不同的 source,但 merged 看起来就像一个真实的文件系统。
这就是 OverlayFS 的作用:
让若干目录在逻辑上叠加成一个可以正常读写的文件系统。
更进一步:
- 层与层之间有优先级(上层覆盖下层)
- 上层可写,下层只读
- 删除并不是“真的删除”,而是用 whiteout 白名单标记
- 修改下层文件,会复制到上层再改
- 不改变下层的来源目录内容
这些行为,是性能和可维护性之间的妥协,也是 OverlayFS 之所以能够支撑 Docker 的原因。
二、OverlayFS 的三层结构(最关键的基础)
OverlayFS 主要有三个核心目录:
1. lowerdir:只读层(可有多层)
它可以包含多个目录:
lowerdir=lower1:lower2:lower3
优先级从左到右,最左边最高。
2. upperdir:可写层
所有写入都会发生在 upperdir。
这意味着:
- 修改下层文件 = 把文件复制一份到 upperdir
- 删除下层文件 = upperdir 产生 whiteout 标记
- 创建新文件 = upperdir
3. workdir:工作层(必须与 upperdir 同一文件系统)
OverlayFS 会在其中放置运行状态记录。
用户一般不需要关心它。
挂载示例
mount -t overlay overlay \-o lowerdir=/lower1:/lower2,upperdir=/upper,workdir=/work \/merged
完成后 /merged 就是最终我们看到的合成视图。
三、路径解析:OverlayFS 内部最精妙的逻辑
当我们访问一个文件,如:
/merged/etc/passwd
OverlayFS 的查找顺序是:
- 检查 upperdir 中是否存在同名文件或目录
- 如果没有,则沿着 lowerdirs 从左到右查找
- 如果 upperdir 中有 whiteout 文件,则视为已删除
- 找到后直接返回
这个查找过程在内核中通过 overlay_lookup() 实现。
举例:
lower1/etc/passwd # 最新配置
lower2/etc/passwd # 较旧版本
upper/etc/passwd # 用户编辑过
最终呈现的 /merged/etc/passwd 一定来自 upper。
而如果用户删除了 /merged/etc/passwd:
upper/etc/.wh.passwd # whiteout 标记
此时 merged 中不再显示 passwd 文件,即使 lowerdir 中还存在。
四、写时复制(Copy-on-Write):OverlayFS 的核心性能机制
如果用户编辑一个来自 lowerdir 的文件,OverlayFS 并不会修改 lowerdir,因为 lowerdir 是只读层。
它会:
- 把该文件复制到 upperdir
- 修改 upperdir 中的文件
- merged 显示的始终是 upperdir 中的文件
示例:
lowerdir/etc/hosts
用户执行:
vim /merged/etc/hosts
OverlayFS 做的事情是:
cp lowerdir/etc/hosts upperdir/etc/hosts
编辑 upperdir/etc/hosts
最终 lowerdir 完全不受影响。
为什么要这样?
- lowerdir 通常来自镜像、ISO、只读镜像层
- 如果直接改 lowerdir 就无法保证层之间的独立性
- 不同用户可以共用 lowerdir
这个模型就像 Docker 镜像层和容器层之间的关系。
五、Whiteout(白名单文件):删除的本质
当我们删除一个来自 lowerdir 的文件时:
rm /merged/etc/hosts
OverlayFS 并不会真的去 lowerdir 删除,而是在 upperdir 创建一个特殊文件:
upper/etc/.wh.hosts
这个文件告诉 OverlayFS:
“不要再显示 lowerdir 的 hosts 文件了,它被删除了。”
所以 merged 层看起来就像真的删除了。
目录删除也是类似过程。
理解 whiteout 是理解 OverlayFS 最关键的一环,因为没有 whiteout 机制,就无法保证“下层不动,上层改变”的一致视图。
六、多层 lowerdir:Docker 镜像分层的基础
OverlayFS 支持多个 lowerdir,并允许它们以“从左到右”的方式叠加:
lowerdir=a:b:c
实际顺序:
- a 覆盖 b
- b 覆盖 c
Docker 镜像层正是这种机制:
ubuntu-base
apt-installed-libs
python-env
custom-layer
container-upperdir
所有镜像层只读,最后一层容器层可写(upperdir)。
这种结构让:
- 镜像层复用非常方便
- 多容器共享只读层
- 存储空间极大节省
七、OverlayFS 如何处理重命名
rename() 是 Linux 文件系统中最复杂的操作之一。它必须同时保证:
- 原子性
- 数据一致性
- 多层的写时复制逻辑
如果你 rename 一个来自 lowerdir 的文件:
mv /merged/etc/hosts /merged/etc/hosts.bak
OverlayFS 必须:
- 复制 hosts 到 upperdir
- 将 hosts.bak 也创建在 upperdir
- 创建 whiteout 标记隐藏 lowerdir/hosts
这个过程在 overlayfs_rename() 中实现,逻辑非常繁琐。
八、目录合并:所谓“联合挂载”的真核心
当不同层中存在目录时,OverlayFS 会把它们逻辑上合并成一个。
例如:
lower1/etc/a.conf
lower2/etc/b.conf
upper/etc/c.conf
最终 merged 会显示:
/etc/a.confb.confc.conf
这并不是简单的 copy,而是在访问时动态决定。
因此 overlay 的目录是“虚拟的”,直到访问时才实际投影出来。
九、OverlayFS 的 6 个典型应用场景
1. Docker / Podman / LXC 容器写时复制层
Docker 容器的文件系统分层全部依赖 OverlayFS(或 overlay2)。
容器文件修改只发生在 upperdir,而镜像层永远保持不变。
2. LiveCD 持久化运行环境
LiveCD 本质是只读镜像。
通过 OverlayFS,用户可以有:
- 上层可写
- 下层只读
- 重启即可丢弃(upperdir 放 tmpfs)
3. Linux 系统回滚功能(事务式 rootfs)
像 openSUSE 的 transactional-update 和 Fedora Silverblue 都会用到 Overlay。
4. Rootfs 临时叠加(initramfs 中常用)
早期启动阶段需要扩展根文件系统,OverlayFS 是最简单的方法。
5. 安全实验环境(沙箱文件系统)
所有修改都写到 upperdir,退出时只要删除 upperdir,就能恢复初始状态。
6. 版本化文件系统设计
多层 lowerdir 本身就是天然的版本链条。
十、性能分析:OverlayFS 为什么比 AUFS、UnionFS 更受欢迎
OverlayFS 的优势:
- 整合进 Linux 主线(更稳定)
- 实现比 aufs、unionfs 更简单
- copy-up 性能优势明显(页粒度而不是整文件复制)
- 更好的元数据一致性
- 容易被文件系统如 ext4、xfs 支持
Docker 早期使用 AUFS,但最终迁移到 overlay2,就是因为 OverlayFS 更轻量、主线维护、错误更少。
十一、OverlayFS 的限制
即便 OverlayFS 很强大,也有一些限制(使用时必须了解):
1. upperdir 和 workdir 必须在同一文件系统
不能跨分区。
2. 不适合大量文件修改
频繁 copy-up 会导致性能下降。
3. 对某些文件系统属性支持有限
例如 xattrs、chattr、某些安全标签等可能行为不完全一致。
4. 不适合数据库类写密集应用
容器内跑 MySQL / PostgreSQL 最佳实践通常是将数据目录挂载真实文件系统。
十二、从内核角度理解 OverlayFS 的数据结构
OverlayFS 在内核中主要使用以下结构:
- overlay_inode
- overlay_dentry
- overlay_super
- ovl_entry
- ovl_dir_cache
其中最关键的是 ovl_entry:
struct ovl_entry {struct dentry *upperdentry;union ovl_dir __rcu *lowerdirs;unsigned numlower;
};
这就是多层映射关系的内核实体。
一个 merged 的文件其实对应多个实际 dentry(upper +多个 lower)。
十三、一个完整实践示例(真实可复现)
下面演示一个真实可复现的 OverlayFS。
1. 准备目录
mkdir lower1 lower2 upper work merged
2. 写入文件
echo lower1-a > lower1/a
mkdir lower1/etc
echo l1-hosts > lower1/etc/hostsecho lower2-b > lower2/b
mkdir lower2/etc
echo l2-resolv > lower2/etc/resolv.conf
3. 挂载
mount -t overlay overlay \-o lowerdir=lower1:lower2,upperdir=upper,workdir=work \merged
4. 查看
ls merged
# a b etc
5. 修改 lower 文件
echo modify >> merged/a
upper/a 会出现,lower1/a 不变。
6. 删除 lower 文件
rm merged/b
upper/.wh.b 会出现。
整个流程充分体现了 OverlayFS 的机制。
十四、总结:OverlayFS 让文件系统进入“分层时代”
OverlayFS 的设计哲学非常现代:
- 下层不可变(immutable)
- 上层可变但可抛弃(ephemeral)
- 多层叠加
- 写时复制提高效率
- whiteout 保证一致性
无论你是在研究容器底层,还是在构建系统级工具,只要你理解了 OverlayFS 的结构、路径解析逻辑、whiteout、copy-up,这套联合文件系统的思想会成为你理解现代 Linux 的一把钥匙。
OverlayFS 不只是一个文件系统,它是一种把“文件组织方式”从线性时代带入“分层时代”的哲学。
它让我们可以自由组合系统、构建可回滚的环境、构建只读镜像、构建多版本 rootfs、构建轻量可写层,从而支撑起整个容器时代。
希望这篇文章能让你真正理解 OverlayFS,而不仅仅是会用它。
