aufs是docker最早支持的存储引擎。aufs是一种union file system,是文件级的存储驱动,是docker早期用的存储驱动,是docker18.06版本之前,ubuntu14.04版本前推荐的,支持xfs、ext4文件。
本教程操作环境:linux7.3系统、docker20版、dell g3电脑。
aufs是docker最早支持的存储引擎。
docker 的存储引擎
docker 的存储引擎设计思路是这样,但是针对不同的文件系统,是由不同的存储驱动去实现的。下面我们来聊聊 docker 的存储驱动。
docker 主要有一下几类存储驱动:
overlay2:是当前版本推荐的存储驱动,无需额外的依赖和配置即可发挥绝佳的性能。在 18.09 版本之后替换了 overlay 存储驱动。支持 xfs,ext4 文件系统。
aufs:docker 最早期使用的存储驱动,是 docker 18.06 版本之前,ubuntu 14.04 版本前推荐的。支持 xfs,ext4 文件系统。
devicemapper:是较早版本的 centos 和 rhel 系统推荐的存储驱动,因为它们不支持 overlay2,需要 direct-lvm 的支持。
btrfs:仅用于 btrfs 文件系统。
zfs:仅用于 zfs 文件系统。
vfs:不依赖于文件系统,但是性能奇差,主要用来测试。
需要注意的是,overlay2,overlay,aufs 的层是基于文件的,当单文件的写并发较高时需要大内存的支持,且读写层可能因为单个文件而变得很大。devicemapper,btrfs,zfs 的层是基于块存储的,因此对于单个文件的高并发影响不大。但是 btrfs 和 zfs 非常消耗内存。
docker aufs
aufs是一种union file system,所谓unionfs就是把不同物理位置的目录合并mount到同一个目录中。unionfs的一个最主要的应用是,把一张cd/dvd和一个硬盘目录给联合 mount在一起,然后,你就可以对这个只读的cd/dvd上的文件进行修改(当然,修改的文件存于硬盘上的目录里)。
aufs又叫another unionfs,后来叫alternative unionfs,后来可能觉得不够霸气,叫成advance unionfs。是个叫junjiro okajima(岡島順治郎)在2006年开发的,aufs完全重写了早期的unionfs 1.x,其主要目的是为了可靠性和性能,并且引入了一些新的功能,比如可写分支的负载均衡。aufs在使用上全兼容unionfs,而且比之前的unionfs在稳定性和性能上都要好很多,后来的unionfs 2.x开始抄aufs中的功能。但是他居然没有进到linux主干里,就是因为linus不让,基本上是因为代码量比较多,而且写得烂(相对于只有3000行的union mount和10000行的unionfs,以及其它平均下来只有6000行代码左右的vfs,aufs居然有30000行代码),所以,岡島不断地改进代码质量,不断地提交,不断地被linus拒掉,所以,到今天aufs都还进不了linux主干(今天你可以看到aufs的代码其实还好了,比起openssl好n倍,要么就是linus对代码的质量要求非常高,要么就是linus就是不喜欢aufs)。
不过,好在有很多发行版都用了aufs,比如:ubuntu 10.04,debian6.0, gentoo live cd支持aufs,所以,也ok了。
好了,扯完这些闲话,我们还是看一个示例吧(环境:ubuntu 14.04)
首先,我们建上两个目录(水果和蔬菜),并在这两个目录中放上一些文件,水果中有苹果和蕃茄,蔬菜有胡萝卜和蕃茄。
$ tree.├── fruits│ ├── apple│ └── tomato└── vegetables ├── carrots └── tomato
然后,我们输入以下命令:
# 创建一个mount目录$ mkdir mnt# 把水果目录和蔬菜目录union mount到 ./mnt目录中$ sudo mount -t aufs -o dirs=./fruits:./vegetables none ./mnt# 查看./mnt目录$ tree ./mnt./mnt├── apple├── carrots└── tomato
我们可以看到在./mnt目录下有三个文件,苹果apple、胡萝卜carrots和蕃茄tomato。水果和蔬菜的目录被union到了./mnt目录下了。
我们来修改一下其中的文件内容:
$ echo mnt > ./mnt/apple$ cat ./mnt/applemnt$ cat ./fruits/applemnt
上面的示例,我们可以看到./mnt/apple的内容改了,./fruits/apple的内容也改了。
$ echo mnt_carrots > ./mnt/carrots$ cat ./vegetables/carrots $ cat ./fruits/carrotsmnt_carrots
上面的示例,我们可以看到,我们修改了./mnt/carrots的文件内容,./vegetables/carrots并没有变化,反而是./fruits/carrots的目录中出现了carrots文件,其内容是我们在./mnt/carrots里的内容。
也就是说,我们在mount aufs命令中,我们没有指它vegetables和fruits的目录权限,默认上来说,命令行上第一个(最左边)的目录是可读可写的,后面的全都是只读的。(一般来说,最前面的目录应该是可写的,而后面的都应该是只读的)
所以,如果我们像下面这样指定权限来mount aufs,你就会发现有不一样的效果(记得先把上面./fruits/carrots的文件删除了):
$ sudo mount -t aufs -o dirs=./fruits=rw:./vegetables=rw none ./mnt$ echo "mnt_carrots" > ./mnt/carrots $ cat ./vegetables/carrotsmnt_carrots$ cat ./fruits/carrotscat: ./fruits/carrots: no such file or directory
现在,在这情况下,如果我们要修改./mnt/tomato这个文件,那么究竟是哪个文件会被改写?
$ echo "mnt_tomato" > ./mnt/tomato $ cat ./fruits/tomatomnt_tomato$ cat ./vegetables/tomatoi am a vegetable
可见,如果有重复的文件名,在mount命令行上,越往前的就优先级越高。
你可以用这个例子做一些各种各样的试验,我这里主要是给大家一个感性认识,就不展开试验下去了。
那么,这种unionfs有什么用?
历史上,有一个叫knoppix的linux发行版,其主要用于linux演示、光盘教学、系统急救,以及商业产品的演示,不需要硬盘安装,直接把cd/dvd上的image运行在一个可写的存储设备上(比如一个u盘上),其实,也就是把cd/dvd这个文件系统和usb这个可写的系统给联合mount起来,这样你对cd/dvd上的image做的任何改动都会在被应用在u盘上,于是乎,你可以对cd/dvd上的内容进行任意的修改,因为改动都在u盘上,所以你改不坏原来的东西。
我们可以再发挥一下想像力,你也可以把一个目录,比如你的源代码,作为一个只读的template,和另一个你的working directory给union在一起,然后你就可以做各种修改而不用害怕会把源代码改坏了。有点像一个ad hoc snapshot。
docker把unionfs的想像力发挥到了容器的镜像。你是否还记得我在介绍linux namespace上篇中用mount namespace和chroot山寨了一镜像。现在当你看过了这个unionfs的技术后,你是不是就明白了,你完全可以用unionfs这样的技术做出分层的镜像来。
下图来自docker的官方文档layer,其很好的展示了docker用unionfs搭建的分层镜像。
关于docker的分层镜像,除了aufs,docker还支持btrfs, devicemapper和vfs,你可以使用 -s 或 storage-driver= 选项来指定相关的镜像存储。在ubuntu 14.04下,docker默认ubuntu的 aufs(在centos7下,用的是devicemapper,关于devicemapper,我会以以后的文章中讲解)你可以在下面的目录中查看相关的每个层的镜像:
/var/lib/docker/aufs/diff/<id>
aufs的一些特性
aufs有所有union fs的特性,把多个目录,合并成同一个目录,并可以为每个需要合并的目录指定相应的权限,实时的添加、删除、修改已经被mount好的目录。而且,他还能在多个可写的branch/dir间进行负载均衡。
上面的例子,我们已经看到aufs的mount的示例了。下面我们来看一看被union的目录(分支)的相关权限:
rw表示可写可读read-write。
ro表示read-only,如果你不指权限,那么除了第一个外ro是默认值,对于ro分支,其永远不会收到写操作,也不会收到查找whiteout的操作。
rr表示real-read-only,与read-only不同的是,rr标记的是天生就是只读的分支,这样,aufs可以提高性能,比如不再设置inotify来检查文件变动通知。
推荐学习:《docker视频教程》
以上就是什么是docker最早支持的存储引擎的详细内容。