Docker storage driver overlayFS

overlayFS是一个类似AUFS的联合挂载文件系统,与AUFS的实现类似但是比AUFS的存储速度更快。docker基于OverlayFS提供两种存储驱动: overlay和更加新的稳定的overlay2.推荐使用overlay2,因为overlay2更加高效。

  • 使用条件
  1. 使用overlay2,Linux kernel版本必须高于4.0,在RHEL或者CentOS上Linux kernel版本高3.10.0-514
  2. Overlay2 在dockerCE中提供支持,dockerEE支持版本在 17.06.02-ee5及以上
  3. Overlay和overlay2存储驱动需要使用xfs后端文件系统,并且要设置 d_type=true
  • 如何配置docker 使用 overlay2 存储驱动

1. 停止Docker 服务

 systemctl stop docker

2. 备份docker存储的文件

cp -au /var/lib/docker /var/lib/docker.bk

3. 如果要使用与/var/lib/ 所使用的备份文件系统不同的文件系统,需要格式化该文件系统并且将其挂载到/var/lib/docker目录上,为使其可以永久化,要将其mount到/etc/fstab上。

4.编辑/etc/docker/daemon.json文件,如果此文件不存在,则创建daemon.json 文件并且添加如下配置项

{
    “storage-driver”:”overlay2”
}

一定确保daemon.json 文件的格式正确性,否则docker将无法启动。

5. 启动docker服务。

systemctl start docker

6. 验证docker使用overlay2存储驱动,查看Storage Driver 和Backing filesystem配置项

docker info

Overlay2机制大揭秘

overlayFS在单个Linux主机上有两个layer,呈现给用户的是一个单独的目录,这些目录就是layers,统一的过程就是联合挂载。OverlayFS将底层目录称为lowerdir,上层目录称为upperdir,统一挂载目录称为merged。
overlay2驱动本身支持128多个lower overlay FS 层,这为docker build docker commit 涉及docker层的操作提供了更好的支持和性能,并在支持文件系统上消耗更少的inode。镜像和容器在磁盘上的存储
我们通过执行docker pull ubuntu来具体看一下镜像和容器在磁盘上是如何储的,通过pull 的过程我们可以看到,此镜像具有四层,可以在/var/lib/docker/overlay2目录下查看到对应的四层镜像目录但是他们的ID不是对应的,

# docker pull ubuntu

l 目录是一个符号链接,它包含了短的层标识符,这些标识符可用于避免在mount命令的参数上达到页面大小限制。

# ls -l /var/lib/docker/overlay2/l/

看一下各层都包含哪些内容

# tree -L 2 /var/lib/docker/overlay2/

最底一层06bdc78880只包含link 和diff,link中包含短标识符的名称,diff中包含层的具体的内容。

# cat  /var/lib/docker/overlay2/06bdc78880b9d180a7b9aa8bab090156d0f3151a1618732b79a6624367d964df/link
# ls /var/lib/docker/overlay2/06bdc78880b9d180a7b9aa8bab090156d0f3151a1618732b79a6624367d964df/diff/

从倒数第二层开始以及以上层都包含lower目录表示这一层的父级,最底层没有父级,还包含一个diff目录里面存储了本层的具体内容,还会有一个merged目录,包含父级和diff层的内容,还有一个work目录,用于copy-on-write。

# cat /var/lib/docker/overlay2/de5b621208f20b61ddf008ef5e495279a3740cea651e9647f5b01edbc9cda39d/lower

从lower层的内容我们可以推导出镜像的层级关系

第四层 b5a17b9416195dd43f3416f6c521981a9bb098f992c4d20c62be8789bd7b2c57

当我们基于ubuntu镜像创建一个容器时,再来看/var/lib/docker/overlay2/目录,可以看到新创建了两个目录,这两个目录分别是容器层和容器的初始层

# ls -l /var/lib/docker/overlay2/

其中b7a6d7a5a21869b197f62cd087610185174ec5feae900c53b0f88c3c213d166b 是容器的读写层,b7a6d7a5a21869b197f62cd087610185174ec5feae900c53b0f88c3c213d166b-init是初始化容器的层。
b7a6d7a5a21869b197f62cd087610185174ec5feae900c53b0f88c3c213d166b中创建了一个新的merged目录,此目录包含整个镜像的所有的层的内容,init目录下diff目录中包含/dev /etc 可见这是单独的镜像层。

|-- b7a6d7a5a21869b197f62cd087610185174ec5feae900c53b0f88c3c213d166b

再来查看系统中的mount 情况

# mount | grep overlay

可以看出,当我们基于ubuntu镜像创建容器时,storage driver 将lowerdir(镜像层)和upperdir(容器层diff目录)workerdir(容器层work目录)mount到容器层的merged目录下,由merged目录提供统一的容器入口层。


Image

overlay/overlay2如何读写文件

有三种读文件的场景
1. 这个文件在容器层中不存在:即要读的文件在upperdir中不存在,则将会从lowerdir中读取对应的文件。这机会不会产生性能开销。
2. 要读的文件在容器层中存在:即在upperdir中存在,在lowerdir中不存在,直接读取upperdir中要读的文件。
3. 在容器层和镜像层中都存在:读取容器层中的文件,镜像层的文件会被覆盖。

修改文件场景

  1. 第一次写一个文件或者目录:第一次向一个已经存在的文件中写入内容,此文件在容器层(upperdir)中不存在,此时overlay2驱动会执行copy_up操作,从镜像层中(lowerdir)copy这个文件到容器层(upperdir),然后在容器层里copy的文件中进行写操作。但是,OverlayFS工作在文件级别而不是块级别,这意味着所有OverlayFS copy_up操作都会复制整个文件,即使该文件非常大且只有一小部分被修改。这会对容器写入性能产生明显影响。但是,有两点值得注:copy_up操作仅在第一次写入给定文件时发生。随后对同一文件的写入将对已经复制到容器的文件副本进行操作;OverlayFS仅适用于两层。这意味着性能应该比AUFS更好,后者在多层图像中搜索文件时会出现明显的延迟。此优点适用于overlay和overlay2驱动程序。与之相比,overlayfs2在初次读取时的性能要稍差于overlayfs,因为它必须遍历更多的层,但是会缓存结果,因此这只是一个小小的代价。
  2. 删除文件或者目录:当在容器中删除一个文件时,一个whiteout 文件会在容器层(upperdir)中被创建,在镜像层(lowerdir)中的文件不会感知到这个删除操作,因为image层时只读层,但是whiteout文件会隐藏删除的文件,使之不可见。当一个目录在容器中被删除,一个opaque目录会在容器层(upperdir)中被创建,这和删除文件的机制类似。
    3. 重命名文件:仅当源路径和目标路径都在顶层时,才允许为目录调用rename(2),否则,它将返回EXDEV错误(“不允许跨设备链接”)。您的应用程序需要设计为可以处理EXDEV并退回到“复制和取消链接”策略。

你可能感兴趣的:(Docker storage driver overlayFS)