自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