UnionFS与AUFS


AUFS(全称:advanced multi-layered unification filesystem,高级多层统一文件系统),用于为 Linux 文件系统实现联合挂载。提到联合挂载,就要先解一下 Union File System。

Union File System

Union File System,简称 UnionFS,是一种为 Linux、FreeBSD 和 NetBSD 操作系统设计的文件系统,它能够多个其他文件系统联合到一个地方来挂载。

类比一下,就像不同目录合并 mount 到同一个目录中。 它和核心原理有两个:

  • 分支管理:它使用 branch 把不同文件系统的文件和目录”透明地”覆盖,形成一个单一一致的文件系统。这些 branch 或者是 read-only 的,或者是 read-write 的,所以当对这个虚拟后的联合文件系统进行写操作的时候,系统是真正写到了一个新的文件中。
  • 写时复制:copy-on-write,简写为 CoW,也叫隐式共享,是一种提高资源使用效率的资源管理技术。它的思想是:如果一个资源是重复的,在没有对资源做出修改前,并不需要立即复制出一个新的资源实例,这个资源被不同的所有者共享使用。当任何一个所有者要对该资源做出修改时,复制出一个新的资源实例给该所有者进行修改,修改后的资源成为其所有者的私有资源。通过这种资源共享的方式,可以显著地减少复制相同资源带来的消耗,但是这样做也会在进行资源的修改时增加一部分开销。通俗来讲,读时看原来的,第一次写时才复制一个出来。

AUFS

AUFS 又叫 Another UnionFS,后来叫 Alternative UnionFS,后来可能觉得不够霸气,叫成 Advance UnionFS。是个叫 Junjiro Okajima(岡島順治郎)在 2006 年开发的,AUFS 完全重写了早期的 UnionFS 1.x,其主要目的是为了可靠性和性能,并且引入了一些新的功能,比如可写分支的负载均衡。AUFS 在使用上全兼容 UnionFS,而且比之前的 UnionFS 在稳定性和性能上都要好很多,后来的 UnionFS 2.x 开始抄 AUFS 中的功能。AUFS的一些实现已经被纳入 UnionFS 2.x 版本。

模拟实验

在Linux中,可以通过 mount 命令手动来创建 AUFS,体会下其写时复制的妙处,这里用Ubuntu(CentOS默认不支持AUFS,需要的话得去装支持AUFS的内核)。

首先创建实验目录

sakura@Sakura-Virture:~$ mkdir aufs

在该目录下创建mnt子目录作为FS的挂载点

sakura@Sakura-Virture:~$ mkdir aufs/mnt

在aufs目录下创建container-layer文件夹,用来模拟容器的读写层

sakura@Sakura-Virture:~$ mkdir aufs/container-layer
# 同时创建文件 container-layer.txt
sakura@Sakura-Virture:~$ echo "I am container layer" > aufs/container-layer/container-layer.txt

在 aufs 目录下创建三个文件 image-layer1、image-layer2、image-layer3,用来模拟容器的镜像层

sakura@Sakura-Virture:~$ mkdir aufs/{image-layer1,image-layer2,image-layer3}
sakura@Sakura-Virture:~$ echo "I am image layer 1" > aufs/image-layer1/image-layer1.txt
sakura@Sakura-Virture:~$ echo "I am image layer 2" > aufs/image-layer2/image-layer2.txt
sakura@Sakura-Virture:~$ echo "I am image layer 3" > aufs/image-layer3/image-layer3.txt

做完上述准备工作后,目录结构如下:

sakura@Sakura-Virture:~$ tree aufs
aufs
├── container-layer
│   └── container-layer.txt
├── image-layer1
│   └── image-layer1.txt
├── image-layer2
│   └── image-layer2.txt
├── image-layer3
│   └── image-layer3.txt
└── mnt
    ├── container-layer.txt
    ├── image-layer1.txt
    ├── image-layer2.txt
    └── image-layer3.txt

5 directories, 8 files

接下来,开始真正创建AUFS。

通过 mount 把 container-layer、image-layer1、image-layer2、image-layer3 以 AUFS 的方式挂载到刚才创建的 mnt 目录下

sakura@Sakura-Virture:~$ cd aufs
sakura@Sakura-Virture:~/aufs$ sudo mount -t aufs -o dirs=./container-layer:./image-layer1:./image-layer2:./image-layer3 none ./mnt

挂载完后,四个目录中的文件已经同步给了mnt,查看mnt的文件结构,如下:

sakura@Sakura-Virture:~/aufs$ tree mnt
mnt
├── container-layer.txt
├── image-layer1.txt
├── image-layer2.txt
└── image-layer3.txt

0 directories, 4 files

但是,原来的四个目录内容是没有任何变化的:

sakura@Sakura-Virture:~/aufs$ cd image-layer2
sakura@Sakura-Virture:~/aufs/image-layer2$ ls
image-layer2.txt

注意,AUFS在创建时,要挂载的目录是由默认的权限配置的。dirs 指定的左边起第一个目录是 read-write 权限,后续目录都是 read-only 权限。可以通过如下方式查看:

sakura@Sakura-Virture:~/aufs$ ls /sys/fs/aufs/
config  si_b133c0cc13e24c7b  si_b133c0cddb1e9c7b
sakura@Sakura-Virture:~/aufs$ cat /sys/fs/aufs/si_b133c0cddb1e9c7b/*
/home/sakura/aufs/container-layer=rw
/home/sakura/aufs/image-layer1=ro
/home/sakura/aufs/image-layer2=ro
/home/sakura/aufs/image-layer3=ro
64
65
66
67
/home/sakura/aufs/container-layer/.aufs.xino

其中的 si_b133c0cddb1e9c7b目录是系统为 mnt 这个挂载点创建的。

然后,尝试去写mnt下的某一个文件。

sakura@Sakura-Virture:~/aufs$ echo "I changed mnt/image-layer3.txt" >> mnt/image-layer3.txt
sakura@Sakura-Virture:~/aufs$ cat mnt/image-layer3.txt
I am image layer 3
I changed mnt/image-layer3.txt

上述操作对mnt中的image-layer3.txt执行了一次写操作(第一次)。查看一下container-layer中的文件结构:

sakura@Sakura-Virture:~/aufs/container-layer$ tree
.
├── container-layer.txt
└── image-layer3.txt

0 directories, 2 files

发现,其中多出了一个新的文件,打开看看

sakura@Sakura-Virture:~/aufs/container-layer$ cat image-layer3.txt 
I am image layer 3
I changed mnt/image-layer3.txt

可以看到,该文件不仅仅有在mnt中写入的信息,还保留了在源目录image-layer3中文件image-layer3.txt的信息。那么,image-layer3中有没有发生变化呢?并没有

sakura@Sakura-Virture:~/aufs$ cat image-layer3/image-layer3.txt 
I am image layer 3
sakura@Sakura-Virture:~/aufs$ ls image-layer1
image-layer1.txt
sakura@Sakura-Virture:~/aufs$ ls image-layer2
image-layer2.txt

很神奇,不仅仅image-layer3没有变换,imager-layer12也没有发生变化,只有container-layer发生了变化。

这就是AUF写时复制的效果。系统首先在 mnt 目录下查找名为 image-layer3.txt 的文件,将其拷贝到 read-write 层的 container-layer 目录中,接着对 container-layer 目录中的 image-layer3.txt 的文件进行写操作。这个过程也就是 AUFS 的实际工作原理。

实验结束,清理环境:

sakura@Sakura-Virture:~/aufs$ sudo umount mnt
sakura@Sakura-Virture:~/aufs$ sudo umount mnt
sakura@Sakura-Virture:~/aufs$ tree
.
├── container-layer
│   ├── container-layer.txt
│   └── image-layer3.txt
├── image-layer1
│   └── image-layer1.txt
├── image-layer2
│   └── image-layer2.txt
├── image-layer3
│   └── image-layer3.txt
└── mnt

5 directories, 5 files

Docker

虽然当前 docker 默认的存储驱动已经演进到了 overlay2,但是学习 AUFS 依然可以帮助我们深入理解 docker 中的文件系统。在Docker构建镜像时,就采用了写时复制。

具体是怎么采用的,以后再说。


文章作者: SrcMiLe
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 SrcMiLe !
评论
  目录