overlayfs文件系统
OverlayFS 是 Linux 内核原生的联合挂载文件系统(Union Mount),核心是写时复制(COW),将多个目录虚拟合并为统一视图,上层优先、下层只读、修改自动拷贝到上层。它是 Docker/containerd 等容器的标准存储驱动,也广泛用于 LiveCD、嵌入式只读系统与系统快照。
合并多个目录为一个视图,写时复制,上层修改不影响下层。
需要 root 权限才能直接mount。
核心结构(四层)
OverlayFS 挂载必须指定 4 个目录(upperdir/workdir必须同分区):
| 目录 | 读写 | 作用 |
|---|---|---|
| lowerdir | 只读 | 基础层(镜像 / 系统),可多层(lower1:lower2:...,Linux 4.0+) |
| upperdir | 可写 | 上层修改层,所有写入 / 删除 / 元数据变更都落在这里 |
| workdir | 临时 | 内部临时目录(原子 rename、whiteout 等),挂载后自动清空 |
| merged | 视图 | 用户看到的统一合并目录(挂载点) |
核心原理(三大规则)
1. 同名文件:上层覆盖
- 上下层同名文件 →只显示 upper,lower 被隐藏。
- 示例:
lower/file.txt与upper/file.txt共存 →merged/file.txt指向upper/file.txt。
2. 同名目录:合并展示
- 上下层同名目录 → 内容合并显示(上层优先)Linux Kernel。
- 示例:
lower/dir/a.txt+upper/dir/b.txt→merged/dir/同时看到a.txt、b.txt。
3. 写时复制(Copy‑up)
- 修改 lower 层文件 → 先完整拷贝到 upper,再在 upper 副本上修改;lower 原文件不变。
- 删除 lower 层文件 → 在 upper 层创建whiteout(白色标记)(空文件 / 特殊标记),模拟删除。
- 修改元数据(chmod/chown)→ 可开启
metacopy仅拷贝元数据,不拷贝数据(节省空间)
挂载与使用
1. 基础挂载(单 lower)
# 准备目录 mkdir -p /lower /upper /work /merged # 挂载 OverlayFS mount -t overlay overlay \ -o lowerdir=/lower,upperdir=/upper,workdir=/work \ /merged2. 多 lower 层(Linux 4.0+)
# lower1 > lower2 > lower3(越左优先级越高) mount -t overlay overlay \ -o lowerdir=/lower1:/lower2:/lower3,upperdir=/upper,workdir=/work \ /merged3. 卸载
umount /merged典型应用场景
容器存储(Docker/containerd)
- 镜像多层只读
lowerdir+ 容器可写upperdir→ 高效分层、快速启动、节省存储。 - Docker 用
overlay2驱动(原生支持多 lower,最多 128 层)。
- 镜像多层只读
LiveCD / 嵌入式只读系统
- 只读 squashfs 作为
lower,tmpfs/ram 作为upper→ 系统可写但重启后恢复初始状态。
- 只读 squashfs 作为
系统快照与测试
- 系统根目录为
lower,临时upper做测试 → 测试后卸载即恢复,无残留。
- 系统根目录为
关键特性与限制
优势
- 内核原生(3.18+)、无额外依赖、性能优于 AUFS。
- 写时复制节省空间、保护底层只读数据。
- 多 lower 层支持,适配容器镜像分层。
限制
- upper/work 必须同分区(依赖原子 rename)。
- 不支持跨节点分布式(本地文件系统)。
- 大文件首次写时拷贝有短暂 I/O 开销(可通过
metacopy缓解)。 - 部分文件系统(如 NFS)不适合做 upper(需 xattr、d_type 支持)。
与 AUFS/Btrfs/ZFS 对比
| 特性 | OverlayFS | AUFS | Btrfs/ZFS |
|---|---|---|---|
| 内核集成 | 原生(3.18+) | 非主线 | 原生 |
| 多 lower 层 | 4.0+ 支持 | 支持 | 子卷 / 快照 |
| 写机制 | COW(文件级) | COW | COW(块级) |
| 复杂度 | 低 | 中 | 高 |
| 容器适配 | 最佳(overlay2) | 早期 Docker | 较少 |
OverlayFS 与 pivot_root
pivot_root 是什么?
一句话:把进程的 “/” 根目录彻底换成新的根目录。
- 让进程看不到宿主机的任何文件
- 只能看到你指定的根文件系统(比如 OverlayFS 合并后的目录)
- 是容器实现「文件系统完全隔离」的核心系统调用
对比:
chroot:简陋切换根,不安全、不彻底pivot_root:安全、干净、内核推荐的真正根切换
必须满足的 3 个条件
- 必须在独立 mount namespace 里(unshare -m)
- 新根必须是一个挂载点(Overlay 挂载最常用)
- 旧根必须能被挂载覆盖(通常把新根放在旧根下)
pivot_root 命令格式
pivot_root 新根 旧根存放目录最常用写法:
pivot_root . .意思:
- 把当前目录作为新根
- 把旧根放到当前目录里(之后可以卸载)
完整可运行脚本(root 执行)
# 1. 创建目录 mkdir -p /tmp/lower /tmp/upper /tmp/work /tmp/merged # 2. 下层放基础文件 echo "this is overlay root" > /tmp/lower/test.txt # 3. 进入隔离命名空间,并执行切换根 unshare -m -- sh -c ' # 挂载 overlayfs mount -t overlay overlay \ -o lowerdir=/tmp/lower,upperdir=/tmp/upper,workdir=/tmp/work \ /tmp/merged # 让新根成为挂载点(必须) mount --bind /tmp/merged /tmp/merged # 进入新根 cd /tmp/merged # 关键:pivot_root 切换根目录 pivot_root . . # 卸载旧的宿主机根(完全隔离) umount -l / # 现在你进入了一个完全独立的迷你容器! exec /bin/sh '进入后效果:
ls /看不到宿主机任何文件- 只能看到 Overlay 合并后的根
- 写操作全部落到 upperdir
- 宿主机完全不受影响
- 这就是容器!
和 chroot 的区别
| 方式 | 安全性 | 彻底性 | 容器使用 |
|---|---|---|---|
| pivot_root | 高 | 完全隔离 | Docker / 容器标准 |
| chroot | 低 | 不彻底 | 老旧工具 |
pivot_root 会彻底切换内核级根目录,chroot 只是伪装。
和 PRoot 的区别
- pivot_root:内核级、快、需要 root
- PRoot:用户态、慢、不需要 root
你可以理解:
- PRoot = 无 root 模拟 pivot_root
- pivot_root = 真正生产级容器根切换
