手机版

Docker用户指南(6) – Btrfs存储驱动实践

时间:2020-05-07 来源:互联网 编辑:宝哥软件园 浏览:

Btrfs是下一代支持许多高级存储技术以使其更适合Docker的写时拷贝文件系统。Btrfs包含在Linux内核主线中以及现在稳定的硬盘格式(on-disk-format)。不过许多功能仍然在开发中,用户应该意识到此驱动目前正在快速发展中。
Docker的btrfs存储驱动利用Btrfs的许多功能来管理镜像和容器。这些功能是精简置备(thin provisioning),写时拷贝和快照。
本文把Docker的Btrfs存储驱动简称为btrfs,将整个Btrfs文件系统称为Btrfs。

Btrfs的未来

Btrfs一直被誉为是一个Linux的未来文件系统。在Linux内核主线的完全支持下,一个稳定的硬盘格式(on-disk-format),以及活跃的专注稳定性开发,离变成现实越来越近了。
就Linux平台上的Docker而言,许多人将btrfs存储驱动视为潜在的长期替代devicemapper存储驱动。不过,到目前为止,devicemapper存储驱动仍然比btrfs更安全,更稳定和更适合用于生产环境。如果你对btrfs非常熟悉且已经有Btrfs的使用经验,这时你才应该考虑把btrfs部署到生产环境中。

镜像分层与Btrfs共享

Docker利用Btrfs subvolumes和快照来管理镜像和容器数据层的硬盘组件(on-disk components)。Btrfs subvolumes看起来像一个正常的Unix文件系统。因此,他们可以有自己的内部目录结构,挂钩到更广泛的Unix文件系统。
subvolumes更新文件时涉及写时拷贝操作,写入新文件时涉及从一个底层存储池来按需分配空间的操作。它们既能嵌套也能做快照。下图显示了4个subvolumes。“subvolume 2″和”subvloume 3″是嵌套的,而“subvolume 4”显示它自己的内部目录树。
Docker用户指南(6) – Btrfs存储驱动实践
快照是在一个时间点对整一个subvolume做的一个副本。它们直接存在于从其创建的subvolume下面。你可以像下图显示的那样创建快照的快照。

Btfs从一个底层存储池给subvolumes和快照(snapshots)按需分配空间。分配单元称为块(chunk),并且块通常大小为〜1GB。
快照看起来和操作跟常规的subvolumes类似。创建快照所需的技术由于Btrfs本地的写时拷贝设计而构建进Btrfs文件系统中。这意味着Btrfs快照空间利用率高且很少或没有性能开销。下图显示一个subvolume与它的快照共享同样的数据。
 虚拟化技术
Docker的btrfs存储驱动把每个镜像和容器数据层存储到Btrfs subvolume或快照。镜像的基础数据层(最底层)作为一个subvolume存储,而镜像子数据层和容器作为快照存储。如下图所示。
docker
使用btrfs驱动的Docker主机创建镜像和容器的过程如下:

1.镜像的基础数据层存储在/var/lib/docker/btrfs/subvolumes的Btrfs subvloume中。 2.后续的镜像数据层存储为subvolume或快照的父级数据层的一个Btrfs快照中。

下图显示一个3个数据层的镜像。base layer是一个subvolume。layer 1是base layer的subvolume的一个快照。layer 2是layer1快照的快照。
docker
从docker 1.10开始,镜像数据层ID不再与在/var/lib/docker的目录名称相关。

镜像和容器在硬盘的结构

镜像数据层和容器在docker主机的文件系统的/var/lib/docker/btrfs/subvolumes/目录可见。不过,如之前所说的,目录名不再与镜像数据层ID相关。那就是说,容器的目录即使容器已经停止都存在。这是因为btrfs存储驱动在/var/lib/docker/subvolumes/下挂载一个默认的,顶层的subvolume。所有的其它subvolumes和快照为作Btrfs文件系统对象存在,而不是作为单独挂载存在。
因为Btrfs工作在文件系统级别上而不是块级别,所以可以使用常规的Unix命令来浏览器每个镜像和容器数据层。下面的示例显示使用ls -l命令浏览一个镜像数据层:

$ ls -l /var/lib/docker/btrfs/subvolumes/0a17decee4139b0de68478f149cc16346f5e711c5ae3bb969895f22dd6723751/
 
total 0
drwxr-xr-x 1 root root 1372 Oct  9 08:39 bin
drwxr-xr-x 1 root root    0 Apr 10  2014 boot
drwxr-xr-x 1 root root  882 Oct  9 08:38 dev
drwxr-xr-x 1 root root 2040 Oct 12 17:27 etc
drwxr-xr-x 1 root root    0 Apr 10  2014 home
...output truncated...

使用Btrfs进行容器读和写

一个容器是一个镜像的空间高效利用的快照。快照的元数据指向存储池的实际数据块。这与subvolume相同。因此,对快照执行的读取与对subvolume执行的读取本质相同。所以Btrfs驱动不会产生任何性能开销。
写入一个新文件到容器涉及到一个按需分配(allocate-on-demand)操作来为容器快照分配一个新的数据块。然后文件写入到这个新空间。按需分配操作对于使用Btrfs的所有写入都是原生的,写入新数据到subvolume一样涉及到到此操作。因此,将新文件写入到容器快照的速度与本地Btrfs写入速度一样。
在容器中更新一个存在的文件将产生一个写时拷贝操作(技术上称为redirect-on-write)。驱动保留原始数据并为快照分配新空间。更新的数据写入到这个新空间。然后驱动更新快照文件系统元数据指向新的数据。原始数据仍然保留在subvolumes中。
使用Btfs写入和更新大量小文件可能会导致性能降低。

配置Docker使用Btrfs

btrfs存储驱动只在Docker主机的/var/lib/docker挂载为Btrfs文件系统上操作。下面介绍如何在Ubuntu 14.04 LTS上配置Btrfs。

先决条件

如果你已经在Docker主机上使用Docker daemon,并且你想保持现有的镜像,在进行下面的配置前先把镜像push到Docker Hub或者其它地方。
停止Docker daemon,然后确保你在/dev/xvdb有一个闲置的块设备。设备标识符在你的环境中可能不同,你应该在整个过程中替换你自己的值。
下面的步骤也假设你的内核已经正确加载了Btrfs模块。要验证它,使用如下命令:

$ cat /proc/filesystems | grep btrfs
 
        btrfs

在Ubuntu 14.04 LTS配置Btrfs

假设你系统已经满足了前面提到的条件,执行如下:
1.安装btrfs-tools包。

$ sudo apt-get install btrfs-tools
 
 Reading package lists... Done
 Building dependency tree
 <output truncated>

2.创建Btrfs存储池。
Btrfs存储池使用mkfs.btrfs命令创建。传递多个设备给mkfs.btrfs命令将在所有这些设备之间创建一个存储池。
这里我们使用在/dev/xvdb的单个设备创建一个存储池。

$ sudo mkfs.btrfs -f /dev/xvdb
 
 WARNING! - Btrfs v3.12 IS EXPERIMENTAL
 WARNING! - see http://btrfs.wiki.kernel.org before using
 
 Turning ON incompat feature 'extref': increased hardlink limit per file to 65536
 fs created label (null) on /dev/xvdb
     nodesize 16384 leafsize 16384 sectorsize 4096 size 4.00GiB
 Btrfs v3.12

3.如果Docker主机本地存储区域不存在,先创建。

$ sudo mkdir /var/lib/docker

4.配置系统重启时自动挂载Btrfs文件系统。
a.获取Btrfs文件系统的UUID。

$ sudo blkid /dev/xvdb
 
 /dev/xvdb: UUID="a0ed851e-158b-4120-8416-c9b072c8cf47" UUID_SUB="c3927a64-4454-4eef-95c2-a7d44ac0cf27" TYPE="btrfs"

b.在/etc/fstab添加一行来让系统每次启动时自动挂载。

/dev/xvdb /var/lib/docker btrfs defaults 0 0
 UUID="a0ed851e-158b-4120-8416-c9b072c8cf47" /var/lib/docker btrfs defaults 0 0

5.挂载新的文件系统并验证

$ sudo mount -a
 
 $ mount
 
 /dev/xvda1 on / type ext4 (rw,discard)
 <output truncated>
 /dev/xvdb on /var/lib/docker type btrfs (rw)

上面输出的最后一行显示/dev/xvdb作为Btrfs挂载在/var/lib/docker。
现在你已经有一个挂载在/var/lib/docker的Btrfs文件系统,docker daemon应该能自动加载btrfs存储驱动了。
1.启动docker daemoon。

$ sudo service docker start
 docker start/running, process 2315

启动之后Docker会自动加载Btrfs,不过你可以指定–storage-driver=btrfs或添加DOCKER_OPTS行来强制Docker使用btrfs。
2.使用docker info命令验证

$ sudo docker info
 
 Containers: 0
 Images: 0
 Storage Driver: btrfs
 [...]

现在docker已经配置使用btrfs存储驱动了。

Btrfs及Docker性能

页缓存(page caching)。Btrfs不支持页缓存共享。意味着n个容器访问同一个文件需要n个副本缓存。因此,Btrfs可能不是PaaS和类似使用场景的最好选择。 小文件写。容器执行大量的小文件写操作(包括Docker主机启动和停止大量容器)会导致Btrfs块利用率低的问题。这可能最终导致docker主机空间很快不足的情况,致命影响docker运行。这是目前使用当前版本的Btrfs的主要缺点。如果你使用btrfs存储驱动,需要使用btrfs filesys来密切监控空间使用情况。不要使用常规的Unix命令如df来查看空间使用情况,因为有可能会显示不正确;推荐始终使用Btrfs原生的命令。 顺序写。Btrfs通过日志技术(journaling technique)将数据写入硬盘。其性能可以提升一半。 碎片(Fragmentation)。碎片是写时拷贝文件系统(如Btrfs)的自然副产品。 许多小的随机写入可以导致这个问题。 它表现为使用SSD硬盘的Docker主机上的CPU峰值和使用机械硬盘的Docker主机上的抖动。 这两者都导致差的性能。
最新版本的Btrfs允许你将autodefrag指定为mount选项。 此模式尝试检测随机写入和碎片整理。 在Docker主机上启用此选项之前,你应该先自己测试下。 一些测试显示此选项对执行大量小型写入的Docker主机(包括启动和停止许多容器的系统)具有负面性能影响。 固态设备(SSD)。 Btrfs具有SSD介质的本机优化。 要启用这些选项,请使用-o ssd mount选项进行挂载。 这些优化包括通过避免诸如在SSD介质上没有用的查找优化等增强的SSD写性能。
Btfs还支持原生的TRIM / Discard。 但是,使用-o discard mount选项进行挂载可能会导致性能问题。 因此,建议你在使用此选项之前先测试下。 使用数据卷(data volumes)。 数据卷提供最佳和最可预测的性能。这是因为他们绕过存储驱动,并且不承担任何通过精简置备和写时拷贝引入的潜在开销。

版权声明:Docker用户指南(6) – Btrfs存储驱动实践是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。

相关文章推荐