Docker底层文件系统UnionFS实践

92 阅读3分钟

Docker底层文件系统UnionFS实践

虚拟化技术、容器技术都已经十分成熟,在日常工作中我们经常会使用到docker。

前置知识

本篇文章讲解docker的底层相关知识。

关于docker的入门教程可以看看docker中文文档:

docker中文文档 http://www.dockerinfo.net/document

容器技术的心法: Namespace做了彼此隔离,Cgroup做了资源限制,rootfs做了文件管控(针对的是Liunx容器) 。本篇主要讲的是上述第三部分,文件系统相关的知识。

rootfs文件管控的内容,一个特点是mount文件挂载,这个决定容器与宿主机看到的文件系统情况,能够打包应用与对应的文件目录供容器使用;另外一个特点就是容器文件系统的组织方式,这个决定了容器镜像文件的组织形式,允许通过”增量“的方式修改镜像里打包的文件(可以用git的提交方式来理解这个“增量”是什么情况)。

容器底层文件系统实现

这一篇文章主要介绍容器的文件系统的增量设计。容器采用了UnionFS,即联合文件系统。

简单来说,就是将文件分层,有一层为只读(readonly),一层可写层(writeable)。通过这两层的性质,只读层在下,可写层在上,构成了容器运行时状态,多个容器可以用同一个镜像。如果文件发生改变,会从文件系统重复制一份出来,而不会影响之前的文件信息,复制出来的这个文件修改完成后,会向上叠加;没有发生改变的文件则可以容器共用,节省空间。

这个操作可以归纳为:写时复制、用时分配。这个行为是通过存储驱动实现的。

容器的存储驱动有AUFS、OverlayFS、Device Mapper等等。 以OverlayFS为例,这个是一种联合系统。只有两层,只读层和可写层。 在这里插入图片描述 镜像层不可改变,容器层可写。

我们可以使用例子模拟一下,看看这样的结构怎么做到“写时复制、用时分配”。

OverlayFS实践

结构:

首先Overlay分为两层,lower层与upper层,其中lower为镜像层(只读),upper为容器层(可写)。 然后两层往上合并为文件Mount视图。

# 创建文件夹,lower、upper、merged、work
mkdir lower  upper  merged  work

# 先写入内容
echo from lower > lower/in_lower.txt
echo from upper > upper/in_upper.txt
# 上面是lower upper各不同的,下面写入相同的
echo from lower > lower/in_same.txt
echo from upper > upper/in_same.txt

# 将文件夹联合
mount -t overlay overlay -o lowerdir=`pwd`/lower,upperdir=`pwd`/upper,workdir=`pwd`/work `pwd`/merged
tree .
.
├── lower
│   ├── in_lower.txt
│   └── in_same.txt
├── merged
│   ├── in_lower.txt
│   ├── in_same.txt
│   └── in_upper.txt
├── upper
│   ├── in_same.txt
│   └── in_upper.txt
└── work
    └── work

# 从merged文件查看
cat merged/in_same.txt
cat merged/in_lower.txt
# 可以看到lower中的内容被upper中的内容遮盖了

接下来可以做一些尝试

# 在merged中增加
echo new from merge >> merged/in_same.txt       # merged追加
echo from merge > merged/in_merge.txt           # merged新建
echo "add in upper"  > upper/in_upper.txt       # upper追加
echo new file upper > upper/new_file_upper.txt  # upper新建

# merge中的追加,会作用在upper上        -       Dockerfile中增加一层(一行命令)的情况
# upper中新建,会体现在merged上         -
# merged中新建,会作用在upper上

# 在merged中删除
rm -i merged/in_same.txt            # merged中删除
rm -i upper/new_file_upper.txt      # upper中删除

# merged中删除文件,upper中文件还是存在
# upper中删除文件,merged中文件也消失

# 在merge中修改
vi upper/in_upper.txt
vi lower/in_lower.txt

cat upper/in_upper.txt
cat lower/in_lower.txt
# merged中修改,会直接修改到upper ;
# merged中修改in_lower , lower文件夹中不变,只会修改到upper文件夹中的in_lower

# 如果从upper直接修改,并不会带到merged中,并且merged中的也会和upper中的文件割裂开来(merge的改动不会带到upper); 而从merged中修改则可以作用到upper中

可以看到,联合文件系统的运行过程就是这种上下层控制的,形成上下覆盖映射,实现写时复制,用时分配的功能。

以上实践的例子在这里:

gitee.com/zeng-jingha…


参考

github.com/cncamp/101