我觉得这个教程真正的意义是带大家了解一下Overlay文件系统,大家如果还想更深入的了解,也可以自己再找一下相关资料,我这里只是带大家先入个门,至于甜糖说不定哪天就消失了,但是这些知识点你可以用在其它地方,希望这个帖子的生命周期比甜糖长,也希望我不要一语成谶。

简单介绍一下Overlay文件系统

OverlayFS是一种联合文件系统(UnionFS),分为上下两个层,我们可以理解成有2个目录lowerupper,但是经过Overlay文件系统挂载后,展现给用户的是一个叫做merged的目录,在这个目录用户看到的内容就是lowerupper两个目录文件的合集,如果用户把文件写入merged目录,实际文件是写入了upper目录,lower目录是一个只读层,文件不会做任何修改。

大家可以参考一下上面这个图,lower目录就是只读层,用户对Overlay的任何修改都写入了upper层,当然还会涉及到文件删除的情况,这里不展开说。这种联合文件系统有很多应用,比如在docker中,每个容器的底层就是它对应的镜像,也就是无论你创建多少个镜像的容器,底层的文件是只有一份,不会浪费多余的磁盘空间。当然具体的实现还有很多特别的处理,但是基本思路就是我说的这样。

用Overlay文件系统实现甜糖缓存共享思路

可能聪明的你们已经想到了,我们是不是可以用类似docker处理镜像和容器的方法共享缓存文件文件呢? 假设我们有2个甜糖的镜像,我给每个甜糖镜像分配一个缓存目录,假设分别为 dir1 dir2 我们分别把2个Overlay文件系统挂载到这2个目录,这两个目录的底层(lower)都是同一份缓存目录,这样就达到共享缓存的目的,而且这两个目录互不影响,对文件的更改都会写入对应的upper层。

具体的实现方法

  1. 先准备一份缓存 假设这个缓存的目录是/mnt/usbdisk/static_cache,这个缓存目录的结构如下

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    
    static_cache/
    └── .yfnode
    	└── cache
            ├── 00318F7338ACA0DDB4205ACA2B2C5A9CE11990F0
            ├── 00318F7338ACA0DDB4205ACA2B2C5A9CE11990F0.chr
            ├── 00318F7338ACA0DDB4205ACA2B2C5A9CE11990F0.mem
            ├── 00318F7338ACA0DDB4205ACA2B2C5A9CE11990F0.task
            ├── 00318F7338ACA0DDB4205ACA2B2C5A9CE11990F0.tn
            ├── 00318F7338ACA0DDB4205ACA2B2C5A9CE11990F0.torrent
            └── 00318F7338ACA0DDB4205ACA2B2C5A9CE11990F0.vdata_0.!mv
    	└── config
    

    注意一定要删除static_cache/.yfnode/config目录,一定要删除,一定要删除,一定要删除,只留static_cache/.yfnode/cache目录,/mnt/usbdisk/static_cache这个目录就是我们的lower层,是所有甜糖容器缓存目录的底层。

  2. 在/mnt/usbdisk目录下新建ttnode1目录,并新建3个子目录mnts upper work 结构如下

    1
    2
    3
    4
    
    /mnt/usbdisk/ttnode1
    ├── mnts
    ├── upper
    └── work
    

    下面我们开始挂载缓存目录,我先用命令的方法,之后我会介绍如何修改fstab文件,做到启动的时候自动挂载

    1
    2
    
    cd /mnt/usbdisk/ttnode1
    mount -t overlay overlay -o lowerdir=/mnt/usbdisk/static_cache,upperdir=./upper,workdir=./work,index=off,nfs_export=off  ./mnts
    

    如果执行完以上两条语句,没有任何错误提示,那么恭喜你,我们的缓存目录已经挂载成功了。

    /mnt/usbdisk/ttnode1/mnts这个目录现在就被挂载到了一个Overlay文件系统,

    • 这个文件系统的底层(lowerdir)是/mnt/usbdisk/static_cache

    • 上层(upperdir)是/mnt/usbdisk/ttnode1/upper

    • 工作目录(workdir)是/mnt/usbdisk/ttnode1/work

    我们如果查看/mnt/usbdisk/ttnode1/mnts这个目录,里面会有/mnt/usbdisk/static_cache目录中的所有文件,我们以后对/mnt/usbdisk/ttnode1/mnts这个目录所做的全部修改都将被写入/mnt/usbdisk/ttnode1/upper,而/mnt/usbdisk/static_cache做为只读层(lowerdir)是不会被修改的。

    下面我们创建容器的时候把缓存目录指定为/mnt/usbdisk/ttnode1/mnts就可以了, 例如这样

    1
    2
    3
    4
    5
    6
    7
    8
    
    docker run -itd \
      -v /mnt/usbdisk/ttnode1/mnts:/mnts \
      --name ttnode \
      --hostname ttnode1 \
      --net=macnet --ip=192.168.2.2 --dns=114.114.114.114 --mac-address C2:F2:9C:C5:B2:94 \
      --privileged=true \
      --restart=always \
      ericwang2006/ttnode
    

    当然这里用到了macvlan,如果不清楚可以看我的教程。 用同样的方法我们可以继续创建/mnt/usbdisk/ttnode2, /mnt/usbdisk/ttnode3 你想开多少实例就开多少

  3. 如何开机自动挂载overlay文件系统

    其实很简单,修改/etc/fstab文件, 增加一行

    1
    
    overlay /mnt/usbdisk/ttnode1/mnts overlay defaults,lowerdir=/mnt/usbdisk/static_cache,upperdir=/mnt/usbdisk/ttnode1/upper,workdir=/mnt/usbdisk/ttnode1/work,index=off,nfs_export=off 0 0
    

    修改完这个文件,重启之前,请仔细核对,不要写错任何目录,否则可能造成系统不能启动

  4. 优点总结

    这种方法做到了共享一份缓存,但是每个目录彼此独立,写入的操作不受任何影响。

  5. 补充一下

    • lower目录可以为任何linux支持的文件系统,可以是nfs、cifs这样的远程文件系统,也可以是另一个overlayfs
    • upperdir所在的文件系统不能是nfs、cifs、gfs2、vfat、ocfs2、fuse、isofs、jfs和另一个overlayfs等文件系统
    • workdir和upperdir必须在同一文件系统下,而lower不是必须的

    如果没有特殊需要,我建议这几个目录都用ext4文件格式

  6. 合并文件脚本

    运行一段时间后,可能底层有不少文件应该删除,上层又有不少文件写入,为了充分利用磁盘空间,我给大家写一段合并脚本 运行脚本前请注意,一定先卸载overlay目录 卸载命令

1
2
docker stop ttnode1
umount /mnt/usbdisk/ttnode1/mnts

有几个容器就重复上面的命令几次,目录根据自己情况修改 然后把下面的代码存成一个shell脚本执行,其中脚本开头的变量lower和upper目录根据自己情况修改,有几个目录就执行几次,注意做好数据备份工作,万一造成意料之外的结果本人概不负责。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#!/bin/bash

lower="/mnt/usbdisk/static_cache/.yfnode/cache"
upper="/mnt/usbdisk/ttnode/upper/.yfnode/cache"
filelist="/tmp/cfile.txt"

cd $upper
find ./ -maxdepth 1 -type c > $filelist

cd $lower
xargs -I{} rm -rf {}<$filelist

cd $upper
xargs -I{} rm -rf {}<$filelist

rsync -av $upper/* $lower

rm -rf $upper

更多内容大家可以参考一下这里