容器镜像按需加载
1、镜像知识点回顾
1.1、镜像技术
1.1.1. Images & layers
Docker image 是由一组上下有序的只读 layer 构建出来的,当用 Dockerfile 构建 image 时,Dockerfile 中每个命令就代表着一个 layer。每一个 layer 都只包含了相比于下一层的 layer 不同的内容,最后所有的 layer 堆叠起来就是一个新的 image。
以下面这个 Dockerfile 为例,它以 Ubuntu15.04 的 image 为基础 image ,加入一个 App 后构建出一个新的 image:
通过docker file制作镜像,每行命令产生了一个image layer。可以通过docker history {image_id}查看制作过程、命令和对应那一个layer。
1.1.2. Container and layers
容器 = 镜像 + 读写层
通过镜像启动容器时,docker 将会在这些只读 layer 的顶部添加一个 writable layer ,也叫作 container layer,container 运行时的所有修改都会写到这个 writable layer 中,包括创建新文件、修改存在的文件、删除文件(Copy On Write)等。Docker 用 storage driver 负责处理各个 layer 之间的交互,docker 目前支持的 storage driver 有 overlay、aufs、zfs、btrfs、devicemapper 等,这些其实都是一些不同类型的联合文件系统。
Container 和 image 之间最大的不同就是顶层的那个 writable layer。Container 删除后,这个 writable layer也会被删除,底层的 image不会发生任何变化。因为所有的修改都写到了writable layer,所以多个container可以共享部分甚至全部的只读layer(底层image),
Copy-on-write 写时复制,顾名思义,在写数据的时候再对源数据进行拷贝,它将共享和拷贝文件的效率最大化。在 container 中,如果要修改一个在只读 layer 中已经存在的文件,这个文件会先被拷贝到writable layer,然后将修改写入 writable layer 中的文件副本。在build image的过程中,某一层要 layer 修改底层 layer 的文件,流程一样如此。
1.2、存储驱动
Docker 的存储驱动称为 graph driver 或 storage driver ,containerd 的存储驱动称为 snapshotter。不论是docker 还是 containerd 的存储驱动,作用都是将从远程存储把镜像下载下来,然后以各种存储驱动特有的方式将镜像转换为一个文件目录的形式,用作容器启动的 rootfs。
1.2.1. 基于目录Union mount的驱动:aufs, overlay, overlay2
文件级存储驱动一般使用一种 union mount 的方法,依赖文件语义实现镜像的分层和 COW,包括 aufs,overlay 和 overlays2。文件级存储驱动将多个文件系统目录根据层级关系整合为一个,特点如下:
在 image 的各个 layer 中查找目标文件;
将目标文件复制至容器的 writable layer;
在 writable layer 修改目标文件,这样镜像各个 layer 中的原文件将不会被读到。
优点:内存利用率高;
缺点:多写场景下 writable layer 会越来越大;
1.2.2. 基于块级快照的驱动: btrfs, zfs 和 devicemapper
块级存储驱动则一般基于内核对存储。比如基于btrfs、ZFS的快照特性。块级镜像方案有如下特点:
多写场景下性能更好;
btrfs 和 ZFS需要更多内存;
ZFS适用场景:高密度的PaaS集群;
下图对比了几种驱动的性能[15]:
1.2.3. 配置方法
下面以docker为例介绍使用方法[10-12]:通过docker info查看当前的存储驱动
Last updated
Was this helpful?