1.介绍
联合文件系统,overlayFs依赖并建立在其它的文件系统之上(例如ext4fs和xfs等等),并不直接参与磁盘空间结构的划分,仅仅将原来底层文件系统中不同的目录进行“合并”.
2.命令
mount -t overlay overlay -o lowerdir=lower1:lower2:lower3,upperdir=upper,workdir=work merged
1)lowerdir=xxx:指定用户需要挂载的lower层目录(支持多lower,最大支持500层);
2)upperdir=xxx:指定用户需要挂载的upper层目录;
3)workdir=xxx:指定文件系统的工作基础目录,挂载后内容会被清空,且在使用过程中其内容用户不可见;
4) merged: 最后merge到哪个目录
- 对用户来说,他只知道有一个merge目录,merge下的文件来自哪个lower,哪个upper,他都不知道.
- merge规则:如果存在同名文件,那么upper>lower[n]>lower[n+1].如果存在同名目录,那么取并集.
- 读写规则:
- 对merge文件的操作:如果操作的文件原属于upper目录,那么会直接造成对源文件的修改;如果操作的文件原属于lower目录,那么会复制一份到upper目录.从此原lower中的文件与merge目录没有任何关系,有关系的是upper下的同名文件.
- 对原文件的操作:对原文件的操作,均会影响merged文件的内容,因为他们本身就是映射的.
3.实际操作:
创建一些目录以及文件.
[root@tv2-callchain-tool-02 testOverlay]# tree .
.
├── l1
│ ├── l1-1
│ └── l1-2
├── l2
│ ├── l2-1
│ └── l2-2
├── result
├── u
│ └── u1
└── work
执行mount操作
[root@tv2-callchain-tool-02 testAufs]# mount -t overlay overlay -o lowerdir=l1:l2,upperdir=u,workdir=work result
查看当前结构
[root@tv2-callchain-tool-02 testOverlay]# tree .
.
├── l1
│ ├── l1-1
│ └── l1-2
├── l2
│ ├── l2-1
│ └── l2-2
├── result
│ ├── l1-1
│ ├── l1-2
│ ├── l2-1
│ ├── l2-2
│ └── u1
├── u
│ └── u1
└── work
└── work
由此可见: l1,l2,u目录下的文件全部merge到了 result目录.下面做一些测试
3.1.修改原文件,看是否merge后的文件也会改.
[root@tv2-callchain-tool-02 testOverlay]# echo "old l1">l1/l1-1
[root@tv2-callchain-tool-02 testOverlay]# cat l1/l1-1
old l1
[root@tv2-callchain-tool-02 testOverlay]# cat result/l1-1
old l1
可见,文件已经改了
3.2.修改result中的文件.修改原本属于upper的文件
[root@tv2-callchain-tool-02 testOverlay]# echo "upper txt">result/u1
You have new mail in /var/spool/mail/root
[root@tv2-callchain-tool-02 testOverlay]# cat result/u1
upper txt
[root@tv2-callchain-tool-02 testOverlay]# cat u/u1
upper txt
[root@tv2-callchain-tool-02 testOverlay]# tree .
.
├── l1
│ ├── l1-1
│ └── l1-2
├── l2
│ ├── l2-1
│ └── l2-2
├── result
│ ├── l1-1
│ ├── l1-2
│ ├── l2-1
│ ├── l2-2
│ └── u1
├── u
│ └── u1
└── work
└── work
3.3.修改result下原本属于lower层的文件.
[root@tv2-callchain-tool-02 testOverlay]# echo "result/lower txt">result/l2-1
[root@tv2-callchain-tool-02 testOverlay]# cat result/l2-1
result/lower txt
[root@tv2-callchain-tool-02 testOverlay]# cat l2/l2-1
[root@tv2-callchain-tool-02 testOverlay]# tree .
.
├── l1
│ ├── l1-1
│ └── l1-2
├── l2
│ ├── l2-1
│ └── l2-2
├── result
│ ├── l1-1
│ ├── l1-2
│ ├── l2-1
│ ├── l2-2
│ └── u1
├── u
│ ├── l2-1
│ └── u1
└── work
└── work
注意这里:
result/l2-1 内容变了,但是原本目录下 l2/l2-1没变,因为是只读层, upper层下多了l2-1文件.此时数据是更改的内容.此时upper下的同名文件隐藏掉lower下的文件.你再修改lower下的文件,result的内容也不会变了.
3.4.动态添加一个文件
3.4.1 添加到 lower,在upper无同名./添加到upper,lower无同名
[root@tv2-callchain-tool-02 l1]# touch l1-add
[root@tv2-callchain-tool-02 testOverlay]# tree .
.
├── l1
│ ├── l1-1
│ ├── l1-2
│ └── l1-add
├── l2
│ ├── l2-1
│ └── l2-2
├── result
│ ├── l1-1
│ ├── l1-2
│ ├── l1-add
│ ├── l2-1
│ ├── l2-2
│ └── u1
├── u
│ ├── l2-1
│ └── u1
└── work
└── work
######添加到upper,lower无同名#########
[root@tv2-callchain-tool-02 testOverlay]# tree .
.
├── l1
│ ├── l1-1
│ ├── l1-2
│ └── l1-add
├── l2
│ ├── l2-1
│ └── l2-2
├── result
│ ├── l1-1
│ ├── l1-2
│ ├── l1-add
│ ├── l2-1
│ ├── l2-2
│ └── u4
├── u
│ ├── l1-2
│ ├── l2-1
│ └── u4
└── work
└── work
多会合并的
4.2 添加lower,且upper有同名/ 添加upper,且lower有同名/添加upper,在lower有同名,都不行
###添加lower,在upper有同名####肯定无效
[root@tv2-callchain-tool-02 testOverlay]# touch l1/u4
You have new mail in /var/spool/mail/root
[root@tv2-callchain-tool-02 testOverlay]# echo "11">l1/u4
[root@tv2-callchain-tool-02 testOverlay]# cat result/
l1-1 l1-2 l1-add l2-1 l2-2 u4
[root@tv2-callchain-tool-02 testOverlay]# cat result/u4
###添加lower,在lower有同名#### 无效
[root@tv2-callchain-tool-02 testOverlay]# echo "l1 add">l1/l2-2
[root@tv2-callchain-tool-02 testOverlay]# cat result/l
l1-1 l1-2 l1-add l2-1 l2-2
[root@tv2-callchain-tool-02 testOverlay]# cat result/l
l1-1 l1-2 l1-add l2-1 l2-2
[root@tv2-callchain-tool-02 testOverlay]# cat result/l
l1-1 l1-2 l1-add l2-1 l2-2
[root@tv2-callchain-tool-02 testOverlay]# cat result/l2-2
###添加upper,在lower有同名#### 无效
3.5.删除呢??
删除需要考虑到几种场景.
a删除的文件是upper层,且lower层没有同名文件,很好办.直接删除就行了
b删除lower文件,并且upper没有同名文件名.
有点难搞,要保证lower原文件不能删除,又要保证用户见不到该文件. overlayFs使用了障眼法.Whiteout文件.Whiteout文件在用户删除文件时创建,用于屏蔽底层的同名文件,同时该文件在merge层是不可见的
类似一个黑名单
当用户在merge层通过ls命令(将通过readddir系统调用)检查父目录的目录项时,overlayfs会自动过过滤掉和whiteout文件自身以及和它同名的lower层文件和目录,达到了隐藏文件的目的,让用户以为文件已经被删除了
c要删除的文件是upper层覆盖lower层的文件,要删除的目录是上下层合并的目录
要把upper层的删除,并且屏蔽掉lower层文件
3.6.创建一个文件或目录
3.7.rename文件/目录
4.docker怎么使用的
[root@tv2-callchain-tool-02 data]# mount|grep overlay
overlay on /var/lib/docker/overlay2/44f8d7c28f545bd10acaea67d7138774445389171a66b418dae0d83469c8e29b/merged type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/AYCIYBZZOU2SBB7HAWWC53G5MV:/var/lib/docker/overlay2/l/7AC2GBWZ3VYQGR2IW6FVGTJELH,upperdir=/var/lib/docker/overlay2/44f8d7c28f545bd10acaea67d7138774445389171a66b418dae0d83469c8e29b/diff,workdir=/var/lib/docker/overlay2/44f8d7c28f545bd10acaea67d7138774445389171a66b418dae0d83469c8e29b/work)
overlay on /data/dockerTest/testAufs/merged type overlay (rw,relatime,lowerdir=a:b,upperdir=c,workdir=result)
overlay on /data/dockerTest/testOverlay/result type overlay (rw,relatime,lowerdir=l1:l2,upperdir=u,workdir=work)
overlay on /data/dockerTest/testOverlay/m type overlay (rw,relatime,lowerdir=a:b,upperdir=c,workdir=work)
后面三个是我们测试时用的
第一个是当前docker启动的容器用的
可以看到:
1.lower是/var/lib/docker/overlay2/l/ 文件夹下的某几个文件
只读层,这些文件一起构成了某个镜像.例如 Ubuntu+java+tomcat+nginx+webApp构成了整个应用的镜像
Dockerfile 中的每个原语执行后,都会生成一个对应的镜像层.即使原语本身并没有明显地修改文件的操作(比如,ENV 原语),它对应的层也会存在。只不过在外界看来,这个层是空的
2.upper是upperdir=/var/lib/docker/overlay2/44f8d7c28f545bd10acaea67d7138774445389171a66b418dae0d83469c8e29b/diff 文件
这个是读写层.容器就是一个读写层,我们在容器里增删改操作会都是写在这里.
一旦我们容器运行时,提交成为一个镜像.那么 会把该读写层,变为只读层!!主要:容器是可写,镜像是只读!
3.merge文件是/var/lib/docker/overlay2/44f8d7c28f545bd10acaea67d7138774445389171a66b418dae0d83469c8e29b/merged 这不就是操作系统吗??
[root@tv2-callchain-tool-02 merged]# ll /var/lib/docker/overlay2/44f8d7c28f545bd10acaea67d7138774445389171a66b418dae0d83469c8e29b/merged
total 48
drwxr-xr-x 2 root root 12288 Oct 13 07:47 bin
drwxr-xr-x 1 root root 4096 Nov 25 12:49 dev
drwxr-xr-x 1 root root 4096 Nov 25 12:49 etc
drwxr-xr-x 2 nfsnobody nfsnobody 4096 Oct 13 07:47 home
drwxr-xr-x 2 root root 4096 Nov 25 12:49 proc
drwx------ 2 root root 4096 Oct 13 07:47 root
drwxr-xr-x 2 root root 4096 Nov 25 12:49 sys
drwxrwxrwt 2 root root 4096 Oct 13 07:47 tmp
drwxr-xr-x 3 root root 4096 Oct 13 07:47 usr
drwxr-xr-x 4 root root 4096 Oct 13 07:47 var
容器创建成功后,会添加一个upper层,运行时的修改都是在针对 upper层操作.如果要修改lower层呢??那么需要写时复制了,就是把lower层复制到upper层,然后你就可以修改了.
如果容器退出,那么upper层会删除掉,之前的lower层不会变,你再用同样的镜像去生成一个容器,还是使用同样的lower层.
5.volume原理
刚刚我们分析了docker的存储层的原理.在此总结下:docker的镜像是又多个只读层叠加的.容器是这些只读层+读写层.如果运行的时候,对文件作出了修改,那么会使用cow机制,将lower层数据拷贝到upper层.当删除容器后,读写层也会删除.
1.启动一个容器,使用volume
docker run -it --name volume-test -h CONTAINER -v /data/testvolume busybox /bin/sh
2.查看容器中的数据.啥都没有
/data/testvolume # ls /data/testvolume/
/data/testvolume #
3.查看
[root@tv2-callchain-tool-02 data]# docker inspect volume-test|grep volume
"Name": "/volume-test",
"Type": "volume",
"Source": "/var/lib/docker/volumes/c40fae3cefad3ffb1eac6fa584a131551ff7c3e5723b15a153a9ca9332316af3/_data",
"Destination": "/data/testvolume",
"/data/testvolume": {}
说明/data/testvolume 映射在了/var/lib/docker/volumes/c40fae3cefad3ffb1eac6fa584a131551ff7c3e5723b15a153a9ca9332316af3/_data
注意,这里是docker volumes目录,说明volume已经绕过了overlayfs.我们在_data下新增一个文件
[root@tv2-callchain-tool-02 ~]# cd /var/lib/docker/volumes/e124d9f2cf43d41f6c2882bac080db974636c6cbbcd01f28aaf3ffe553b4514b/_data
[root@tv2-callchain-tool-02 _data]# touch testhh
查看容器
/data/testvolume # ls /data/testvolume/
testhh
没有问题
我们在容器里创建
/data/testvolume # touch /data/testvolume/testhh2
在宿主机的目录上
[root@tv2-callchain-tool-02 _data]# ls /var/lib/docker/volumes/e124d9f2cf43d41f6c2882bac080db974636c6cbbcd01f28aaf3ffe553b4514b/_data
testhh testhh2
我们再看下mount
[root@tv2-callchain-tool-02 data]# mount|grep overlay
overlay on /data/dockerTest/testAufs/merged type overlay (rw,relatime,lowerdir=a:b,upperdir=c,workdir=result)
overlay on /data/dockerTest/testOverlay/result type overlay (rw,relatime,lowerdir=l1:l2,upperdir=u,workdir=work)
overlay on /data/dockerTest/testOverlay/m type overlay (rw,relatime,lowerdir=a:b,upperdir=c,workdir=work)
overlay on /var/lib/docker/overlay2/d95533f356ba958c012a197d35cc8fa8e36c56d1d852ce731b2f5c847b65136a/merged type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/ZOOVPE6ITB5JBEWQW3AIQBLXTE:/var/lib/docker/overlay2/l/7AC2GBWZ3VYQGR2IW6FVGTJELH,upperdir=/var/lib/docker/overlay2/d95533f356ba958c012a197d35cc8fa8e36c56d1d852ce731b2f5c847b65136a/diff,workdir=/var/lib/docker/overlay2/d95533f356ba958c012a197d35cc8fa8e36c56d1d852ce731b2f5c847b65136a/work)
确实没有使用overlayfs
参考:https://blog.csdn.net/luckyapple1028/article/details/78075358 这个文章写得很好