跳至正文
老丹的足迹 —— 代码写给机器,游记写给自己,感悟写给时间
老丹的足迹 老丹的足迹
老丹的足迹 老丹的足迹
  • 首页
  • 示例页面
  • 首页
  • 示例页面
老丹的足迹 老丹的足迹
老丹的足迹 老丹的足迹
  • 首页
  • 示例页面
  • 首页
  • 示例页面

深度解析 Linux OverlayFS:透明玻璃、便利贴与写时复制

一、开篇:当你遇到 Overlay,你遇到了什么?

在 Linux 系统运维和容器开发的日常工作中,你大概率会在以下场景中与“Overlay”狭路相逢:

  • 执行 df -Th 时,发现某个挂载点的类型是 overlay;
  • 在 Docker 的 docker info 输出中,看到 Storage Driver: overlay2;
  • 或者你在制作嵌入式系统根文件系统时,需要把只读的 squashfs 和可写的临时目录合并起来。

如果你把这里的 Overlay 理解成“网络隧道”或者“视频画中画”,那就跑偏了。在 Linux 文件系统层面,Overlay 指的就是 OverlayFS——一种联合挂载文件系统。它的终极使命很简单:将两个或多个目录(其中至少一个是只读的)叠加(Stack)起来,对外呈现为一个统一的、可读写的虚拟目录。

二、形象类比:一张原稿纸 + 一块透明玻璃板

为了让你脑海中立刻建立起画面感,请想象一张桌子:

  • 桌面底层:铺着一张写满了字的原稿纸。这张纸被死死按在桌上,你不能涂改它,也不能撕掉它(只读层,Lowerdir)。
  • 桌面上层:悬空盖着一块完全透明的玻璃板(读写层,Upperdir)。你可以用白板笔在玻璃上随意写字、画图、贴便利贴。
  • 你的视角:你站在正上方低头看下去,你眼里看到的“完整画面”,就是玻璃上的笔迹和原稿纸内容叠加在一起的合成图(合并视图,Merged)。

OverlayFS 干的事,就是帮你制造出这个“从上往下看”的合并视角。你在这个视角里做的一切修改,实际上都只发生在玻璃板(上层)上,底下的原稿纸(下层)永远保持原样。

三、核心概念与数据结构的硬核拆解

在 Linux 内核中,OverlayFS 的挂载涉及以下四个关键目录,缺一不可:

参数全称角色定位读写属性生命周期
Lowerdir下层目录原稿纸:基础文件系统,存放底层静态数据只读(Read-Only)永久存在,永不修改
Upperdir上层目录玻璃板:存放所有修改、新增、删除操作的痕迹可读写(Read-Write)随容器或会话创建,可销毁
Workdir工作目录草稿纸:用于 OverlayFS 内部原子操作的临时空间可读写必须为空目录,用于辅助事务操作
Merged挂载点你的眼睛:最终呈现的虚拟合并视图可读写(对用户而言)用户在此目录进行操作

特别注意: workdir 必须和 upperdir 在同一个文件系统上,这是内核的硬性要求。

四、动手实验:手把手教你创建一个 OverlayFS

理论总是枯燥的,我们来在终端里实际操练一把。不需要装任何额外软件,Linux 内核 3.18+ 均原生支持。

# 1. 创建实验所需的所有目录
mkdir -p /tmp/overlay-test/{lower,upper,work,merged}

# 2. 在下层(只读层)放入一些原始文件
echo "我是底层原稿,不可修改" > /tmp/overlay-test/lower/immutable.txt
echo "底层共享数据" > /tmp/overlay-test/lower/share.txt

# 3. 执行 OverlayFS 挂载命令(这是核心)
sudo mount -t overlay overlay \
  -o lowerdir=/tmp/overlay-test/lower,\
     upperdir=/tmp/overlay-test/upper,\
     workdir=/tmp/overlay-test/work \
  /tmp/overlay-test/merged

# 4. 现在进入 merged 目录,看看你看到了什么
ls /tmp/overlay-test/merged/
# 输出: immutable.txt  share.txt

此时,你看到的 merged 目录就是底层两个文件的完整镜像。

接下来见证奇迹(写时复制,CoW):

# 5. 尝试修改底层来的文件
echo "我在玻璃板上加了注释" >> /tmp/overlay-test/merged/share.txt

# 6. 查看 merged 里的文件,发现已改变
cat /tmp/overlay-test/merged/share.txt
# 输出:底层共享数据\n我在玻璃板上加了注释

# 7. 查看底层的原始文件,发现它丝毫未变!
cat /tmp/overlay-test/lower/share.txt
# 输出:底层共享数据(依旧是原样)

为什么会这样? 这就是 写时复制(Copy-on-Write,CoW) 机制在起作用。当你试图修改下层(Lower)的只读文件时,OverlayFS 会先将该文件完整复制一份到上层(Upper)目录,然后你的所有修改都发生在上层这个副本上。从此,merged 看到的将是上层副本,下层的原文件被“透明地遮挡”了。

再试试删除操作(Whiteout 遮挡):

# 8. 在 merged 里删除一个下层文件
rm /tmp/overlay-test/merged/immutable.txt

# 9. 查看 merged,确实不见了
ls /tmp/overlay-test/merged/
# 输出: share.txt

# 10. 但查看 lower 目录,文件依然存在
ls /tmp/overlay-test/lower/
# 输出: immutable.txt  share.txt

# 11. 查看 upper 目录,你会发现一个特殊文件
ls /tmp/overlay-test/upper/
# 输出: share.txt  immutable.txt(实际上这是一个 Character Device,即 Whiteout 标记)

OverlayFS 不会真正删除下层文件,而是在上层创建一个名为 immutable.txt 的白屏文件(Whiteout)。它是一种特殊的字符设备,作用就是告诉内核:“在合并视图里,把这个名字给我屏蔽掉”。

五、进阶:多层级联(Lowerdir 的多层堆叠)

现代 Linux 支持 多个 Lowerdir,用冒号(:)分隔。这在 Docker 镜像分层中极其关键。

mount -t overlay overlay \
  -o lowerdir=/layer3:/layer2:/layer1,\
     upperdir=/upper,workdir=/work /merged

在 Docker 中,镜像就是由几十个只读的 Lower 层堆叠而成。当你要启动一个容器时,Docker 会把这些只读层和你容器的可写层(Upper)合并挂载。最底层的 Lower 是基础操作系统,最上面的 Lower 是你刚写的代码层。 如果上层和下层有同名文件,上层的文件完全覆盖下层(类似于 CSS 的层叠样式表)。

六、OverlayFS 的两代演进:Overlay 与 Overlay2

如果你在 Docker 中配置存储驱动,会发现有 overlay 和 overlay2 两种。它们有什么区别?

  • Overlay(第一代):只支持一个 Lowerdir,且底层文件系统必须为 d_type 支持(如 ext4),硬链接支持不完善,容易触发 too many levels of symbolic links 错误。
  • Overlay2(第二代,当前默认):支持多个 Lowerdir,使用了更稳定的硬链接处理机制,且显著降低了 inode 消耗。除非是极老的 Linux 内核(< 4.0),否则请务必使用 overlay2。

七、在生产环境中的三大应用场景

1. Docker/Kubernetes 容器的镜像分层存储

这是 OverlayFS 最伟大的应用。当你拉取一个 Nginx 镜像时,你没有真正下载“一个大包”,而是下载了多个只读层(如 Debian 底层、Nginx 主程序层、配置文件层)。启动 100 个 Nginx 容器,它们共享这些只读层,只有每个容器的 Upper 层是独立且极其轻量的。这带来了极致的磁盘空间节省和秒级的容器启动速度。

2. 嵌入式 Linux 的只读根文件系统(Squashfs + Overlay)

在路由器、智能摄像头等嵌入式设备中,为了固件安全和防篡改,根文件系统通常做成只读的 Squashfs 镜像。系统启动时,用 OverlayFS 将 Squashfs 作为 Lowerdir,将内存文件系统(tmpfs)作为 Upperdir。用户任何配置修改均保存在内存中,断电即失,但固件永远安全、永不损坏。

3. 系统还原卡/无盘工作站

在学校的计算机教室或网吧,管理员利用 OverlayFS 保护 C 盘系统分区。每次开机,系统分区作为 Lowerdir,内存作为 Upperdir。学生任意折腾、删文件、装软件都只影响 Upper。重启后,丢弃 Upper,系统瞬间恢复如初,无需使用 Ghost 还原。

八、必须警惕的坑与限制(高能警告)

  1. rename 系统调用的限制:OverlayFS 对跨层重命名(rename)操作支持不完美。如果你在 merged 里将文件从一个目录移动到另一个目录,可能会遇到 Invalid cross-device link 错误,因为这对内核来说意味着复杂的文件复制与删除操作。
  2. 文件句柄(File Handle)稳定性:当底层 Lowerdir 发生变化(如升级 Docker 镜像的某一层)时,依赖该层启动的长期运行进程可能会因为文件句柄失效而报错 Stale file handle。这是容器环境需要优雅重启 Pod 的重要原因之一。
  3. 并发写同一个文件:如果有多个进程同时通过 merged 写入同一个文件,OverlayFS 的 CoW 机制可能导致数据竞争,需依赖上层应用(如数据库)自身的事务锁机制。
  4. 磁盘空间满的误判:由于数据实际写在 Upperdir,当你 df -h 查看 merged 时,显示的是整个文件系统的可用空间,但你写文件只会消耗 upperdir 所在分区的空间。若 upperdir 所在分区已满,即使 merged 显示有空间,写入也会报错。

九、总结:一张图厘清所有关系

你想做什么?数据实际去哪了?下层(Lower)受影响吗?
新建文件直接写入 upperdir完全无影响
修改下层文件复制到 upperdir 后再修改(CoW)完全无影响
删除下层文件在 upperdir 创建一个 Whiteout 遮罩原文件依旧存在,只是被隐藏
修改上层文件直接在 upperdir 中修改完全无影响
删除容器/重启系统直接删除 upperdir 和 workdir下层数据纹丝不动,可复用

最后的忠告

当你在 Linux 下再遇到 Overlay,请在心里默念三遍:它不是网络隧道,它是一个文件叠层器;它不是把文件搬走,它是在文件上盖了一层玻璃。

如果你是在排障时遇到了 No space left on device 但 df -h 显示没满,请去检查 upperdir 所在分区的 inode(df -i),大概率是 OverlayFS 的 workdir 或 upperdir 产生了过多的小文件占满了 inode。如果你是在配置 Docker 时遇到 overlay2: backing fs not supported,请确保你存放 /var/lib/docker 的磁盘格式是 ext4 或 xfs,千万不要是 aufs 或 nfs。

希望这篇文章能让你对 Linux OverlayFS 有一个全面且扎实的认知。如果你正在某个具体的场景(比如搭建 PXE 无盘系统、调试容器存储问题)中使用它,遇到了卡壳的地方,欢迎随时追问具体的操作细节。

作者

老丹

关注我
其他文章
上一个

深入理解 TUN/TAP:软件定义网络的基石与全景解析

下一个

Cgroup 深度解析:从内核原理到云原生应用的全面指南

关于博主

    老丹是一名C/C++后台开发工程师,信奉“无抽象不设计,无性能不生产”。

  • 技术栈:Modern C++、Linux环境编程、多线程/并发、网络编程等。
  • 信条:能用constexpr解决的问题绝不拖到运行时,能靠RAII避免的泄漏绝不写析构。
  • 正在填坑:从解封装到渲染的C++全链路实现,正在驯服FFmpeg与H.264/H.265。
  • 输出原则:这里的每一段代码都经过-Wall -Wextra -Werror -O2的洗礼。

近期文章

  • Linux系统的安全基石:深入理解可插拔认证模块(PAM) 2026年7月27日
  • vsftpd 完全指南:从核心原理到Docker容器化部署 2026年7月27日
  • 互联网的”导航”安全卫士:深入解读DNSSEC 2026年7月27日
  • Ubuntu DNS 配置完全指南 2026年7月27日
  • 在 Ubuntu 中使用 Certbot 的操作指南 2026年7月27日

文章分类

  • C/C++开发 (13)
  • Docker容器 (3)
  • Linux工具包 (10)
  • Linux服务配置 (33)
  • Linux系统 (10)
  • OpenWrt路由 (2)
  • Shell脚本 (3)
  • 安防技术 (4)
  • 数据安全 (30)
  • 网络协议 (17)
  • 计算机理论 (22)
联系我们:📍 地址:中国·广东省深圳市   |   ✉️ 邮箱:support@tanglinux.com   |   💬 QQ:870866607
版权所有:老丹的足迹粤ICP备2026061170号-1       公安备案图标 粤公网安备44030002013274号