docker的默认文件系统是AUFS(后来是Overlay)
Overlay:取消aufs,使用硬链接,一层指向一层,缺点:针对目录无法做硬链接,只能复制,会产出大量的文件描述符 (inode),导致inode 耗尽
Overlay2:128层镜像以后才开始进行硬链接的方式。
AFUS测试
准备三个目录: base ,mnt , top。在base目录下准备base.txt 和 common.txt文件,在top目录下准备commm.yml和foo.txt文件, mnt目录用于挂载
├── base│ ├── test.txt│ └── commm.yml├── mnt└── top ├── commm.yaml └── foo.txt
[root@pinyoyougou-docker aufsTest]# cat base/test.txtbase test[root@pinyoyougou-docker aufsTest]# cat base/commm.yml base[root@pinyoyougou-docker aufsTest]# cat top/comm.yml TOP[root@pinyoyougou-docker aufsTest]# cat top/foo.txt foo top
开始:
需要在centos 安装aufs
cd /etc/yum.repo.d 或者 cd /etc/yum.repos.d # 下载文件wget https://yum.spaceduck.org/kernel-ml-aufs/kernel-ml-aufs.repo# 安装yum install kernel-ml-aufs# 修改内核启动vim /etc/default/grub## 修改参数GRUB_DEFAULT=0# 重新生成grub.cfggrub2-mkconfig -o /boot/grub2/grub.cfg# 重启计算机reboot
用AUFS,把 base 和 top 一起 挂载到 ./mnt 目录:
mount -t aufs -o br=./top:./base none ./mnt
mount 命令的参数意义如下:
-t aufs:mount 的文件类型,使用的是 aufs-o:传递个 aufs 的选项,每个文件类型的选项不同br:表示 branch,也就是 aufs 需要的的各个目录none:这个本来是设备的名字,但是我们并没有用到任何设备,只会用到文件夹,因此这里为 none./mnt:挂载点,也就是内容最终出现的目录
看下mnt目录:
# ls mnt base.txt commm.yml foo.txt
会发现top目录下多了一个text.txt文件
# ls top test.txt common.txt foo.txt堆栈式的联合文件系统
而base目录下的test.txt并没有改变,这是因为AFUS本质上堆栈式的联合文件系统,主要功能是:把多个目录结合成一个目录,对外使用。把多个目录挂载成一个,
读写操作步骤如下:
- 默认情况下,最上层的目录为读写层,只能有一个
- 下面可以有一个或者多个只读层读文件
- 读文件,从最上面一个开始往下逐层去找,打开第一个找到的文件,读取其中的内容
- 写文件,如果在最上层找到了该文件,直接打开
否则,从上往下开始查找,找到文件后,把文件复制到最上层,然后再打开这个 copy - 删除文件:在最上层创建一个 whiteout 文件,.wh.,就是在原来的文件名字前面加上 .wh.
从功能上讲,AUFS可以将分布在不同地方的目录挂载到同一个虚拟文件系统当中
(1)首先我们将思路切换到 Linux启动阶段。、
典型的 Linux启动时,首先加载 bootfs(Boot File System)目录。这个目录里面包括 Bootloader和kernel。Bootloader用来加载启动 kernel。当kerenel成功加载到内存中后, bootfs就会释放掉, kernel随之开始加载rootfs。
(2)rootfs(Root FileSystem)包含的是 Linux系统中标准的 /dev、/proc、/bin、/etc等文件。
因为 rootfs是后续kernel启动的基础,对于 kernel来说异常重要,因此此时 kernel将 Rootfs加锁—设为 readonly。在只读权限下, kernel进行一系列的检查操作。当kernel确认 rootfs包含的文件正确无误后,将 readonly改为readwrite(可读可写),以后用户就可以按照正确的权限对这些目录进行操作了。
(3)说到这里,就轮到到 AUFS登场了。
当 Docker利用 LXC虚拟化出来一个容器之后,就相当于购买了一台裸机,有内存、CPU、硬盘,但没有操作系统。
Docker参考 Linux的启动过程,将一个readonly权限的 bootfs挂载到容器文件系统中,然后通过 AUFS,再将readonly权限的 rootfs添加到 bootfs之上,当rootfs检查完毕之后,再将用户所要使用的文件内容挂载到 rootfs之上,同样是readonly权限。
每次挂载一个 FS文件层,并且每层之间只会挂载增量(在这里大家可以借助于 SVN进行理解,相当每个 FS层都是 SVN提交上去的数据增量)。
这些文件层就是堆栈式文件系统中所保存的数据。
将不同的文件层挂载到同一个文件系统中的文件系统,就是联合文件系统;
而AUFS就是用来管理、使用这些文件层的文件系统,因此也称之为高级多层次统一文件系统( Advanced Multi Layered Unification Filesystem)
但是每个 FS层都是 readonly权限,那么容器内部如何向这些文件写入数据呢?
其实当 Docker利用 AUFS加载完昀高一层之后,会在更上面再添加一个 FS层,而这个层是 readwrite权限。
容器内部的应用,对当前文件系统所有的写操作(包括删除)都会保存在这个 FS层当中,而当容器向 Docker发出 commit命令后,Docker会将这个 FS层中的数据作为单独一个文件层保存到 AUFS之中,而一个镜像( image)就可以理解为:特定 FS层的集合。
所以可以看出镜像的层次关系,处于下层的 image是上层 image的父类,而没有父类 image的就是baseimage。因此需要从 image启动 container时,Docker会依次加载 baseimage和父类 image,而用户所有的操作就都保存在更高层的readwrite的 layer中。
Docker如何利用AUFS特性,解决容器初始化和写时复制问题?
(1)通过将镜像“分隔”为 AUFS的文件层,使得所有容器都可以共享文件层,且不会发生写冲突。
(2)但在 Docker中,所有的镜像都是只读的,所有的镜像也都不保存用户信息,只会用于新建和复制。
(3)而对于容器而言,其所看到的所有文件都是可读写的,只不过所有的写操作都被保存在更上层的文件层当中。