docker存储-overlayfs.镜像底层原理/volume原理

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].如果存在同名目录,那么取并集.
  • 读写规则:
  1. 对merge文件的操作:如果操作的文件原属于upper目录,那么会直接造成对源文件的修改;如果操作的文件原属于lower目录,那么会复制一份到upper目录.从此原lower中的文件与merge目录没有任何关系,有关系的是upper下的同名文件.
  2. 对原文件的操作:对原文件的操作,均会影响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 这个文章写得很好

https://zhuanlan.zhihu.com/p/41958018

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值