Loading

Overlay 联合文件系统详解


一、Overlay 联合文件系统的三层架构

在上一节中,我们了解到 UnionFS(联合文件系统)可以把多个目录联合到一起挂载成一个大目录给容器使用。Overlay 就是 UnionFS 的一种具体实现,它的架构主要分为三层

层级 名称 别称 读写属性 作用
最底层 lowerdir 镜像层 只读 存放 rootfs,即基础的文件系统内容
中间层 upperdir 容器层 可读写 记录容器对文件的所有增删改操作
最上层 merged 展现层 lowerdirupperdir 联合挂载后的合并结果
  • lowerdir(镜像层):只要某个目录被指定为 lowerdir,它就变成只读的了。这一层指定的目录其实就是我们之前说的那个 rootfs,所以又称为镜像层。
  • upperdir(容器层):只要某个目录被指定为 upperdir,它就是可写的。容器执行的文件写入、修改、删除操作,结果都会体现在这一层指定的目录里,所以又称为容器层。
  • merged(展现层):这一层本身不存放任何文件,它的内容全部来自于 upperdirlowerdir,是这两层联合挂载、合并之后的结果。我们在容器里面看到的就是 merged 层。

二、从上往下看的"遮挡"原理

在容器内部,我们看到的是 merged 层。理解 merged 层的关键是:从上往下看,upperdir 挡在中间。

具体规则如下:

  • 查看某个文件时,先经过 upperdir,看 upperdir 里有没有这个文件
  • 如果 upperdir没有,就继续往下看到 lowerdir(相当于没有遮挡住)
  • 如果 upperdir,就以 upperdir 里的为准(相当于被遮挡住了,即使 lowerdir 里也有同名文件)

初始状态示例

假设初始时只有 lowerdir 里有文件,upperdir 是空的:

┌─────────────────────────────────────┐
│  merged(展现层)                     │
│  → file1, file2, file3              │
├─────────────────────────────────────┤
│  upperdir(容器层)                   │
│  → (空)                            │
├─────────────────────────────────────┤
│  lowerdir(镜像层,只读)              │
│  → file1, file2, file3              │
└─────────────────────────────────────┘

此时在 merged 层从上往下看:upperdir 里没有任何文件,没有任何遮挡,所以直接看到 lowerdir 里的 file1file2file3


三、三种改动操作在 Overlay 中的体现

1. 修改文件

如果在容器内(即 merged 层)编辑修改了 file2,会发生什么?

  • 不会改动 lowerdir,因为 lowerdir 是只读的,改不了
  • 改动的结果会放到 upperdir 里面,在 upperdir 中产生一个同名文件 file2,里面是修改后的新内容
┌─────────────────────────────────────┐
│  merged(展现层)                     │
│  → file1, file2(已修改), file3       │
├─────────────────────────────────────┤
│  upperdir(容器层)                   │
│  → file2(修改后的新内容)             │
├─────────────────────────────────────┤
│  lowerdir(镜像层,只读)              │
│  → file1, file2(原始), file3         │
└─────────────────────────────────────┘

下次在 merged 层看 file2 时,由于 upperdir 里出现了同名的 file2,遮挡住了 lowerdir 里的 file2,所以看到的就是 upperdir 里修改后的版本。

2. 新增文件

如果在容器内新建了一个文件 file4,这也是改动操作,新增的文件会写到哪里?写到 upperdir,不会改动 lowerdir

┌─────────────────────────────────────┐
│  merged(展现层)                     │
│  → file1, file2(已修改), file3, file4│
├─────────────────────────────────────┤
│  upperdir(容器层)                   │
│  → file2(修改后), file4(新增)      │
├─────────────────────────────────────┤
│  lowerdir(镜像层,只读)              │
│  → file1, file2(原始), file3         │
└─────────────────────────────────────┘

merged 层从上往下看,file4upperdir 里有,直接被 upperdir 挡住了,所以能看到这个新文件。

3. 删除文件

如果在容器内把 file3 删掉了,会发生什么?

  • 不会真正删除 lowerdir 里的 file3
  • 而是在 upperdir 里创建一个特殊的字符设备文件(whiteout 文件),文件名为 file3,代表"已删除"
┌─────────────────────────────────────┐
│  merged(展现层)                     │
│  → file1, file2(已修改), file4       │
├─────────────────────────────────────┤
│  upperdir(容器层)                   │
│  → file2(修改后), file4, file3(whiteout) │
├─────────────────────────────────────┤
│  lowerdir(镜像层,只读)              │
│  → file1, file2(原始), file3         │
└─────────────────────────────────────┘

联合文件系统在 merged 层往下看时,只要看到 upperdir 里有这种特殊的 whiteout 文件,就认为该文件已被删除,在 merged 层中就不再展示 file3。但实际上 file3 并没有被真正删除,它仍然存在于 lowerdir 里。


四、为什么 lowerdir 必须只读?

lowerdir 指定的目录本质就是一个镜像(rootfs),而这个镜像目录有可能同时作为其他容器的 lowerdir 来进行联合挂载。

如果在容器 1 里通过 merged 层把 file3 删了,实际就把 lowerdir 里的 file3 真删了,那其他共享这个 lowerdir 的容器里也会跟着丢失 file3——这就破坏了隔离性。所以 lowerdir 里指定的目录一定是只读的,所有改动都只发生在 upperdir 里面。


五、改动操作总结

操作 Overlay 实际行为 lowerdir 变化
修改文件 upperdir 中创建同名文件,写入修改后内容 不变
新增文件 直接在 upperdir 中创建新文件 不变
删除文件 upperdir 中创建 whiteout 字符设备文件标记删除 不变

六、Overlay 与 Overlay2

在 Docker 容器引擎中,Overlay 有两个版本:

  • overlay:基本只能工作在两层(lowerdir + upperdir)之上,合并成一个 merged 层展示
  • overlay2:在 overlay 基础上做了很多优化,支持更多的层,并且对 inode 的使用做了进一步优化。现在基本都用 overlay2

使用 overlay2 有一个前提条件:内核版本必须至少在 4.0 以上。这也是为什么安装较新版本的 Docker(如 19、20 及以后的版本)时,通常要求先升级内核。

查看当前 Docker 使用的存储驱动

[root@test04 ~]# docker info | grep overlay
 Storage Drive: overlay2
  Network: bridge host ipvlan macvlan null overlay

可以看到,默认的 Storage Driver 就是 overlay2。新版本的 Docker 引擎默认就使用 overlay2,不需要手动修改。如果使用的是老版本且想手动指定,可以在 Docker 的配置文件中添加相应配置项来指定存储驱动。


七、本节总结与下一步

本节完整介绍了 Overlay 联合文件系统的三层架构(lowerdirupperdirmerged)及其工作原理:

  • merged只是展现层,不真正存放文件,内容来自下面两层的合并
  • 所有读操作遵循从上往下看的遮挡规则:优先 upperdir,其次 lowerdir
  • 所有写操作(增、删、改)只影响 upperdirlowerdir 始终保持只读
  • Docker 目前默认使用 overlay2 驱动,要求内核 4.0 以上

下一步:动手做实验,自己利用 Overlay 联合文件系统实现一次联合挂载,亲身体验联合挂载的效果。这样在后续学习 Docker 启动容器时,就能理解容器的文件系统到底是怎样通过联合挂载关联进去的。

posted @ 2026-06-19 09:46  知杏  阅读(23)  评论(0)    收藏  举报