存储驱动

我们来了解一下它一些相关的存储的驱动。

我们docker的存储都离不开一个东西,也就是所谓的存储引擎,他是实现我们联合文件系统的基本,这一章节我就带大家去看一下到底有哪些常见的存储驱动,以及我们的存储驱动怎么来进行调优。

8.3.1 常见的存储驱动

docker的存储驱动是我们docker的核心组件,它是实现docker分层镜像的基础,从docker诞生以来到现在较为出名的一些存储系统就是以下三个。

1、device mapper(DM):性能和稳定性存在问题,不推荐生产环境中使用

但是DM是会在一些较为老的centos7内核中去使用的这么一个存储系统。也就意味着如果你的内核版本低于3.18他的overlayfs存储系统还没有进入主线版本,那这时候主线版本就是DM,那docker就会退格至采用DM的存储系统,也就意味着我们在选择一个操作系统以后,我们通过docker info找到Storage Driver这一行就是显示我们采用的存储驱动,假如我们采用的是centos7的内核版本比较老的话可能他的默认存储系统就是DM,但是这个性能和稳定性存在问题,是相对于我们的overlayfs来说的。并不是说差到不能用。

2、btrfs:社区实现了btrfs driver,稳定性和性能存在问题,比DM相对要好,但是依旧比voerlapyfs差

这个是由我们docker社区去实现的,在某些第三方容器不是docker的容器,的一些方案中也有人在去使用,但是同理对于overlapyfs来说稳定性和性能依旧是有一些问题的,但是较于DM来说经测试的话稍微强一点

3、overlayfs(建议大家使用的一种存储驱动):内核 3.18 overlayfs 进入主线,性能和稳定性优异,在生产中第一选择

在工作中建议大家采用overlapyfs,这也是我们官方社区推荐的一个存储系统版本,但是他有要求必须要内核版本3.18以后才会进入到主线,在ubuntu 16版本中已经进入主线了。也就是内核必须大于3.18这个版本以后,docker才会默认使用到overlay,如果内核没有3.18的话overlay不是主线版本,这时候就需要去进行编译以及引用。

8.3.2 docker overlayfs 驱动工作原理

overlay是怎样来进行工作的呢。我们从上图可以看到,他会分为三层:

  1. image layer(镜像层)

  2. container layer(容器层):我们可以将这层理解成我们容器的读写层。

  3. container mount(容器挂载):就是用户能够看到的这么一些信息。

这三层对于到我们的overlayFS的话就会分为这三个目录:

lowerdir(最底层):

upperdir(上一层):

merged(用户的挂载层):

那么 lower 和 upper 目录里有相同的文件夹及相同的文件,合并到 merged 目录里时显示的是哪个呢?规则如下:

  1. 文件名及目录不相同,则 lower 及 upper 目录中的文件及目录按原结构都融入到 merged 目录中

  2. 文件名相同,只显示 upper 层的文件。如上图在 lower 和 upper 目录下及下层目录 dir_A 下都有 same.txt 文件,但在合并到 merged 目录时,则只显示 upper 的,而 lower 的隐藏 ;

  3. 目录名相同, 对目录进行合并成一个目录。如上图在 lower 及 upper 目录下都有 dir_A 目录,将目录及目录下的所有文件合并到 merged 的 dir_A 目录,目录内如有文件名相同,则同样只显示 upper 的,如上图中 dir_A 目录下的same.txt文件。

overlay只支持两层,upper文件系统通常是可写的;lower文件系统则是只读,这就表示着,当我们对 overlay 文件系统做任何的变更,都只会修改 upper 文件系统中的文件。那下面看一下overlay文件系统的、读,写,删、除操作。

  • 读:

    • 读 upper 没有而 lower 有的文件时,需从 lower 读

    • 读只在 upper 有的文件时,则直接从 upper 读

    • 读 lower 和 upper 都有的文件时,则直接从 upper 读。

  • 写:

    • 对只在 upper 有的文件时,则直接在 upper 写

    • 对在lower 和 upper 都有的文件时,则直接在 upper 写。

    • 对只在 lower 有的文件写时,则会做一个copy_up 的操作,先从 lower将文件拷贝一份到upper,同时为文件创建一个硬链接。此时可以看到 upper 目录下生成了两个新文件,写的操作只对从lower 复制到 upper 的文件生效,而 lower 还是原文件。

  • 删:

    • 删除 lower 和 upper 都有的文件时,upper 的会被删除,在 upper 目录下创建一个 ‘without’ 文件,而 lower 的不会被删除。

    • 删除 lower 有而 upper 没有的文件时,会为被删除的文件在 upper 目录下创建一个 ‘without’ 文件,而 lower 的不会被删除。

    • 删除 lower 和 upper 都有的目录时,upper 的会被删除,在 upper 目录下创建一个类似‘without’ 文件的 ‘opaque’ 目录,而 lower 的不会被删除。

可以看到,因为 lower 是只读,所以无论对 lower 上的文件和目录做任何的操作都不会对 lower 做变更。所有的操作都是对在 upper 做 。

  • copy_up只在第一次写时对文件做copy_up操作,后面的操作都不再需要做copy_up,都只操作这个文件,特别适合大文件的场景。overlay的 copy_up操作要比AUFS相同的操作要快,因为AUFS有很多层,在穿过很多层时可能会有延迟,而overlay 只有两层。而且overlay在2014年并入linux kernel mailline ,但是aufs并没有被并入linux kernel mailline ,所以overlay 可能会比AUFS快。

8.3.2.1 实践overlayfs的工作过程及特性

1、在宿主机上我们进入到/data/目录下,去创建挂载目录,在演示overlayFS的工作过程

#进入到data目录下
[15:28:32 root@docker ~]#cd /data/

#创建一个overlay子目录
[16:00:46 root@docker data]#mkdir overlay

#进入到overlay目录中
[16:01:45 root@docker data]#cd overlay/

2、创建overlayFS的挂载目录。

#创建挂载目录
[16:01:47 root@docker overlay]#mkdir {low,upper,work,merged}

#创建完成
[16:03:27 root@docker overlay]#ls
low  merged  upper  work

work:   #我们的工作目录不需要管理
upper:  #中间层目录
low:    #最底层目录
merged: #用户的挂载层

3、使用overlay的挂载命令进行挂载overlay的文件系统。

[16:03:28 root@docker overlay]#mount -t overlay overlay -olowerdir=./low,upperdir=./upper,workdir=./work ./merged

mount -t overlay            #指定挂载文件系统时overlay
overlay                     #挂载到当前overlay目录下
-olowerdir=./low             #最底层目录是当前文件下的/low文件
upperdir=./upper            #上一层目录是我们当前文件下的/upper文件
workdir=./work ./merged     #工作目录分别是我们当前的/work /merged  文件

#通过mount加grep过滤显示已经挂载成功了
[16:13:06 root@docker overlay]#mount | grep /data/overlay
overlay on /data/overlay/merged type overlay (rw,relatime,lowerdir=./low,upperdir=./upper,workdir=./work)

4、到 low 目录下我们写一个1.txt文件

#进入到low文件中
[16:14:06 root@docker overlay]#cd low/

#通过echo写入aaaaa的1.txt文件
[16:15:45 root@docker low]#echo "aaaaaa" >> 1.txt

5、再到upper文件中写一个2.txt文件

#进入到upper 文件中
[16:15:55 root@docker low]#cd ../upper/

#通过echo 写入bbbbb的2.txt文件
[16:16:54 root@docker upper]#echo "bbbbb" >> 2.txt

6、回到overlay目录中,通过tree命令查看目录结构会发现惊人的一幕,会发现merged文件多了两个文件,分别是1.txt和2.txt,

#回到/data/overlay/目录下
[16:17:52 root@docker upper]#cd /data/overlay/

#通过tree查看会发现merged文件中多了两个文件,分别是1.txt和2.txt
[16:18:26 root@docker overlay]#tree 
.
├── low
│   └── 1.txt
├── merged
│   ├── 1.txt
│   └── 2.txt
├── upper
│   └── 2.txt
└── work
    └── work

总结:

但是为什么现在我们的merged文件下会多出这两个文件,这就是我们所谓的用户展现层,至上而下去看,如果下面层有的东西上面都会显示,也就是low、upper层有的东西,在merged层都会显示。如果上面层有的会把下面的直接覆盖掉。这句话怎么理解呢我们接着往下看。

7、首先到我们的merged目录中,查看这连个文件的内容和我们分别在low层和upper层中的内容一样

#进入到merged目录
[16:23:39 root@docker overlay]#cd merged/

#查看1.txt文件
[16:37:30 root@docker merged]#cat 1.txt 
aaaaaa

#查看2.txt文件
[16:37:33 root@docker merged]#cat 2.txt 
bbbbb

8、现在我们在 merged目录下对1.txt进行修改,在他的里面追CCCCCCC的内容。

#通过echo 追加CCCCC到1.txt文件中
[16:37:34 root@docker merged]#echo "CCCCCC" >> 1.txt 

#再次查看1.txt发现CCCCCC已经追加进去
[16:39:41 root@docker merged]#cat 1.txt 
aaaaaa
CCCCCC

9、查看所有层那些发生了修改。

#回到/data/overlay/目录下
[16:39:43 root@docker merged]#cd /data/overlay/

#查看low 文件中的1.txt文件发现还是只有aaaaa
[16:40:59 root@docker overlay]#cat low/1.txt 
aaaaaa

10、查看我们的upper文件下面就会多出来一个1.txt文件,这就是之前所说的写时复制,因为修改的操作只会出现在upper层,low层是只读的

#查看我们的upper文件
[16:41:06 root@docker overlay]#cat upper/
1.txt  2.txt 

#并且upper层的1.txt文件也变了,变成了我们刚才修改的CCCCC内容
[16:41:06 root@docker overlay]#cat upper/1.txt 
aaaaaa
CCCCCC

11、那如果我们在用户层merged中,将1.txt文件删除了

#进入到 merged文件
[16:45:25 root@docker overlay]#cd merged/

#删除1.txt文件
[17:26:53 root@docker merged]#rm -fr 1.txt 

12、查看我们的low文件中的1.txt是存在的,因为不会删除low层中的文件。

[17:26:56 root@docker merged]#ll ../low/
total 4
-rw-r--r-- 1 root root 7 Aug 13 16:15 1.txt

#查看low文件中的1.txt
[17:28:14 root@docker merged]#cat ../low/1.txt 
aaaaaa

13、但是通过 ls 查看我们的upper层就会发现,1.txt文件已经变为了C文件,字符设备文件,这个代表在我们的overlay中已经被删除了,也就意味着只要是在upper层显示这种格式的至上而下去看的话,这个upper层的1.txt会把下面low层的1.txt给他覆盖掉,覆盖的结果就是在用户层显示这个结果已经不在了

[17:28:20 root@docker merged]#ll ../upper/
total 4
c--------- 1 root root 0, 0 Aug 13 17:26 1.txt
-rw-r--r-- 1 root root    6 Aug 13 16:17 2.txt

#并且通过cat查看他提示说没有这样的文件
[17:30:20 root@docker merged]#cat ../upper/1.txt 
cat: ../upper/1.txt: No such device or address

他会欺骗用户层。实际在low文件中还有1.txt文件。但是在用户显示层就没有了,因为upper层的优先级比low层搞。所以upper层和low层都有1.txt所以上层将下层覆盖掉,这就是我上层优先级大于下层

14、我们将upper层的1.txt文件删除,merged中的 1.txt文件又回来了,并且这个1.txt 的内容和low层中的 1.txt 文件内容相同,这个就很好的给大家展示我们的存储驱动系统的写时复制机制,以及由上至下去看会发现我们的上层优先级大于下层

#先查看 low层中的1.txt
[17:38:42 root@docker overlay]#cat low/1.txt 
aaaaaa

#然后把upper层中的1.txt文件删除
[17:38:46 root@docker overlay]#rm -fr upper/1.txt 

#再查看merged层就会发现1.txt文件又回来了
[17:40:14 root@docker overlay]#ll merged/
total 8
-rw-r--r-- 1 root root 7 Aug 13 16:15 1.txt
-rw-r--r-- 1 root root 6 Aug 13 16:17 2.txt

#并且内容就是 low层中的1.txt文件内容
[17:40:18 root@docker overlay]#cat merged/1.txt 
aaaaaa

8.3.3 修改为overlayfs 存储驱动

如果我们安装完了docker 之后,通过docker info查看到我们的存储驱动不是我们的overlay的话,建议修改为我们的overlay启动。

[17:40:23 root@docker overlay]#docker info

修改的方式:

#先把我们的overlay加载到我们的模块加载中
echo "overlay" > /etc/modules-load.d/overlay.conf

#查看当前的模块加载方式
cat /proc/modules|grep overlay

#重启服务器
reboot

#把默认的存储引擎改为overlay即可
vim /etc/systemd/system/docker.service
        --storager-driver=overlay
点赞