自Docker诞生之初,就采用了aufs做为唯一的存储驱动。但因为aufs一直没有进入内核主线,所以各大发行版只有Ubuntu默认包含了aufs支持,这让Docker某种程度上成了专用于Ubuntu的容器技术。

直到后来红帽工程师为其实现了devicemapper存储驱动,其它发行版上使用Docker的技术门槛才低了许多。但是受内核的devicemapper机制的限制,Docker的devicemapper驱动在性能和资源消耗上相比aufs驱动都仍有差距。

直到内核版本3.18,另一个unionfs文件系统实现overlayfs并入了内核主线。而Docker(自1.4.0版本开始)在很短的时间内就提供了对overlayfs存储驱动的试验性支持。从此在各大发行版上使用unionfs做为Docker的存储驱动才成为了可能。

而我本人由于Docker+devicemapper驱动在使用中的种种问题,当然是盼望着尽快试用Docker的overlayfs驱动。

镜像备份

国内下载官方镜像太过费劲,因此在环境更新前要首先将已有的镜像导出。导出使用save命令:

$ docker save -o /media/Storage/dockers/centos.tar centos:centos6
$ docker save -o /media/Storage/dockers/debian.tar debian
......

用同样的命令将所有的镜像全部导出备份。而容器则全部删除,这里不多说。

以下是我docker info命令的完整输出,可以看到我的Docker数据及元数据分别存放在两个逻辑卷上,数据占用空间是8.291GB,共有43个镜像。

$ docker info
Containers: 0
Images: 43
Storage Driver: devicemapper
 Pool Name: docker-254:1-1279-pool
 Pool Blocksize: 65.54 kB
 Data file: /dev/vgroot/lvdocker
 Metadata file: /dev/vgroot/lvdockermeta
 Data Space Used: 8.291 GB
 Data Space Total: 17.18 GB
 Metadata Space Used: 6.197 MB
 Metadata Space Total: 16.78 MB
 Library Version: 1.02.92 (2014-11-28)
Execution Driver: native-0.2
Kernel Version: 3.18.1-1-ARCH
Operating System: Arch Linux
CPUs: 4
Total Memory: 3.753 GiB
Name: ksh-zen
ID: C56B:VEMA:MS6I:ZUGG:J3MO:53U6:IU7B:4HO2:PRRB:O3O2:HZVM:EEZ4

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ora                 prepared            e50218f3bfab        2 weeks ago         309.7 MB
python              3                   474f82d465a5        3 weeks ago         814.9 MB
python              3.4                 474f82d465a5        3 weeks ago         814.9 MB
python              4.4.2               474f82d465a5        3 weeks ago         814.9 MB
python              latest              474f82d465a5        3 weeks ago         814.9 MB
postgres            9                   aaab661c1e3e        4 weeks ago         213.1 MB
postgres            9.3                 aaab661c1e3e        4 weeks ago         213.1 MB
postgres            9.3.5               aaab661c1e3e        4 weeks ago         213.1 MB
postgres            latest              aaab661c1e3e        4 weeks ago         213.1 MB
debian              latest              f6fab3b798be        6 weeks ago         85.1 MB
debian              wheezy              f6fab3b798be        6 weeks ago         85.1 MB
debian              7                   f6fab3b798be        6 weeks ago         85.1 MB
debian              7.7                 f6fab3b798be        6 weeks ago         85.1 MB
centos              centos6             70441cac1ed5        6 weeks ago         215.8 MB

确认所有镜像全部成功导出后停止docker。由于有更新内核并重做文件系统的需求,我还要禁止Docker开机自动启动:

$ sudo systemctl stop docker
$ sudo systemctl disable docker
Removed symlink /etc/systemd/system/multi-user.target.wants/docker.service.

更新软件包

Docker 1.4.0发布后Arch Linux很快就同步到了最新版本,所以我只要直接更新就好:

$ yaourt -Sy docker

而3.18的内核虽然很快就进了testing仓库,但却迟迟没有进入core仓库,所以我要临时启用testing仓库:

$ su -
# vi /etc/pacman.conf

将如下两行的注释去掉:

#[testing]
#Include = /etc/pacman.d/mirrorlist

然后再更新内核才能看到我们想要的3.18。

$ yaourt -Sy linux

内核更新完成之后记得要将/etc/pacman.conf里修改的内容复原。

环境重建

销毁Docker使用的两个逻辑卷及/var/lib/docker目录下所有文件:

$ su -
# lvremove -f /dev/vgroot/lvdocker
  Logical volume "lvdocker" successfully removed
# lvremove -f /dev/vgroot/lvdockermeta
  Logical volume "lvdockermeta" successfully removed
# rm -rf /var/lib/docker

接着重建逻辑卷,创建文件系统并将其挂载,我个人比较偏好使用xfs文件系统,你自己也可以选择ext4:

# lvcreate -L 20G -n lvdocker vgroot
WARNING: ext4 signature detected on /dev/vgroot/lvdocker at offset 1080. Wipe it? [y/n]: y
  Wiping ext4 signature on /dev/vgroot/lvdocker.
  Logical volume "lvdocker" created.
# mkfs -t xfs /dev/vgroot/lvdocker
meta-data=/dev/vgroot/lvdocker   isize=256    agcount=4, agsize=1310720 blks
         =                       sectsz=512   attr=2, projid32bit=1
         =                       crc=0        finobt=0
data     =                       bsize=4096   blocks=5242880, imaxpct=25
         =                       sunit=0      swidth=0 blks
naming   =version 2              bsize=4096   ascii-ci=0 ftype=0
log      =internal log           bsize=4096   blocks=2560, version=2
         =                       sectsz=512   sunit=0 blks, lazy-count=1
realtime =none                   extsz=4096   blocks=0, rtextents=0
# mkdir /var/lib/docker
# mount /dev/vgroot/lvdocker /var/lib/docker
# df
Filesystem                  1K-blocks      Used Available Use% Mounted on
/dev/mapper/vgroot-lvarch     8125880   4833020   2857048  63% /
dev                           1962456         0   1962456   0% /dev
run                           1967700       620   1967080   1% /run
tmpfs                         1967700         0   1967700   0% /dev/shm
tmpfs                         1967700         0   1967700   0% /sys/fs/cgroup
tmpfs                         1967700         8   1967692   1% /tmp
/dev/mapper/vgroot-lvboot      999320     47880    882628   6% /boot
/dev/mapper/vgroot-lvvar      1998672    441904   1435528  24% /var
/dev/mapper/vgroot-lvhome    83845120  79331008   4514112  95% /home
tmpfs                          393544         4    393540   1% /run/user/1000
/dev/sdb1                   167774792 143071912  24702880  86% /media/Storage
/dev/mapper/vgroot-lvdocker  20961280     32928  20928352   1% /var/lib/docker

为了让新文件系统能自动挂载。要以root身份编辑/etc/fstab,加入如下一行内容:

/dev/mapper/vgroot-lvdocker     /var/lib/docker xfs             rw,relatime,attr2,inode64       0 2

然后就可以将机器重启了。

环境确认

重启后/var/lib/docker文件系统应该已经自动挂载,再确认一下新的内核是否包含了overlayfs支持。注意,它对应的内核模块模块实际上叫overlay:

$ modinfo
filename:       /lib/modules/3.18.1-1-ARCH/kernel/fs/overlayfs/overlay.ko.gz
alias:          fs-overlay
license:        GPL
description:    Overlay filesystem
author:         Miklos Szeredi <miklos@szeredi.hu>
depends:
intree:         Y
vermagic:       3.18.1-1-ARCH SMP preempt mod_unload modversions
$ cat /proc/filesystems
nodev   sysfs
nodev   rootfs
nodev   ramfs
nodev   bdev
nodev   proc
nodev   cgroup
nodev   cpuset
nodev   tmpfs
nodev   devtmpfs
nodev   binfmt_misc
nodev   debugfs
nodev   securityfs
nodev   sockfs
nodev   pipefs
nodev   configfs
nodev   devpts
nodev   hugetlbfs
nodev   autofs
nodev   pstore
nodev   efivarfs
nodev   mqueue
        ext3
        ext2
        ext4
nodev   rpc_pipefs
nodev   nfs
nodev   nfs4
        xfs
        iso9660
        vfat
        fuseblk
nodev   fuse
nodev   fusectl

这说明新的内核包含了overlayfs支持,但默认没有将对应模块载入。没有关系,只要我们正确的为Docker配置了overlay驱动,Docker服务启动时内核应该就会自动载入overlay模块了。

因为overlayfs仍是实验特性,因此即便内核升级到了3.18版本,在Arch上Docker也仍然默认采用devicemapper驱动。必须指明参数迫使docker启用overlayfs。因为Arch Linux已经用systemd取代了SysV init脚本,所以我们应该去修改Docker的service文件。

$ su -
# vi /lib/systemd/system/docker.service

可以看到文件内容有以ExecStart开头的一行:

ExecStart=/usr/bin/docker -d -H fd://

加入指定存储驱动的参数-s并存盘退出,修改后应该是这个样子:

ExecStart=/usr/bin/docker -d -H fd:// -s overlay

修改了service文件以后,需要让systemd刷新一下再启动服务:

# systemctl daemon-reload
# systemctl start docker
# exit

检查一下添加的参数是否生效了:

$ docker info
Containers: 0
Images: 0
Storage Driver: overlay
Execution Driver: native-0.2
Kernel Version: 3.18.1-1-ARCH
Operating System: Arch Linux
CPUs: 4
Total Memory: 3.753 GiB
Name: ksh-zen
ID: C56B:VEMA:MS6I:ZUGG:J3MO:53U6:IU7B:4HO2:PRRB:O3O2:HZVM:EEZ4

可以看到"Storage Driver"后面是overlay,设定的参数起作用了。

看看/var/lib/docker文件系统下是什么情况:

# ls /var/lib/docker
containers  execdriver  graph  init  linkgraph.db  overlay  repositories-overlay  tmp  trust  volumes
# du -sh /var/lib/docker/*
0       /var/lib/docker/containers
0       /var/lib/docker/execdriver
0       /var/lib/docker/graph
7.3M    /var/lib/docker/init
8.0K    /var/lib/docker/linkgraph.db
0       /var/lib/docker/overlay
4.0K    /var/lib/docker/repositories-overlay
0       /var/lib/docker/tmp
0       /var/lib/docker/trust
0       /var/lib/docker/volumes

目录下面的子目录等自动创建,且大部分目录都是空的。

恢复备份

将之前备份的所有镜像全部重新导入:

$ docker load -i /media/Storage/dockers/centos.tar
$ docker load -i /media/Storage/dockers/debian.tar
......

导入完成之后还要确认一下镜像是可用的:

$ docker run -it centos:centos6 /bin/bash
[root@147c15762dfa /]#

最终效果

至此为Docker 1.4.0启用overlay驱动的操作算是全部完成,数据也全部安全迁移到了新的Docker环境下。看一看这么一番折腾是否解决了我的问题:

$ docker info
Containers: 0
Images: 43
Storage Driver: overlay
Execution Driver: native-0.2
Kernel Version: 3.18.1-1-ARCH
Operating System: Arch Linux
CPUs: 4
Total Memory: 3.753 GiB
Name: ksh-zen
ID: C56B:VEMA:MS6I:ZUGG:J3MO:53U6:IU7B:4HO2:PRRB:O3O2:HZVM:EEZ4
$ df -h
Filesystem                   Size  Used Avail Use% Mounted on
/dev/mapper/vgroot-lvarch    7.8G  4.7G  2.8G  63% /
dev                          1.9G     0  1.9G   0% /dev
run                          1.9G  628K  1.9G   1% /run
tmpfs                        1.9G     0  1.9G   0% /dev/shm
tmpfs                        1.9G     0  1.9G   0% /sys/fs/cgroup
tmpfs                        1.9G  8.0K  1.9G   1% /tmp
/dev/mapper/vgroot-lvvar     2.0G  432M  1.4G  24% /var
/dev/mapper/vgroot-lvboot    976M   47M  862M   6% /boot
/dev/mapper/vgroot-lvdocker   20G  1.6G   19G   8% /var/lib/docker
/dev/mapper/vgroot-lvhome     80G   76G  4.4G  95% /home
tmpfs                        385M  4.0K  385M   1% /run/user/1000
/dev/sdb1                    161G  137G   24G  86% /media/Storage

同样是43个镜像,空间占用由8.291GB变成了1.6GB,效果明显。

接下来我打算用一两篇文章对overlay的内部机制和它可能带来的好处做一个简单的分析,希望能讲清楚。


Comments

comments powered by Disqus