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层
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