干货 | Docker 文件系统的分层与隔离 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
cloudwise
V2EX    监控宝

干货 | Docker 文件系统的分层与隔离

  •  
  •   cloudwise 2015-09-14 15:41:04 +08:00 2270 次点击
    这是一个创建于 3727 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现在就开始天的分享~
    M 老师: docker 的很多特性都表现在它所使用的文件系统上,比如大家都知道 docker 的文件系统是分层的,所以它可以快速迭代,可以回滚。这个回滚机制跟 github 很像,每次提交的时候都会有一个 id , 回滚就是跟据这个 id 来操作的。

    M 老师: docker 所支持的文件系统有以下几种: Aufs 、 devicemapper 、 btrfs 和 Vfs ,其中前三种是联合文件系统,可以支持分层, VFS 不支持。平时用的最多的是 aufs 和 devicemapper 。

    M 老师:先介绍一下 Aufs , Aufs (advanced multi layered unification filesystem ), 直译过来就是高级分层联合文件系统,做为一种 Union FS ,它支持将不同的目录挂载到同一个虚拟文件系统下。

    M 老师:这个怎么理解呢,通过一条命令我们来看一下:

    mount -t aufs -o br=/tmp/dir1=ro:/tmp/dir2=rw none /tmp/newfs

    M 老师:大家有条件的可以一起做下实验,方便理解,-o 指定 mount 传递给文件系统的参数; br 指定需要挂载的文件夹,这里包括 dir1 和 dir2 ; ro/rw 指定文件的权限只读和可读写; none 这里是挂载的设备,而没有设备用 none 表示。

    M 老师:为什么要有只读和可读写两种呢,因为 docker 在启动容器的时候就会用到这两种,而上面这个例子是模拟这个 docker 文件系统模型。

    问:启动 docker 的时候,对硬盘使用只读,意义在于什么?

    答:这个问题很好,一个 image 可以启动多个 container ,这时候会有一个问题,如果每个 container 对大家共有的部分都有可写的权限,就会出问题。所以 docker 启动的时候会加载镜像的文件系统那层是只读的,然后每个 contianer 获取自己的可读写的层,如果 container 要修改只读层的文件,那么该文件就会从只读层提取到读写层。只读层的文件就被读写层的文件覆盖了,但只读层的那个文件依然存在 这个就实现了文件系统上的隔离。

    问:就像我们写程序抵触共享的东西不变,只是利用这个共性来底层共享?

    答:是的。

    问:加那个 none 是干什么用的?

    答: none 这里没有设备,用 none 表示,其实是没有意义的。但命令要求要有一个设备,这条命令中设备是 none

    问:这个命令是在容器里执行的吗?还是在宿主机?

    答:容器。

    M 老师:继续咱们的分享,刚才实验的结果是什么样子呢,就是把 /tmp/dir1 和 /tmp/dir2 合并之后挂载到 /tmp/newfs ,如果这时在 /tmp/dir1 下创建一个文件 a ,/tmp/dir2 下创建一个文件 b 则 在 /tmp/newfs 会看到 a,b 这两个文件,这就是联合,并且 a 文件是只读的。

    M 老师:如果有相同的文件则以先挂载的为准,后面挂载的操作会被忽略掉。大家可以想像一下,我每做一次操作都相当于去挂载一个新的目录,这样所有的操作就保存下来了。当然实际情况并不是每次操作都去挂载。当 container 发生改变的时候,并且我提交 commit 才会重新挂载一层。

    问:比如 mkdir test 这也算是重新挂载了一层?

    答: docker 有一个命令 docker commit ,执行这个的时候会重新挂载一层。

    M 老师: 可能还会有一些不理解,下面用实际的 docker 镜像来举个例子。大家启动一个 container 之后,执行 docker save ,可以把 container 保存成镜像。

    例如:

    docker save

    cloud_jiankongbao:01.tar

    cloud_jiankongbao:01

    其中 cloud_jiankongbao:01.tar 是镜像的名字,后面的 cloud_jiankongbao:01 是这个 container 的 ID ,可以看到,保存下来的是 tar 包。 不是.iso 文件^_^

    M 老师:镜像解压之后是什么呢,我们来看一下:

    ls .

    a005304e4e74c1541988d3d1abb170e338c1d45daee7151f8e82f8460634d329

    d9bde94c518a16a886514758b6b4431200145ecd58e30c5633ac3c0256544d77

    f1b10cd842498c23d206ee0cbeaa9de8d2ae09ff3c7af2723a9e337a6965d639

    fb9cc58bde0c0a8fe53e6fdd23898e45041783f2d7869d939d7364f5777fde6f

    里面有四个目录,其实分别是 4 个 docker 的 ID ,每次使用 docker commit 提交对 docker 的修改之后就会产生一个新的 id ,就是通过这个 ID 实现对镜像的回滚。

    M 老师:这 4 个目录之间是有关系的。这个关系可以通过 docker image --tree 来查看。

    docker images --tree

    └─f1b10cd84249 Virtual Size: 0 B

    └─fb9cc58bde0c Virtual Size: 203.1 MB

    └─a005304e4e74 Virtual Size: 203.1 MB

    └─d9bde94c518a Virtual Size: 1.957 GB Tags: cloud_jiankongbao:01

    M 老师:每个目录下有 json layer.tar VERSION 这三个文件,我们现在只研究他们的结构,所以只看 layer.tar 这个文件。

    M 老师:我们到一个目录下把 layer.tar 解压一下

    dfb9cc58bde0c0a8fe53e6fdd23898e45041783f2d7869d939d7364f5777fde6f;tar -xflayer.tar;ls

    ls fb9cc58bde0c0a8fe53e6fdd23898e45041783f2d7869d939d7364f5777fde6f/

    binetcjsonliblost+foundmntprocsbinsrvtmpvar

    devhomelayer.tar lib64 mediaopt root selinux sys usr VERSION

    问:为什么会提交四次?

    答:提交 4 次是我们自己提交的.

    M 老师:在使用 docker 的过程中我们需要保存自己的修改, docker commit 执行完之后就把 container 中的内容回写到镜像中了,就相当于加了一层文件系统,每次提交后就生成了一个新的镜像。 4 个 ID 是 4 次提交的镜像的 ID ,这 4 个 ID 其实相当于一个镜像的 4 个 tag 。我们再看一下 4 个镜像 ID 的系统:

    f1b10cd84249 这个镜像是初始镜像,大小为 0




    fb9cc58bde0c 这个镜像是在 f1b10cd84249 基础上创建新的镜像;

    a005304e4e74 是以 fb9cc58bde0c 为基础创建新的镜像,是树状继承的关系;

    M 老师:我们再看一下不同 ID 目录下的 bin 目录。

    ls a005304e4e74c1541988d3d1abb170e338c1d45daee7151f8e82f8460634d329/bin/

    gtar tar




    a005304e4e74 只有两个文件, fb9cc58bde0c 包括了大部分 bin 下的文件,对应的场景是 fb9cc58bde0c ,是装好操作系统, 然后我又装了 tar 这个工具。 docker commit 提交之后,就是 a005304e4e 。

    问:可以认为 fb9cc58bde0c 是一个最小化的 OS

    答:可以这么理解。

    M 老师:最后简单说一下 devicemapper ,回到最开始说的, docker 支持多种文件系统。 devicemapper 是利用了 Snapshot 和 Thinly-Provisioned Snapshot 两种原理,将多个快照挂在同一个卷下从而实现文件系统的分层。这里的快照技术其实就是 vm 中的快照。

    M 老师:刚才说的 autofs 是将不同的目录挂到一个虚拟目录, devicemapper 就是把多个快照挂载到同一个卷下,不过使用 devicemapper 的话,一个 container 的大小最大只能是 10G ,启动 docker daemon 时用参数-s 指定:

    docker -d -s devicemapper

    M 老师:当容器基于镜像启动之后,每个容器都会获得自己的写读可写的文件系统层。原镜像的那部分文件系统是只读的,从而实现每个容器的在文件系统上的隔离。

    问: autofs 最大一个 container 是多大?

    答:没有限制,直到物理服务器没有资源,但通常不会将数据库和 LOG 保存在镜像中,所以也不会写的太大,因为 docker 本身是轻量级的。

    M 老师:平时大家都在说 dokcer 是弱隔离的,因为他没有隔离的很彻底,比如内核是跟大家共用的,跟宿主机共用同一个内核。 SELinux 、 Cgroups 以及 /sys 、/proc/sys 、/dev/sd*等目录下的资源是与宿主机共用的。如果要隔离的彻底那就是 VM 了,而且如果 dockers 要想实现这些隔离就必然要牺牲一下现在轻量级的特性。

    M 老师:好吧,今天的分享就到这里了,谢谢大家!
    目前尚无回复
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     959 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 23ms UTC 19:02 PVG 03:02 < href="/worldclock#lax">LAX 11:02 JFK 14:02
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86