本文通过“多个环境共用一份基础文件”的例子,浅谈 OverlayFS(叠加文件系统)。

为便于理解,下面只讨论“一个只读下层 + 一个可写上层”的常见用法,所有文件操作都通过合并后的目录进行,不展开挂载参数和特殊文件语义。

What

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

1
2
3
基础文件放在只读层
≠
应用看到的整个目录都不能修改

OverlayFS 是 Linux 的一种文件系统,可以把不同的目录树叠加起来,对应用呈现一棵合并后的目录树。

先认识三个名字:

1
2
3
4
5
lowerdir(下层):提供原有文件,作为只读内容使用

upperdir(上层):保存新增文件、修改后的文件和删除标记

merged(合并视图):应用实际访问的目录

所以:

应用看到的是合在一起的文件,实际的数据仍然分别保存在上层和下层。

Why

假设环境 A 和环境 B 使用同一套基础文件,只需要分别修改少量配置。

如果每个环境都先完整复制一份基础文件,就会重复保存大量相同内容。

使用 OverlayFS 后,可以变成:

1
2
3
环境 A:共享基础文件 + A 自己的可写上层

环境 B:共享基础文件 + B 自己的可写上层

不需要提前为每个环境复制整套文件,后续改动又可以分别保存在各自的上层。

因此,它的目的可以概括为:

共同的内容一起用,各自的改动分开存。

基础 Example

假设下层和上层分别包含这些普通文件:

1
2
3
4
5
6
7
lowerdir(下层)
config.txt 内容:mode=default
readme.txt 内容:使用说明

upperdir(上层)
config.txt 内容:mode=debug
result.txt 内容:运行结果

通过 OverlayFS 合并后,应用看到:

1
2
3
4
merged(合并视图)
config.txt 内容:mode=debug ← 来自上层
readme.txt 内容:使用说明 ← 来自下层
result.txt 内容:运行结果 ← 来自上层

同一路径的普通文件,上层版本优先,因此应用读到的是 mode=debug。

这不是把两个 config.txt 的内容拼接起来,也不是把下层文件改成了 mode=debug。 下层的原文件仍然保留。

对于同名目录,通常会合并其中的目录项,让应用能看到来自不同层的文件。

How

只看三个动作。

1. 读取:选择上层或下层的文件

在没有删除标记的情况下,可以简单理解为:

1
2
3
上层有这个文件 → 读取上层版本

上层没有、下层有 → 读取下层版本

只读下层文件,不需要先把它复制到上层。

2. 修改:先复制到上层,再修改

假设 readme.txt 目前只在下层,应用准备往里面追加一行文字。

OverlayFS 不会直接修改下层,而是先把文件复制到上层,再对上层副本进行修改。这个过程称为 copy-up(向上复制)。

1
2
3
4
5
6
7
8
9
10
11
下层 readme.txt
│
│ copy-up
▼
上层 readme.txt
│
│ 追加文字
▼
上层保存修改后的版本

下层原文件保持不变

之后再修改这个文件,就可以继续操作上层副本。

复制的是需要修改的文件,不是整个下层目录树;上层保存的是文件副本,也不只是那一行新增文字。

如果是新建文件,则直接创建在上层。

3. 删除:记下“不要再显示这个文件”

假设应用删除一个仍然存在于下层的文件。

因为不能修改下层,OverlayFS 会在上层记录一个 whiteout(删除标记),表示这个名字已经被删除。

1
2
3
4
5
下层:原文件仍然存在

上层:记录对应的删除标记

merged:不再显示这个文件

所以:

从合并视图中删除下层文件,不等于真的删除了下层的原文件。

记忆图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
            应用
│
▼
merged:合并视图
│
OverlayFS
│
┌───────┴───────┐
▼ ▼
upperdir lowerdir
可写上层 只读下层
│ │
新增、修改、 原有基础文件
删除标记 保持不变

可以简单记成:

1
2
3
4
5
读:选择可见的上层或下层文件

改:必要时复制到上层,再修改

删:下层文件用上层标记隐藏

OverlayFS 也支持多个下层。因此,基础环境、工作区和工具包可以分别准备,再一起组合到应用看到的目录树中。

一句话概括:

把多层文件合起来看,把运行中的改动留在自己的上层。


参考资料:

  1. Linux Kernel Documentation: Overlay Filesystem
  2. Docker Documentation: OverlayFS Storage Driver
  3. Docker Documentation: Storage Drivers — The Copy-on-write Strategy