讲述Docker底层原理的第三篇文章;
本文讲述了和Docker底层文件存储相关的技术:UnionFS以及AUFS;
系列文章:
源代码:
Union File System
什么是Union File System
Union File System,简称UnionFS,是一种为 Linux 、FreeBSD 和 NetBSD 操作系统设计的,把其他文件系统联合到一个联合挂载点的文件系统服务;
它使用 branch 把不同文件系统的文件和目录“透明地”覆盖,形成一个单一、一致的文件系统 ;
这些 branch 或者是 read-only 的、或者是 read-write 的,所以当对这个虚拟后的联合文件系统进行写操作的时候 , 系统是真正写到了一个新的文件中!
看起来这个虚拟后的联合文件系统是可以对任何文件进行操作的 , 但是其实它并没有改变原来的文件!
这是因为:UnionFS 用到了一个重要的资源管理技术:写时复制;
写时复制(copy-on-write ,下文简称 CoW),也被称为隐式共享,是一种对可修改资源实现高
效复制的资源管理技术;UnionFS的思想是:如果一个资源是重复的,并且没有任何修改,这时并不需要立即创建一个新的资源,这个资源可以被新旧实例共享;
而创建新资源发生在第一次写操作(也就是对资源进行修改的时候);
通过这种资源共享的方式可以显著地减少未修改资源复制带来的消耗,但是也会在进行资源修改时增加小部分的开销;
AUFS
AUFS是Docker使用的第一种存储驱动,目前Docker也是支持的!
目前Docker默认的存储驱动已经变为了
overlay2,这里只是简单的介绍AUFS;查看Docker的存储驱动:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 root@jasonkay:~/workspace/my_docker/chapter2_basic# docker info
Client:
Context: default
Debug Mode: false
Plugins:
app: Docker App (Docker Inc., v0.9.1-beta3)
buildx: Build with BuildKit (Docker Inc., v0.6.1-docker)
scan: Docker Scan (Docker Inc., v0.8.0)
Server:
Containers: 1
Running: 1
Paused: 0
Stopped: 0
Images: 2
Server Version: 20.10.8
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: cgroupfs
Cgroup Version: 1可以看到
Storage Driver: overlay2;
关于Docker存储驱动,包括overlay、overlay2等等分析的文章非常多,这里不再赘述了;
想要深入了解存储驱动的,可以自行Google,下面我们通过案例简单学习下AUFS,对这种文件系统有个了解即可!
AUFS实例
创建AUFS文件
下面通过一个实例来学习AUFS和CoW实现;
首先,在目录下创建一个aufs目录,然后在 aufs 目录下创建一个 mnt 的文件夹作为挂载点;
接着,在 aufs 目录下创建一个名为 container-layer 的目录,里面有一个名为container-layer.txt的文件,文件内容为I am container layer;
同样地 , 继续在 aufs 目录下创建 4 个名为 image-layer{n} 的文件夹( n 取值分别为 1到4),里面有一个名为image-layer{n}.txt的文件,文件内容为I am image layer ${n};
命令如下:
1 | ############################ 创建AUFS目录 ############################ |
检查目录结构:
1 | root@jasonkay:~/workspace/test/aufs# tree |
使用AUFS挂载目录
接下来将container-layer和4个image-layer{n}的目录使用AUFS的方式挂载至当前的mnt目录下;
1 | ############################ 挂载目录到mnt ############################ |
注:在
mount aufs命令中,没有指定待挂载的 5 个目录的权限;则默认情况下的行为是:dirs 指定的左边起第一个目录是
read-write权限, 后续的都是read-only权限!
确认新 mount 的文件系统中,每个目录的权限:
1 | # 查看当前系统全部AUFS的文件 |
可以看到,container-layer是 read-write 权限, 后续的都是 read-only 权限!
修改AUFS文件
接下来修改layer-4,以确认AUFS的CoW工作方式;
向 mnt/image-layer-4.txt 文件末尾添加一行文字:
1 | # 添加文字 |
从 cat 命令输出可以看到,mnt/image-layer-4.txt 文件内容的确发生了变化;
但是这里的mnt只是一个虚拟挂载点,接下来需要查看实际的文件修改位置;
查看 image-layer4/image-layer4.txt:
1 | cat image-layer4/image-layer4.txt |
发现实际的 image-layer4/image-layer4.txt 文件并未变化!
检查 container-layer/ 目录下的内容,发现多了一个名为 image-layer4.txt 的文件,并且文件内容如下:
1 | ll container-layer/ |
可见,当尝试修改 mnt/image-layer4.txt 时,系统首先在 mnt 目录下查找名为 image-layer4.txt 的文件,并将其拷贝到 read-write 层的 container-layer 目录中;
接着,对 container-layer 目录中的 image-layer4.txt 文件进行写操作,即:CoW;
注:试验结束别忘了将挂载点恢复:
1
2
3
4
5
6
7 pwd # /root/workspace/test/aufs
# 取消挂载mnt目录
sudo umount ./mnt
# 查看AUFS,发现si_452a0e92fdc8093d已经不存在!
ls /sys/fs/aufs/ # config
小结
本篇主要介绍了UnionFS以及AUFS,最后通过实践,体验了CoW(写时复制);
下一篇将会使用 Go 编写一个类似于 Docker 的容器环境,尽请期待;
附录
系列文章:
源代码: