要真正理解我们要做的事情,首先来了解DeviceMapper插件的工作原理。
它是基于DeviceMapper的“精简目标”的特性。它实际上是目标块设备的快照,之所以被称为“精简”是因为它允许精简配置。精简配置意味着你有一个(希望很大)可用存储块的池,接着你可以从那个池中创建任意大小的块设备(虚拟磁盘,如有需要);在你实际读写后,这些存储块将会被标记为已使用(或者从池中拿走)。
这意味着你是可以超额使用这个池,比如在一个100GB的池里面创建几千个10GB的卷,甚至可能是一个100TB的卷在一个1GB的池里面。只要你的实际读写的块的容量不大于池的大小,你怎么做都OK。
从本质上来看,“精简目标”实际上使用了两个存储设备:一个(大)的是存储块池自己,还有一个小的存储了一些元数据。这些元数据中包括了卷、快照、以及每个卷的块或者快照同存储池中块的映射信息。
在了解如何调整容器的大小之前,我们来试试看如何给池增加更多空间。
警告:下面的操作会删除你所有的容器和镜像,确保你已经把之前的数据做了备份!
记住上面说过的,当数据和元类信息文件不存在的时候Docker会创建它们,所以解决方案非常简单:在启动它们之前,在Docker里创建这些文件!
停止Docker守护进程,因为我们将要重新设置我们的存储插件,如果我们在运行的时候移除文件,那么糟糕的事情就将发生。
警告:下面的操作也会删除你所有的容器和镜像。确保把你重要的镜像保存在registry中,保存你容器里面的重要数据。
要获得一个更快速的池,最简单的办法就是使用一个真实的设备而不是一个基于文件的循环设备。过程几乎一样。假设你有一个完全空的硬盘,/dev/sdb,你想把它完全用于容器的存储,你可以这样做:
如果你希望合并多块相似的磁盘,可以使用RADID10软件,这个会通过链接到/dev/md而实现。另外一个非常好的选择是把你的磁盘(或者RAID磁盘阵列)放到LVM的物理卷中,并且创建两个逻辑卷:一个是数据,一个是元数据。对于元数据池的最佳的大小我没有什么特别的建议,不过占数据池的1%看起来不错。
就像前面一样,停止Docker,移除它的数据目录,然后创建一个指向/dev/mapper设备的符号链接,然后重启Docker。
如
ln-s/dev/mapper/vg_dockerdev-LogVol01/var/lib/docker/devicemapper/devicemapper/data之后重启docker即可。
默认来说,如果你使用DeviceMapper的存储插件,所有的镜像和容器是从一个初始10G的文件系统中创建的。让我们来看看如何从一个更大的文件系统中创建一个容器。
首先,我们用Ubuntu的镜像来创建我们的容器。我们不需要在这个容器里运行任何东西,只需要这个文件(或者关联的文件系统)存在。为了演示,我们会在这个容器里运行df,来看一下根文件系统的大小。
$dockerrun-dubuntudf-h/4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603由于需要修改DeviceMapper管理中的一些卷的信息,我们现在用root的身份来运行一些命令。所有以#开头的命令都必须以root身份来执行。只要能访问Docker的Socket服务,你也可以用普通用户的身份来执行其他的命令(以$开头)。
让我们看一下/dev/mapper,那里应该有一个对应容器文件系统的符号链接,以docker-X:Y-Z-开头:
ls-l/dev/mapper/docker-*-4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603lrwxrwxrwx1rootroot7Jan3121:04/dev/mapper/docker-0:37-1471009-4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603->../dm-8注意记住那个全名,我们未来会用到。
首先让我们来看一下当前卷的信息表:
dmsetuptabledocker-0:37-1471009-4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603020971520thin254:07第二个数字是设备的大小,表示有多少个512-bytes的扇区.这个值略高于10GB的大小。
我们来计算一下一个42GB的卷需要多少扇区,
$echo$((42*1024*1024*1024/512))88080384精简快照目标的一个神奇的特点是它不会限制卷的大小。当你创建它的时候,一个精简的卷使用0个块,当你开始往块里面写入的时候,它们会从共用的块池中进行分配。你可以写0个块,或者是10亿个块,这个和精简快照目标没关系。文件系统的大小只和DeviceMapper表有关系。
觉得困惑?不要担心。我们只是需要装载一个新的表,这个完全和之前的是一样的,但是有更多的扇区。仅此而已。
旧表是020971520thin254:07。我们会改变第二个数字,要非常小心保持其他的值不变。你的卷可能不是7,所以要使用正确的值!
这样操作:
#echo088080384thin254:07|dmsetuploaddocker-0:37-1471009-4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603现在如果我们再次检查表的信息,步骤和前面一样。首先使用下面的命令激活新表:
#dmsetupresumedocker-0:37-1471009-4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603执行完命令后,再次检查一下表的信息,发现它会使用新的扇区数量。
我们已经调整了块设备的大小,但是我们仍然需要调整文件系统的大小,我们使用resize2fs来操作:
#resize2fs/dev/mapper/docker-0:37-1471009-4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603resize2fs1.42.5(29-Jul-2012)Filesystemat/dev/mapper/docker-0:37-1471009-4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603ismountedon/var/lib/docker/devicemapper/mnt/4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603;on-lineresizingrequiredold_desc_blocks=1,new_desc_blocks=3Thefilesystemon/dev/mapper/docker-0:37-1471009-4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603isnow11010048blockslong作为一个可选步骤,我们会重启容器,检查一下我们的确有了正确大小的空闲空间:
$dockerstart4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603$dockerlogs4ab0bdde0a0dd663d35993e401055ee0a66c63892ba960680b3386938bda3603df:Warning:cannotreadtableofmountedfilesystems:NosuchfileordirectoryFilesystemSizeUsedAvailUse%Mountedon-9.8G164M9.1G2%/df:Warning:cannotreadtableofmountedfilesystems:NosuchfileordirectoryFilesystemSizeUsedAvailUse%Mountedon-42G172M40G1%/想把整个过程自动化起来?当然没问题。
CID=$(dockerrun-dubuntudf-h/)DEV=$(basename$(echo/dev/mapper/docker-*-$CID))dmsetuptable$DEV|sed"s/0[0-9]*thin/0$((42*1024*1024*1024/512))thin/"|dmsetupload$DEVdmsetupresume$DEVresize2fs/dev/mapper/$DEVdockerstart$CIDdockerlogs$CID扩容镜像不幸的是,当前版本的Docker不能让我们很方便地扩容镜像。你可以把镜像对应的块设备进行扩容,然后从它来创建一个容器,但是新的容器不会有正确的大小。
同样,如果你提交了一个很大的容器,最后生成的镜像也不会很大(这是由Docker为镜像准备文件系统的方法造成的)。
这意味着如果一个容器真的超过了10GB,在不使用一些其他的小技巧的情况下,你没法正确的把它提交为一个镜像。
Docker将来肯定会提供一些更好的方法来扩容容器,所需的代码变动是很小的。管理一个精简的池和对应的元信息比较复杂(因为这个需要很多不同的操作流程,以及一个潜在的数据迁移。鉴于移除了所有的东西来构件新的池,也就没有在本文提及),但是我们今天提到的一些解决方案相信已经对你有所帮助。