您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

UnionFS 与 Docker

我们自己在上一节留下了不少问题,在自制 rootfs 有很多不完善的地方,在 Docker 产品的方面,就对这些部分进行了补足, 的方案,基本都是围绕 UnionFS (联合系统)展开的,本节我们会讲讲 UnionFS 和它在 Docker中 的应用。

计算机的系统是一种存储和组织计算机数据的,它使得对其访问和查找变得容易,系统使用和树形目录的抽象逻辑概念代替了硬盘和光盘等物理设备使用数据块的概念,使用系统来保存数据不必关心数据实际保存在硬盘(或者光盘)的地址为多少的数据块上,只需要记住这个的所属目录和名。在写入新数据之前,不必关心硬盘上的那个块地址没有被使用,硬盘上的存储空间管理(分配和释放)由系统完成,只需要记住数据被写入到了哪个中。

一句话总结,系统是一套实现了数据的存储、分级组织、访问和等操作的抽象数据类型。

联合系统(Union File Sy):2004 年由纽约州立大学开发,它可以把多个目录联合挂载到同目录下,而目录的物理位置是分开的。UnionFS可以把只读和可读写系统合并在一起,具有写时复制,允许只读系统的可以保存到可写系统当中。

目前有多种系统可以被当作联合系统,CentOS8 使用的是 overlay2,下面,我们尝试着挂载 overlay2 系统。

/root/test 目录下,建立unionfs 目录,它的目录结构如下(a,b,c是,其他都是目录):

unionfs
├── lower1
│   ├── a
│   └── b
├── lower2
│   └── a
├── merged
├── upper
│   └── c
└── work

进入 unionfs 目录,使用 mount 命令挂载:

cd unionfs
mount -t overlay overlay -o lowerdir=lower1:lower2,upperdir=upper,workdir=work merged

如上,挂载了名为 overlay 的 overlay2 类型的系统,挂载点为 merged 目录。

查看 merged 目录的层次:

[root@centos8 unionfs]# tree merged
merged
├── a
├── b
└── c

查看这些的:

[root@centos8 unionfs]# for i in `ls merged`;do echo $i: `cat merged/$i`;done
a: in lower1
b: in lower1
c: in upper

可以看到,从 merged 视角,位于 lower2 的 a 被 lower1 的 a 覆盖;b 位于 lower1,c 位于 upper,符合从高到低 upper->lower1->lower2 的层次结构。

我们按照如下操作来验证 unionfs 的分层特性:

[root@centos8 unionfs]# touch merged/d
[root@centos8 unionfs]# ls merged/
a  b  c  d
[root@centos8 unionfs]# ls upper/
c  d
[root@centos8 unionfs]# ls lower1
a  b
[root@centos8 unionfs]# ls lower2
a

可以看到对 merged 目录的改动同步至 upper 目录中,并不会影响到 lower 目录。

Docker 的官方文档中有一张,很好地展示了 Docker 使用 UnionFS 搭建的分层结构的状态。

图中的容器是运行在 debian 容器环境中的 apache 网页应用,这个环境还提供了 emacs 编辑器。

将之前我们自己构建的 rootfs 与上面这张对比,会发现我们将所有系统、运行库和上层应用,都放到了 rootfs 里面,这样做缺乏灵活性,增大了维护的复杂度。而 Docker 引入了层(layer)的概念,将 rootfs 的进行了分层管理,有系统层,运行库依赖层等等,可以一层接一层进行增量式挂载叠加。启动容器的时候通过 UnionFS 把相关的层挂载到目录,作为容器的根 rootfs。

借助于 UnionFS,容器内部的更改都被保存到了最上面的读写层,而其他层都是只读的,这样中只读 rootfs 是可以被多个容器复用的。UnionFS 将的更新挂载到老的之上,而不去那些不更新的,这就意味着即使虚拟的系统被反复,也能保证宿主机空间占用保持较低水平。

我们将中间只读的 rootfs 的集合称为 Docker 镜像,我们在后面的部分会讲到,Docker 镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。UnionFS 使得镜像的复用、定制变得更为容易。甚至可以用之前构建好的镜像作为基础层,然后进一步新的层,以定制自己所需的,构建新的镜像。

Docker 容器与我们之前的容器在本质上没有区别,我们之前的容器更偏向抽象的技术概念,而受到在 Docker 管理约束的容器就是 Docker 容器,它会带有 Docker 产品的一些特征和。

Docker镜像 和 Docker容器 的关系,就像是面向对象程序设计中的 类 和 实例 一样,镜像是静态的定义,容器是镜像运行时的实体。
从系统来看,Docker容器比Docker镜像多一层可读写的系统挂载层,从生命周期来看,Docker容器可以被创建、启动、停止、、暂停等。

在 rootfs 的基础上,Docker 公司创新性地提出了使用 UnionFS,多个增量 rootfs 联合挂载完整 rootfs 的方案,通过“分层镜像”的设计,围绕 Docker 镜像,大家甚至可以协同工作,再 Docker 官方提供的镜像仓库,进一步减少了共享镜像的成本,这大大提高了开发部署的效率。


联系我
置顶