ZFS是支持许多高级存储技术(如卷管理,快照,检验和,压缩,去重,复制等)的下一代文件系统。由Microsystems(现在是Oracle Corporation)创建,以CDDL许多可证开源。由于CDDL和GPL的许可证不兼容,ZFS无法作为Linux内核主线的一部分提供。不过,Linux的ZFS(ZoL)提供了在内核树之外的模块并且可以单独安装用户空间工具。
Linux的ZFS(ZoL)目前已经是稳定成熟了。不过,除非你在Linux上拥有丰富的ZFS使用经验,否则不建议目前在生产环境使用zfs Docker存储驱动。
镜像分层和ZFS共享
Docker zfs存储驱动大量使用三个ZFS数据集:
ZFS文件系统是精简置备的(thinly provisioned)并通过按需分配操作从一个ZFS池(zpool)分配空间。快照和克隆是节省空间的某个时间点的ZFS文件系统副本。快照是只读的。克隆(clones)是可读写的。克隆只能从快照创建。它们简单的关系如下图.
上图中的实线部分是创建一个克隆的过程。步骤1创建文件系统的一个快照,步骤2是从快照创建克隆。虚线表示克隆和文件系统之间的关系,通过快照,所有三个ZFS数据集从相同的底层zpool中申请空间。
在使用zfs存储驱动的Docker主机上,一个镜像的base层是一个ZFS文件系统。每一个子层是基于该层下面层的快照的克隆。一个容器是基于从其创建的镜像顶层的快照的ZFS克隆。所有的ZFS数据集从同一个zpool申请空间。下图显示zpool,三个数据集,一个基于两层镜像的容器的关系。
下面的过程解释了镜像是如何分层的和如何创建容器。该过程基于上图。
1.镜像的base数据层作为ZFS文件系统存在于Docker主机上。
此文件系统消耗用于在/var/lib/docker上创建Docker主机的本地存储区的zpool空间。
2.其它的镜像数据层是在其下方的镜像层的数据集的克隆。
在这个图中,”Layer 1″是通过创建base层的一个ZFS快照,然后从这个快照创建一个克隆增加。这个克隆是可写的并消耗从zpool按需分配的空间。快照是只读的,将base层保持为一个不可变的对象。
3.当一个容器创建后,一个可读写的数据层增加在镜像的上面。在上图中,这个容器的可读写数据层是通过创建镜像顶层(Layer1)的快照,然后从这个快照创建一个克隆创建的。
所有对容器的更改,将通过按需分配操作从zpool中分配空间。默认下,ZFS以128K大小的数据块分配空间。
从只读快照创建子层和容器的此过程允许保持镜像为一个不可变对象。
使用ZFS读写容器
使用zfs存储驱动进行容器的读取是非常简单的。一个新创建的容器基于一个ZFS克隆。此克隆最初与从其创建的数据集共享其所有数据。这意味着使用zfs存储驱动的读操作是非常快的 – 即使要读取的数据还没有复制到容器中。下面显示这个数据块的分享。
写入新数据到容器是通过按需分配操作完成。每次需要写数据到容器的新区域,一个新的数据块从zpool分配。这意味着写入新数据到容器的新区域将消耗额外的空间。从底层zpool分配新空间给容器(ZFS克隆)。
更新容器存在的数据通过分配新数据块给容器克隆和存储更改的数据到这些新数据块完成。原始的数据块没有更改,允许底层镜像数据集保持不变。这与写入正常的ZFS文件系统相同,并且都执行了写时拷贝操作。
配置Docker使用ZFS存储驱动
zfs存储驱动只支持/var/lib/docker挂载为一个ZFS文件系统的Docker主机。本节介绍如何在Ubuntu 14.04系统上安装和配置原生Linux ZFS(ZoL)。
先决条件
如果你已经在你docker主机上使用docker daemon并且有你想保留的镜像,在执行下面的步骤之前先push它们到docker hub或你的私有docker registry。
停止docker daemon。然后确保在/dev/xvdb有一个空闲的块设备。块设备的标识符可能与你的不同,请替换成你自己的。
在Ubuntu 16.04 LTS安装ZFS
1.先停止docker deamon。
2.安装zfs软件包。
- $ sudo apt-get install -y zfs
- Reading package lists… Done
- Building dependency tree
- <output truncated>
3.验证zfs模块是否已经正确加载。
- $ lsmod | grep zfs
- zfs 2813952 3
- zunicode 331776 1 zfs
- zcommon 57344 1 zfs
- znvpair 90112 2 zfs,zcommon
- spl 102400 3 zfs,zcommon,znvpair
- zavl 16384 1 zfs
在Ubuntu 14.04安装ZFS
1.先停止docker daemon。
2.安装add-apt-repository命令依赖的software-properties-common软件。
- $ sudo apt-get install -y software-properties-common
- Reading package lists… Done
- Building dependency tree
- <output truncated>
3.增加zfs-native软件包ppa源。
- $ sudo add-apt-repository ppa:zfs-native/stable
- The native ZFS filesystem for Linux. Install the ubuntu-zfs package.
- <output truncated>
- gpg: key F6B0FC61: public key "Launchpad PPA for Native ZFS for Linux" imported
- gpg: Total number processed: 1
- gpg: imported: 1 (RSA: 1)
- OK
4.获取最新的软件包列表。
- $ sudo apt-get update
- Ign http://us-west-2.ec2.archive.ubuntu.com trusty InRelease
- Get:1 http://us-west-2.ec2.archive.ubuntu.com trusty-updates InRelease [64.4 kB]
- <output truncated>
- Fetched 10.3 MB in 4s (2,370 kB/s)
- Reading package lists… Done
5.安装ubuntu-zfs软件包
- $ sudo apt-get install -y ubuntu-zfs
- Reading package lists… Done
- Building dependency tree
- <output truncated>
6.加载zfs模块。
- $ sudo modprobe zfs
7.验证模块是否已正确加载。
- $ lsmod | grep zfs
- zfs 2768247 0
- zunicode 331170 1 zfs
- zcommon 55411 1 zfs
- znvpair 89086 2 zfs,zcommon
- spl 96378 3 zfs,zcommon,znvpair
- zavl 15236 1 zfs
配置Docker ZFS
一旦ZFS安装并加载完成,你可以继续配置docker ZFS。
1.创建一个新的zpool。
- $ sudo zpool create -f zpool-docker /dev/xvdb
该命令创建名为”zpool-docker”的zpool。名称可以是任意的。
2.检查zpool是否存在。
- $ sudo zfs list
- NAME USED AVAIL REFER MOUNTPOINT
- zpool-docker 55K 3.84G 19K /zpool-docker
3.创建并挂载一个新的ZFS文件系统到/var/lib/docker。
- $ sudo zfs create -o mountpoint=/var/lib/docker zpool-docker/docker
4.检查是否已经挂载成功。
- $ sudo zfs list -t all
- NAME USED AVAIL REFER MOUNTPOINT
- zpool-docker 93.5K 3.84G 19K /zpool-docker
- zpool-docker/docker 19K 3.84G 19K /var/lib/docker
现在你已经把一个ZFS文件系统挂载到/var/lib/docker,docker daemon应该可以自动加载zfs存储驱动了。
5.启动docker daemon。
- $ sudo service docker start
- docker start/running, process 2315
6.验证docker daemon是否已经在使用zfs存储驱动了。
- $ sudo docker info
- Containers: 0
- Images: 0
- Storage Driver: zfs
- Zpool: zpool-docker
- Zpool Health: ONLINE
- Parent Dataset: zpool-docker/docker
- Space Used By Parent: 27648
- Space Available: 4128139776
- Parent Quota: no
- Compression: off
- Execution Driver: native-0.2
- […]
上面命令的输出显示docker daemon的存储驱动为zfs,父数据集为之前创建的zpool-docker/docker文件系统。
ZFS与Docker性能
有几个影响使用zfs存储驱动的docker性能的因素。