一、docker文件系统分层存储原理
docker镜像技术的基础是联合文件系统(UnionFS),其文件系统是分层的,那它的分层机制是什么样的呢?共分为几种层呢?又是怎么工作的呢?
目前docker支持的联合文件系统有很多种,包括:AUFS、overlay、overlay2、DeviceMapper、VSF等。
Linux 中各发行版实现的 UnionFS 各不相同,所以docker在不同 linux 发行版中使用的也不同。通过docker info 命令可以查看当前系统所使用哪种 UnionFS,常见的几种发行版使用如下:
CentOS, Storage Driver: overlay2、overlay
debain, Storage Driver: aufs
RedHat, Storage Driver: devicemapper
1、 overlayFS文件系统
Overlay是虚拟层,它其实是叠加的lower层和upper层,overlay的操作其实是拷贝后修改,并非修改底层。OverlayFS多了一层虚拟,所有会有损耗问题,它太消耗inode,随着镜像和容器增加,Inode会遇到瓶颈,所以需要内核4.0以上最合适。
2、 OverlayFS文件系统的文件读写原理
3、 Centos发行版的overlay2文件系统进介绍
其实不管是什么发行版,其原理都如出一辙。
先来看张图:
存储的位置位于:/var/lib/docker/overlay/,在overlayfs中每个镜像层都会在它下有相应的目录,使用硬链接与底层数据进行连接
从上述图中可以看到三个层结构,即lowerdir、upperdir、merged层
对应的,使用docker inspect [容器ID]就可以看到这几个层所在的位置
DNS配置、主机名文件、日志输出等属于容器运行时的信息,不属于镜像容器
3.1 lowerdir层
其中lowerdir是只读的镜像层(image layer),其中就包含bootfs/rootfs层,bootfs(boot file system)主要包含bootloader和kernel,bootloader主要是引导加载kernel,当boot成功 kernel 被加载到内存中,bootfs就被umount了,rootfs(root file system)包含的就是 典型Linux系统中的/dev、/proc、/bin、/etc等标准目录。
lowerdir是可以分很多层的,除了bootfs/rootfs层以外,还可以通过Dockerfile建立很多image层,构建过程如下
Dockerfile中每一个指令都会生成一个新的image层,如上图所示。
当FROM时就已经生成了bootfs/rootfs层,也就是kernel和base层。
3.2 upperdir层
upperdir层是lowerdir的上一层,只有这一层可读可写的,其实就是Container层,在启动一个容器的时候会在最后的image层的上一层自动创建,所有对容器数据的更改都会发生在这一层。
3.3 merged层
merged层就是联合挂载层,也就是给用户暴露的统一视觉,将image层和container层结合,就如最上边的图中描述一致,同一文件,在此层会展示离它最近的层级里的文件内容,或者可以理解为,只要container层中有此文件,便展示container层中的文件内 容,若container层中没有,则展示image层中的。
二、 联合挂载系统的工作原理
1、 读:
如果文件在upperdir(容器)层,直接读取文件;
如果文件不在upperdir(容器)层,则从镜像层(lowerdir)读取;
2、 写:
首次写入:如果upperdir中不存在,overlay和overlay2执行copy_up操作,把文件从lowdir拷贝到upperdir中,由于overlayfs是文件级别的(即使只有很少的一点修改,也会产生copy_up的动作),后续对同一文件的再次写入操作将对已经复制到容器层的文件副本进行修改,这也就是尝尝说的写时复制(copy-on-write)
删除文件或目录:当文件被删除时,在容器层(upperdir)创建whiteout文件,镜像层(lowerdir)的文件是不会被删除的,因为它们是只读的,但without文件会阻止它们显示,当目录被删除时,在容器层(upperdir)一个不透明的目录,这个和上边的whiteout的原理一样,组织用户继续访问,image层不会发生改变
3、 注意事项:
*copy_up操作只发生在文件首次写入,以后都是只修改副本,
*overlayfs只适用两层目录,,相比于比AUFS,查找搜索都更快。
*容器层的文件删除只是一个“障眼法”,是靠whiteout文件将其遮挡,image层并没有删除,这也就是为什么使用docker commit 提交保存的镜像会越来越大,无论在容器层怎么删除数据,image层都不会改变。
4、 容器整体构成图(此图没有展现联合挂载层)
三、带着问题看事物,docker容器为什么启动更快
先来看一张docker与VM的对比图:
可以清楚的看到,VM比docker多了Hypervisor 和 Guest OS的过程,也正是省略了这些过程使docker技高一筹,问题又来了,为什么docker可以省略这些过程呢?
(1)Hypervisor:主要作用是实现硬件资源虚拟化;因为docker容器上程序直接使用的都是物理机的硬件资源,所以不需要资源虚拟化的过程,也因此在CPU、内存利用率上docker将会在效率上明显提高
(2)Guest OS:主要作用加载操作系统内核;因为docker利用的是宿主机的内核,所以在启动一个容器时,不需要像VM一样重新加载一个操作系统内核,也因此大大节约了启动时间。
以下是官网提供的容器启动过程图:
四、Docker分层文件系统的问题及解决方案:
1 存在读写效率问题;
2 数据在容器内,无法在主机上访问;
3 容器删除后,容器内的所有数据丢失
4 解决方案docker volume(docker存储卷)
5 Docker volume的使用场景:
5.1 持久化存储容器的文件(数据);
5.2 容器与主机共享文件;
5.3 映射容器中的配置文件;
5.4 数据容器
五、Docker local volume
Docker run -v /root:/mydata2 -itd tomcat sh
将主机/root目录映射到tomcat容器的/mydata2下(这里要注意目录本身权限的问题)
Docker inspect xxxxx查看容器的详细信息可以看到
六、Docker volume的存储厂商存储
七、Docker volume plugin
1 、总体框架
2、docker volume plugin涉及细节:
3、 docker volume plugin自动发现机制:
4、Docker volume支持的插件:
5、Docker volume plugin的一般安装流程
八、 Docker volume的选择与建议:
1 如果本机磁盘能解决问题,首先本机磁盘,做好数据备份工作
2 如果有存储,可以挂载到主机上,当作本地磁盘方式使用
3 远程共享情况下:首先考虑NFS Server这种简单共享文件是否满足要求
4 其次考虑Gluster FS与Ceph这种开源分布式存储系统