Docker Storage-Driver

Storage Driver查询

可以使用docker info命令查看你的Docker使用的storage driver,信息如下:

[root@84 tmp]# docker info
Containers: 0
 Running: 0
 Paused: 0
 Stopped: 0
Images: 6
Server Version: 18.03.0-ce
Storage Driver: overlay2 #使用的storage driver
 Backing Filesystem: xfs

Storage对比

可以看到的本机上使用的storage driveroverlay2。此外,还有一个Backing Filesystem它只你本机的文件系统,我的是extfsaufs是在xfs之上创建的。你能够使用的storage driver是与你主机上的Backing Filesystem有关的。

Storage driver 后端文件系统 不支持的后端文件系统
overlay ext4 xfs btrfs aufs overlay zfs eCryptfs
overlay2 ext4 xfs btrfs aufs overlay zfs eCryptfs
aufs ext4 xfs btrfs aufs eCryptfs
btrfs btrfs only N/A
devicemapper direct-lvm N/A
vfs debugging only N/A
zfs zfs only N/A

你可以通过在docker daemon命令中添加--storage-driver=<name>标识来指定要使用的storage driver,或者在/etc/default/docker文件中通过DOCKER_OPTS指定。
选择的storage driver对容器中的应用是有影响的。

Storage Driver 详解

AUFS

AUFS是Docker最先使用的storage driver,它技术很成熟,社区支持也很好,它的特性使得它成为storage driver的一个好选择,使用它作为storage driver,Docker会:

  • 容器启动速度很快
  • 存储空间利用很高效
  • 内存的利用很高效

尽管如此,仍有一些Linux发行版不支持AUFS,主要是它没有被并入Linux内核。

AUFS是一种联合文件系统,意思是它将同一个主机下的不同目录堆叠起来(类似于栈)成为一个整体,对外提供统一的视图。AUFS是用联合挂载来做到这一点。
AUFS使用单一挂载点将多个目录挂载到一起,组成一个栈,对外提供统一的视图,栈中的每个目录作为一个分支。栈中的每个目录包括联合挂载点都必须在同一个主机上。
在Docker中,AUFS实现了镜像的分层。AUFS中的分支对应镜像中的层。
此外,容器启动时创建的读写层也作为AUFS的一个分支挂载在联合挂载点上。

AUFS通过写时复制策略来实现镜像镜像的共享和最小化磁盘开销。AUFS工作在文件的层次上,也就是说AUFS对文件的操作需要将整个文件复制到读写层内,哪怕只是文件的一小部分被改变,也需要复制整个文件。这在一定成度上会影响容器的性能,尤其是当要复制的文件很大,文件在栈的下面几层或文件在目录中很深的位置时,对性能的影响会很显著。
例如:当要在一个包含很长字符串的文件中追加一个字符串时,如果这是对这个文件的第一次修改操作,意味着它当前不在最顶层的读写层。AUFS就会在下面额读写层中查找它,查找是自顶向下,逐层查找的。找到之后,就把整个文件拷贝到读写层,再对它进行修改。文件比较大时,复制操作就会很耗时间。当文件在最下面几层时,查找它的时间开销也比较大。
幸运的是,一个文件只需复制一次,此后对它的操作就在读写层进行了。

AUFS在性能方面的特性可以总结如下:

  • 在容器密度比较告的场景下,AUFS是非常好的选择,因为AUFS的容器间共享镜像层的特性使其磁盘利用率很高,容器的启动时间很短;
  • AUFS中容器之间的共享使对系统页缓存的利用率很高;
  • AUFS的写时复制策略会带来很高的性能开销,因为AUFS对文件的第一次更改需要将整个文件复制带读写层,当容器层数很多或文件所在目录很深时尤其明显;

最后,需要说明的是,数据卷(data volumes)可以带来很好的性能表现,这是因为它绕过storage driver直接将文件卸载宿主机上,不需要使用写时复制策略。正因如此,当需要大量的文件写操作时最好使用数据卷。

Device mapper 详解

Docker在Debian,Ubuntu系的系统中默认使用aufs,在RedHat系中使用device mapper。device mapper在Linux2.6内核中被并入内核,它很稳定,也有很好的社区支持。

device mapper将所有的镜像和容器存储在它自己的虚拟设备上,这些虚拟设备是一些支持写时复制策略的快照设备。device mapper工作在块层次上而不是文件层次上,这意味着它的写时复制策略不需要拷贝整个文件。
device mapper创建镜像的过程如下:

  • 使用device mapper的storge driver创建一个精简配置池;精简配置池由块设备或稀疏文件创建。
  • 接下来创建一个基础设备;
  • 每个镜像和镜像层都是基础设备的快照;这写快照支持写时复制策略,这意味着它们起始都是空的,当有数据写入时才耗费空间。

在device mapper作为storage driver的系统中,容器层container layer是它依赖的镜像的快照。与镜像一样,container layer也支持写时复制策略,它保存了所有对容器的更改。当有数据需要写入时,device mapper就为它们在资源池中分配空间;
下图展示了资源池,基础设备和两个镜像之间的关系

storage_driver1.jpg

device mapper中的读操作

下图展示了容器中的某个进程读取块号为0x44f的数据:

  • 某个进程发出读取文件的请求;由于容器只是镜像的精简快照(thin snapshot),它并没有这个文件。但它有指向这个文件在下面层中存储位置的指针。
  • device mapper由指针找到在镜像层号为a005e中的块号为0xf33的数据;
  • device mapper将这个位置的文件复制到容器的存储区内;
  • device mapper将数据返回给应用进程;
storage_driver2.jpg

device mapper中的写操作
在device mapper中,对容器的写操作由“需要时分配”策略完成。更新已有数据由“写时复制”策略完成,这些操作都在块的层次上完成,每个块的大小为64KB。
向容器写入56KB的新数据的步骤如下:

  • 进程向容器发出写56KB数据的请求;
  • device mapper的“需要时分配”策略分配一个64KB的块给容器快照(container snapshot);如果要写入的数据大于64KB,就分配多个大小为64KB的块。
  • 将数据写入新分配的块中;

device mapper在Docker中的性能表现

device mapper的性能主要受“需要时分配”策略和“写时复制”策略影响,下面分别介绍:

需要时分配(allocate-on-demand)
device mapperdriver通过allocate-on-demand策略为需要写入的数据分配数据块。也就是说,每当容器中的进程需要向容器写入数据时,device mapper就从资源池中分配一些数据块并将其映射到容器。
当容器频繁进行小数据的写操作时,这种机制非常影响影响性能。
一旦数据块被分配给了容器,对它进行的读写操作都直接对块进行操作了。

写时复制(copy-on-write)
与aufs一样,device mapper也支持写时复制策略。容器中第一次更新某个文件时,device mapper调用写时复制策略,将数据块从镜像快照中复制到容器快照中。
device mapper的写时复制策略以64KB作为粒度,意味着无论是对32KB的文件还是对1GB大小的文件的修改都仅复制64KB大小的文件。这相对于在文件层面进行的读操作具有很明显的性能优势。
但是,如果容器频繁对小于64KB的文件进行改写,device mapper的性能是低于aufs的。

存储空间使用效率
device mapper不是最有效使用存储空间的storage driver,启动n个相同的容器就复制了n份文件在内存中,这对内存的影响很大。所以device mapper并不适合容器密度高的场景。

overlayfs

OverlayFS与AUFS相似,也是一种联合文件系统(union filesystem),与AUFS相比,OverlayFS:

  • 设计更简单;
  • 被加入Linux3.18版本内核
  • 可能更快

overlayfs在Docker社区中获得了很高的人气,被认为比AUFS具有很多优势。但它还很年轻,在成产环境中使用要谨慎。

overlayfs中镜像的分层和共享

OverlayFS将一个Linux主机中的两个目录组合起来,一个在上,一个在下,对外提供统一的视图。这两个目录就是层layer,将两个层组合在一起的技术被成为联合挂载union mount。在OverlayFS中,上层的目录被称作upperdir,下层的,目录被称作lowerdir,对外提
供的统一视图被称作merged
下图展示了容器和镜像的层与OverlayFS的upperdirlowerdir以及merged之间的对应关系(图来自Docker官网Docker docs):

storage_driver3.jpg

由上图可以看出,在一个容器中,容器层container layer也就是读写层对应与OverlayFS的upperdir,容器使用的对象对应于OverlayFS的lowerdir,容器文件系统的挂载点对应merged。
注意到,镜像层和容器曾可以有相同的文件,这中情况下,upperdir中的文件覆盖lowerdir中的文件。

OverlayFS仅有两层,也就是说镜像中的每一层并不对应OverlayFS中的层,而是,镜像中的每一层对应/var/lib/docker/overlay中的一个文件夹,文件夹以该层的UUID命名。然后使用硬连接将下面层的文件引用到上层。这在一定程度上节省了磁盘空间。这样,OverlayFS中的lowerdir就对应镜像层的最上层,并且是只读的。在创建镜像时,Docker会新建一个文件夹作为OverlayFS的upperdir,它是可写的。

overlayfs中镜像和容器的结构

执行docker images -a查看ubuntu镜像都由哪些层组成:

$ docker images -a
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu              latest              1d073211c498        7 days ago          187.9 MB
<none>              <none>              5a4526e952f0        7 days ago          187.9 MB
<none>              <none>              99fcaefe76ef        7 days ago          187.9 MB
<none>              <none>              c63fb41c2213        7 days ago          187.7 MB

然后查看/var/lib/docker/overlay下的文件夹:

$ ls -l /var/lib/docker/overlay/
total 24
drwx------ 3 root root 4096 Oct 28 11:02 1d073211c498fd5022699b46a936b4e4bdacb04f637ad64d3475f558783f5c3e
drwx------ 3 root root 4096 Oct 28 11:02 5a4526e952f0aa24f3fcc1b6971f7744eb5465d572a48d47c492cb6bbf9cbcda
drwx------ 5 root root 4096 Oct 28 11:06 99fcaefe76ef1aa4077b90a413af57fd17d19dce4e50d7964a273aae67055235
drwx------ 3 root root 4096 Oct 28 11:01 c63fb41c2213f511f12f294dd729b9903a64d88f098c20d2350905ac1fdbcbba

可以看出,镜像中的每一层在/var/lib/docker/overlay文件夹下都有一个文件夹和它对应,文件夹以镜像层的UUID命名。文件夹存储了本层独有的文件和指向它下面各层文件的硬连接。

使用docker ps命令查看当前正在运行的容器的ID:

$ docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
73de7176c223        ubuntu              "bash"              2 days ago          Up 2 days                               stupefied_nobel

这个容器的数据存储在/var/lib/docker/overlay/73de7176c223...文件夹下,文件夹以容器的ID命名。执行ls -a命令查看具体文件:

$ ls -l /var/lib/docker/overlay/73de7176c223a6c82fd46c48c5f152f2c8a7e49ecb795a7197c3bb795c4d879e
total 16
-rw-r--r-- 1 root root   64 Oct 28 11:06 lower-id
drwxr-xr-x 1 root root 4096 Oct 28 11:06 merged
drwxr-xr-x 4 root root 4096 Oct 28 11:06 upper
drwx------ 3 root root 4096 Oct 28 11:06 work

这就是OverlayFS的核心内容了。lower-id文件保存了当前容器依赖镜像的最上层的UUID,并将其作为lowerdir;upper文件夹就是容器的读写层read-write layer,对容器的所有修改都保存在这个文件夹里;merged文件夹就是容器文件系统的挂载点,容器通过它提供统一的视角。对容器的任何修改都会立即在这个文件夹里得到反应;work文件夹需要OverlayFS来发挥作用,它用来支持像copy-up这样的操作。

overlayfs中容器的读写操作

读文件:

  • 要读的文件不在container layer中:那就从lowerdir中读,会耗费一点性能;
  • 要读的文件之存在于container layer中:直接从upperdir中读;
  • 要读的文件在container layer和image layer中都存在:从upperdir中读文件;

修改文件

  • 第一次修改一个文件的内容:第一次修改时,文件不在container layer(upperdir)中,overlay driver调用copy-up操作将文件从lowerdir读到upperdir中,然后对文件的副本做出修改。
    需要说明的是,overlay的copy-up操作工作在文件层面,不是块层面,这意味着对文件的修改需要将整个文件拷贝到upperdir中。索性下面两个事实使这一操作的开销很小:
  • copy-up操作仅发生在文件第一次被修改时,此后对文件的读写都直接在upperdir中进行;
  • overlayfs中仅有两层,这使得文件的查找效率很高(相对于aufs)。
  • 删除文件和目录:
  • 删除文件:文件被删除时,和aufs一样,相应的whiteout文件被创建在upperdir。并不删除容器层(lowerdir)中的文件,whiteout文件屏蔽了它的存在。
  • 删除文件夹:删除一个文件夹时,一个“遮挡目录”(opaque dir)被创建在upperdir中,它的作用与whitout文件一样,屏蔽了lowerdir中文件夹的存在。

在Docker中使用overlayfs

OverlayFS在Linux3.18版本中被并入内核,所以要使用overlayfs,请确保你的系统的内核版本大于等于3.18。overlayfs可以工作在各种Linux文件系统上,但目前比较推荐extfs。

在进行下列操作之前,如果你本机上有需要保存的镜像,使用docker push将它们保存到Docker Hub或其他的镜像库当中。
下面是在Docker中使用overlayfs的步骤:

  • 如果docker daemon正在运行,停止它;
  • 检查你的内核版本和overlay模块的按装情况:
$ uname -r 
3.19.0-21-generic
$ lsmod | grep overlay
overlay

使用overlaystorage driver启动docker daemon:

$ docker daemon --storage-driver=overlay & 

此外,你可以在/etc/default/docker文件中通过配置DOCKER_OPTS使overlay作为Docker的默认storage driver。

overlayfs在Docker中的性能表现

总体上,overlay要比aufs和device mapper快一点,在某些场景下甚至比btrfs快。下面是对overlay性能影响较大的几个方面:

  • 页缓存(page caching):overlayfs支持页缓存的共享,这意味着多个使用同一文件的容器可以共享同一页缓存,这使得overlayfs具有很高的内存使用效率;
  • copy-up操作:overlay的拷贝操作工作在文件层面上,也就是对文件的第一次修改需要复制整个文件,这回带来一些性能开销,在修改大文件时尤其明显。
    但overlay的拷贝操作比aufs还是快一点,因为aufs有很多层,而overlay只有两层,所以overlay在文件的搜索方面相对于aufs具有优势。
  • i节点限制:使用overlay作为storage driver会消耗大量的i节点,随着镜像和容器数量的增长这种消耗尤其显著,这在一定程度上限制了overlay的使用。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • # docker --helpUsage: docker [OPTIONS] COMMAND [arg...] ...
    dujh302阅读 370评论 0 0
  • 原文发布在:http://cizixs.com/2016/04/06/docker-images,转载请注明出处。...
    cizixs阅读 2,699评论 1 16
  • 写这篇文章主要是为了今后毕业论文素材上的整理,同时对docker进行巩固温习。大纲: docker简介docker...
    胡图仙人阅读 7,393评论 2 96
  • feisky云计算、虚拟化与Linux技术笔记posts - 1014, comments - 298, trac...
    不排版阅读 3,813评论 0 5
  • 文/SweetAnna 你依然是我的软肋
    SweetAnna阅读 143评论 0 0