docker存储驱动介绍


OverlayFS是内核提供的文件系统,overlay和overlay2是docker的存储驱动;docker支持多种graphDriver,包括vfs、devicemapper、overlay、overlay2、aufs等等,其中最常用的就是aufs了,但随着linux内核3.18把overlay纳入其中,overlay的地位变得更重。

​OverlayFS​​​是一个类似于​​AUFS​​​ 的现代联合文件系统,但更快,实现更简单。Docker为​​OverlayFS​​​提供了一个存储驱动程序。​​OverlayFS​​​是内核提供的文件系统,​​overlay​​​和​​overlay2​​​是​​docker​​提供的存储驱动

设置存储方式


/etc/docker/daemon.json

{
"storage-driver": "overlay2",
"storage-opts": [
"overlay2.override_kernel_check=true"
]
}

overlay原理


OverlayFS将单个Linux主机上的两个目录合并成一个目录。这些目录被称为层,统一过程被称为联合挂载。OverlayFS底层目录称为lowerdir, 高层目录称为upperdir。合并统一视图称为merged。当需要修改一个文件时,将文件从只读的Lower复制到可写的Upper进行修改,结果也保存在Upper层。在Docker中,底下的只读层就是image,可写层就是Container。

下图是一个docker镜像和docke容器的分层图,docker镜像是lowdir,docker容器是upperdir。而统一的视图层是merged层

docker overlay2存储驱动简介_docker

overlay具有:上下合并,同名覆盖 ,写时拷贝 ,等特点,具体如下:

Lowerdir与Upperdir同名文件在 Merged中显示的只有Upperdir中的同名文件,不同名文件会合并在Merged中显示修改文件或目录策略:
        (1)若文件存在于Upperdir,则直接修改Upperdir中的文件

        (2)若文件只存在于Lowerdir,则先将文件从Lowerdir中拷贝至Upperdir再进行修改

在Merged层创建文件或目录,会直接在Upperdir层创建,在Merged层删除文件策略:
        (1)若文件只存在Upperdir层,则直接在Upprdir层删除文件

        (2)若文件存在Lowerdir层,则在Upperdir层创建一个同名的任何用户都没有任何权限,大小为0的字符设备

基于以上策略,Lowerdir层内容都不会被修改,使得在OverlayFS中,Lower可以是只读的,而Upper则需要是可读写的文件系统。
 

性能对比


使用overlay和overlay2驱动性能好于aufs和devicemapper,在实际生产环境overlay2的性能高于btrfs

  • 页缓存:overlayfs支持页缓存共享,也就是说如果多个容器访问同一个文件,可以共享同一个页缓存。这使得overlay/overlay2驱动高效地利用了内存
  • copy_up:aufs和overlayfs,由于第一次写入都会导致copy_up,尤其是大文件,会导致写延迟,以后的写入不会有问题。由于overlayfs层级 比aufs的多,所以ovelayfs的拷贝高于aufs
  • inode限制:使用overlay存储驱动可能导致inode过度消耗,特别是当容器和镜像很多的情况下,所以建议使用overlay2.

高性能建议


  • 使用高性能磁盘如:SSD
  • 如果是搞IO:建议使用外挂高性能盘

但 overlay2驱动程序本身最多支持128个较低的OverlayFS层。此功能可为与层相关的Docker命令(如docker buildand)提供更好的性能docker commit,并在后备文件系统上占用更少的inode。

overlay2镜像结构


在路径/var/lib/docker/overlay2/下,每个镜像层都有一个对应的目录,包含了该层镜像的内容

overlay2 容器结构


启动一个容器,也是载/var/lib/docker/overlay2目录下生成一层容器层,目录包括diff,link,lower,merged,work,diff记录每一层自己内容的数据,link记录该层链接目录(实际是目录下到层的链接),比如在容器中创建目录或在diff新增该目录 

[root@localhost b6c81a19e3b5327bf45aa9296721d78ebfaa8eec0ade4f837117eb4a2a7cad1e]# ll
total 8
drwxr-xr-x 6 root root 76 Jul 17 15:13 diff
-rw-r--r-- 1 root root 26 Jul 17 15:11 link
-rw-r--r-- 1 root root 173 Jul 17 15:11 lower
drwx------ 3 root root 18 Jul 17 15:11 work

实战


创建如下几个目录:

[root@localhost tmp]#  mkdir -p lower upper merger worker
[root@localhost tmp]# ll
total 0
drwxr-xr-x 2 root root 6 Jul 20 17:11 lower
drwxr-xr-x 2 root root 6 Jul 20 17:11 merger
drwxr-xr-x 2 root root 6 Jul 20 17:11 upper
drwxr-xr-x 2 root root 6 Jul 20 17:11 worker

创建内容如下:

[root@localhost lower]# echo '1.txt lower' >1.txt
[root@localhost lower]# echo '3.txt lower' >3.txt


[root@localhost upper]# echo '1.txt upper' >1.txt
[root@localhost upper]# echo '2.txt upper' >2.txt

[root@localhost tmp]# tree
.
├── lower
│ ├── 1.txt
│ └── 3.txt
├── merger
├── upper
│ ├── 1.txt
│ └── 2.txt
└── worker

加载overlay支持,嵌入式可在内核编译时用make menuconfig配置overlay支持

[root@localhost tmp]# modprobe overlay

创建overlay

[root@localhost tmp]# mount -n -t overlay overlayfs:/overlay -o lowerdir=lower/,upperdir=upper/,workdir=worker/ merger/

创建完后结果(可看出merger层的文件是lower层和upper层的不同名文件合并,同名的文件为upper层文件覆盖)

[root@localhost tmp]# tree 
.
├── lower
│ ├── 1.txt
│ └── 3.txt
├── merger
│ ├── 1.txt
│ ├── 2.txt
│ └── 3.txt
├── upper
│ ├── 1.txt
│ └── 2.txt
└── worker
└── work

[root@localhost tmp]# cd merger/
[root@localhost merger]# cat 1.txt
1.txt upper

(1)在merger中创建文件

[root@localhost merger]# echo 'meger' > meger1.txt
[root@localhost merger]# cd ..
[root@localhost tmp]# tree
.
├── lower
│ ├── 1.txt
│ └── 3.txt
├── merger
│ ├── 1.txt
│ ├── 2.txt
│ ├── 3.txt
│ └── meger1.txt
├── upper
│ ├── 1.txt
│ ├── 2.txt
│ └── meger1.txt
└── worker
└── work

(2)在merger中修改文件,分在upper层存在的和只在lower层存在的


[root@localhost merger]# echo "change 1.txt in meger"> 1.txt
[root@localhost merger]# cat ../upper/1.txt
change 1.txt in meger
[root@localhost merger]# cat ../lower/1.txt
1.txt lower


[root@localhost merger]# echo 'change in meger' > 3.txt
[root@localhost merger]# cat ../upper/3.txt
change in meger
[root@localhost merger]# cat ../lower/1.txt
1.txt lower

(3)在merger中删除文件,分只在upper层存在的和在lower层存在的 

[root@localhost merger]# rm -rf 1.txt 
[root@localhost merger]# cd ..
[root@localhost tmp]# tree
.
├── lower
│ ├── 1.txt
│ └── 3.txt
├── merger
│ ├── 2.txt
│ ├── 3.txt
│ └── meger1.txt
├── upper
│ ├── 1.txt
│ ├── 2.txt
│ └── meger1.txt
└── worker
└── work

[root@localhost upper]# cat 1.txt
cat: 1.txt: No such device or address
[root@localhost upper]# cat ../lower/1.txt
1.txt lower