victor
发布于

Linux overlay文件系统解析

一个 overlay 文件系统包含两个文件系统,一个 upper 文件系统和一个 lower 文件系统,是一种新型的联合文件系统。overlay 是“覆盖…上面”的意思,overlay 文件系统则表示一个文件系统覆盖在另一个文件系统上面。
为了更好的展示 overlay 文件系统的原理,现新构建一个 overlay 文件系统。文件树结构如下:

1、在一个支持 overlay 文件系统的 Linux (内核 3.18 以上)的操作系统上一个同级目录内(如/root 下)创建四个文件目录 lower 、upper 、merged 、work 其中 lower 和 upper 文件夹的内容如上图所示,merged 和 work 为空,same 文件名相同,内容不同。
2、在/root 目录下执行如下挂载命令,可以看到空的 merged 文件夹里已经包含了 lower 及 upper 文件夹中的所有文件及目录。
$mount -t overlay overlay -olowerdir=./lower,upperdir=./upper,workdir=./work ./merged
3、使用 df –h 命令可以看到新构建的 overlay 文件系统已挂载。
Filesystem Size Used Avail Use% Mounted on
overlay 20G 13G 7.8G 62% /root /merged
那么 lower 和 upper 目录里有相同的文件夹及相同的文件,合并到 merged 目录里时显示的是哪个呢?规则如下:

  1. 文件名及目录不相同,则 lower 及 upper 目录中的文件及目录按原结构都融入到 merged 目录中;
  2. 文件名相同,只显示 upper 层的文件。如上图在 lower 和 upper 目录下及下层目录 dir_A 下都有 same.txt 文件,但在合并到 merged 目录时,则只显示 upper 的,而 lower 的隐藏 ;
  3. 目录名相同, 对目录进行合并成一个目录。如上图在 lower 及 upper 目录下都有 dir_A 目录,将目录及目录下的所有文件合并到 merged 的 dir_A 目录,目录内如有文件名相同,则同样只显示 upper 的,如上图中 dir_A 目录下的 same.txt 文件。
    overlay 只支持两层,upper 文件系统通常是可写的;lower 文件系统则是只读,这就表示着,当我们对 overlay 文件系统做任何的变更,都只会修改 upper 文件系统中的文件。那下面看一下 overlay 文件系统的读,写,删除操作。

    ¬ 读 upper 没有而 lower 有的文件时,需从 lower 读;
    ¬ 读只在 upper 有的文件时,则直接从 upper 读
    ¬ 读 lower 和 upper 都有的文件时,则直接从 upper 读。

    ¬ 对只在 upper 有的文件时,则直接在 upper 写
    ¬ 对在 lower 和 upper 都有的文件时,则直接在 upper 写。
    ¬ 对只在 lower 有的文件写时,则会做一个 copy_up 的操作,先从 lower 将文件拷贝一份到 upper,同时为文件创建一个硬链接。此时可以看到 upper 目录下生成了两个新文件,写的操作只对从 lower 复制到 upper 的文件生效,而 lower 还是原文件。

    ¬ 删除 lower 和 upper 都有的文件时,upper 的会被删除,在 upper 目录下创建一个 ‘without’ 文件,而 lower 的不会被删除。
    ¬ 删除 lower 有而 upper 没有的文件时,会为被删除的文件在 upper 目录下创建一个 ‘without’ 文件,而 lower 的不会被删除。
    ¬ 删除 lower 和 upper 都有的目录时,upper 的会被删除,在 upper 目录下创建一个类似‘without’ 文件的 ‘opaque’ 目录,而 lower 的不会被删除。
    可以看到,因为 lower 是只读,所以无论对 lower 上的文件和目录做任何的操作都不会对 lower 做变更。所有的操作都是对在 upper 做, 。
    copy_up 只在第一次写时对文件做 copy_up 操作,后面的操作都不再需要做 copy_up,都只操作这个文件,特别适合大文件的场景。overlay 的 copy_up 操作要比 AUFS 相同的操作要快,因为 AUFS 有很多层,在穿过很多层时可能会有延迟,而 overlay 只有两层。而且 overlay 在 2014 年并入 Linux kernel mailline ,但是 aufs 并没有被并入 Linux kernel mailline ,所以 overlay 可能会比 AUFS 快。
    lower 文件系统可以为任何 Linux 支持的文件系统,甚至可以为另一个 overlayfs。因为虽然 overlay 文件系统的底层是由两个文件系统构成,但它本身只是一个文件系统,就如前面用 df 命令看到的,所以也可以和其他文件系统组成新的 overlay 文件系统。而 upper 是可写的,不支持 NFS。多层 lower 可执行如下命令:
    $mount -t overlay overlay -olowerdir=/lower1:/lower2:/lower3 ,upperdir=./upper,workdir=./work ./merged
    上例中,lower 是由三个文件系统合并成一个文件系统,其中 lower1 在最上面,lower3 在最底下。
    Docker 一直在用 AUFS(高级多层次统一文件系统)作为容器的文件系统。AUFS 是一个能透明覆盖一或多个现有文件系统的层状文件系统。当一个进程需要修改一个文件时,AUFS 创建该文件的一个副本。AUFS 可以把多层合并成文件系统的单层表示。Docker 的 image 构采用的是 AUFS,每个新版本都是一个与之前版本的简单差异改动,有效地保持镜像文件最小化。那 docker 使用 overlay 之后有什么区别呢?
    首先镜像在下载时每一层的镜像都有一个自己的镜像 ID,每个镜像都会有自己的目录,保存在/var/lib/docker/overlay 目录下,但是这些层目录的名字并不是下载镜像时的 ID 名称。我们都知道 AUFS 是多层,那如何体现为两层呢?启动一个容器后,也在这个目录下产生一个层目录,进入到目录可以看到有三个文件夹,分别是 merged,upper,work,和一个文件 lower-id,而在 lower-id 中保存的就是镜像最上层的 ID,所以对容器来说,还是一个两层的文件系统。

这里说明一下,docker pull image 时显示的镜像 ID 名称与/var/lib/docker/overlay 目录下的镜像目录名称不一样。镜像目录中保存的是这层独有的文件和硬链接下层共享的文件。这样可以更有效的利用磁盘资源。
从上面这个图可以看到,overlay 的两层对应的就是 docker 的镜像层(只读)和容器层(可写),只是把原来 AUFS 中的多层镜像合并成了 lower 层,而 upper 层代表的是容器层。
我们看到虽然 overlay 和 AUFS 都是联合文件系统,但结构比 AUFS 简单,且并入了 Linux kernel mainline,可能会比 AUFS 快,但还是太年轻,要谨慎在生产使用。而 AUFS 做为 docker 的第一个存储驱动,已经有很长的历史,比较的稳定,且在大量的生产中实践过,有较强的社区支持。

浏览 (1157) 点赞 收藏 分享
评论