容器化之路:谁偷走了我的构建时间

随着全面云时代到来,很多公司都走上了容器化道路,老刘所在的公司也不例外。作为一家初创型的互联网公司,容器化的确带来了很多便捷,也降低了公司成本,不过老刘却有一个苦恼,以前每天和他一起下班的小王自从公司上云以后每天都比他早下班一个小时,大家手头上的活都差不多,讲道理不应该呀,经过多番试探、跟踪、调查,终于让老刘发现了秘密的所在。

作为一个开发,每天总少不了要出N个测试版本进行调试,容器化以后每次出版本都需要打成镜像,老刘发现每次他做一个镜像都要20分钟,而小王只要10分钟,对比来对比去只有这个东西不一样!


Storage-Dirver到底是何方神圣?为什么能够导致构建时间上的差异?现在让我们来一窥究竟。

在回答这个问题之前我们需要先回答三个问题——什么是镜像?什么是镜像构建?什么是storage-driver?

什么是镜像?

说到镜像就绕不开容器,我们先看一张来自官方对镜像和容器解释的图片:


看完以后是不是更疑惑了,我们可以这样简单粗暴的去理解,镜像就是一堆只读层的堆叠。那只读层里到底是什么呢,另外一个简单粗暴的解释:里边就是放了一堆被改动的文件。这个解释在不同的storage-driver下不一定准确但是我们可以先这样简单去理解。

那不对呀,执行容器的时候明明是可以去修改删除容器里的文件的,都是只读的话怎么去修改呢?实际上我们运行容器的时候是在那一堆只读层的顶上再增加了一个读写层,所有的操作都是在这个读写层里进行的,当需要修改一个文件的时候我们会将需要修改的文件从底层拷贝到读写层再进行修改。那如果是删除呢,我们不是没有办法删除底层的文件么?没错,确实没有办法删除,但只需要在上层把这个文件隐藏起来,就可以达到删除的效果。按照官方说法,这就是Docker的写时复制策略。

为了加深大家对镜像层的理解我们来举个栗子,用下面的Dockerfile构建一个etcd镜像:


构建完成以后生成了如下的层文件:


每次进入容器的时候都感觉仿佛进入了一台虚机,里面包含linux的各个系统目录。那是不是有一层目录里包含了所有的linux系统目录呢?

bingo答对!在最底层的层目录的确包含了linux的所有的系统目录文件。


上述Dockerfile中有这样一步操作

ADD . /go/src/github.com/coreos/etcd

将外面目录的文件拷到了镜像中,那这一层镜像里究竟保存了什么呢?


打开发现里面就只有

/go/src/github.com/coreos/etcd这个目录,目录下存放了拷贝进来的文件。

到这里是不是有种管中窥豹的感觉,接下来我们再来了解什么是镜像构建,这样基本上能够窥其全貌了。

什么是镜像构建?

通过第一节的内容我们知道了镜像是由一堆层目录组成的,每个层目录里放着这一层修改的文件,镜像构建简单的说就是制作和生成镜像层的过程,那这一过程是如何实现的呢?以下图流程为例:


Docker Daemon首先利用基础镜像ubuntu:14.04创建了一个容器环境,通过第一节的内容我们知道容器的最上层是一个读写层,在这一层我们是可以写入修改的,Docker Daemon首先执行了RUN apt-update get命令,执行完成以后,通过Docker的commit操作将这个读写层的内容保存成一个只读的镜像层文件。接下来再在这一层的基础上继续执行 ADD run.sh命令,执行完成后继续commit成一个镜像层文件,如此反复直到将所有的Dockerfile都命令都被提交后,镜像也就做好了。

这里我们就能解释为什么etcd的某个层目录里只有一个go目录了,因为构建的过程是逐层提交的,每一层里只会保存这一层操作所涉及改动的文件。

这样看来镜像构建就是一个反复按照Dockerfile启动容器执行命令并保存成只读文件的过程,那为什么速度会不一样呢?接下来就得说到storage-driver了。

什么是storage-driver?

再来回顾一下这张图:


之前我们已经知道了,镜像是由一个个的层目录叠加起来的,容器运行时只是在上面再增加一个读写层,同时还有写时复制策略保证在最顶层能够修改底层的文件内容,那这些原理是怎么实现的呢?就是靠storage-driver!

简单介绍三种常用的storage-driver:

  1. AUFS

AUFS通过联合挂载的方式将多个层文件堆叠起来,形成一个统一的整体提供统一视图,当在读写层进行读写的时,先在本层查找文件是否存在,如果没有则一层一层的往下找。aufs的操作都是基于文件的,需要修改一个文件时无论大小都会将整个文件从只读层拷贝到读写层,因此如果需要修改的文件过大,会导致容器执行速度变慢,docker官方给出的建议是通过挂载的方式将大文件挂载进来而不是放在镜像层中。

  1. OverlayFS

OverlayFS可以认为是AUFS的升级版本,容器运行时镜像层的文件是通过硬链接的方式组成一个下层目录,而容器层则是工作在上层目录,上层目录是可读写的,下层目录是只读的,由于大量的采用了硬链接的方式,导致OverlayFS会可能会出现inode耗尽的情况,后续Overlay2对这一问题进行了优化,且性能上得到了很大的提升,不过Overlay2也有和AUFS有同样的弊端——对大文件的操作速度比较慢。

  1. DeviceMapper

DeviceMapper和前两种Storage-driver在实现上存在很大的差异。首先DeviceMapper的每一层保存的是上一层的快照,其次DeviceMapper对数据的操作不再是基于文件的而是基于数据块的。

下图是devicemapper在容器层读取文件的过程:


首先在容器层的快照中找到该文件指向下层文件的指针。

再从下层0xf33位置指针指向的数据块中读取的数据到容器的存储区

最后将数据返回app。

在写入数据时还需要根据数据的大小先申请1~N个64K的容器快照,用于保存拷贝的块数据。

DeviceMapper的块操作看上去很美,实际上存在很多问题,比如频繁操作较小文件时需要不停地从资源池中分配数据库并映射到容器中,这样效率会变得很低,且DeviceMapper每次镜像运行时都需要拷贝所有的镜像层信息到内存中,当启动多个镜像时会占用很大的内存空间。

针对不同的storage-driver我们用上述etcd的dockerfile进行了一组构建测试

文件存储系统 单次构建时间 并发10次平均构建时间
DevivceMapper 44s 269.5s
AUFS 8s 26s
Overlay2 10s 269.5s

注:该数据因dockerfile以及操作系统、文件系统、网络环境的不同测试结果可能会存在较大差异

我们发现在该实验场景下DevivceMapper在时间上明显会逊于AUFS和Overlay2,而AUFS和Overlay2基本相当,当然该数据仅能作为一个参考,实际构建还受到具体的Dockerfile内容以及操作系统、文件系统、网络环境等多方面的影响,那要怎么样才能尽量让构建时间最短提升我们的工作效率呢?

且看下回分解!

原文地址:https://blog.51cto.com/14051317/2377220

时间: 2024-10-30 04:43:06

容器化之路:谁偷走了我的构建时间的相关文章

华为云容器化交付流水线 引领企业容器化之路

ContainerOps 12月16日,OSChina在深圳举办的"源创会年终盛典"上,华为云容器服务技术总监发表了名为<DevOps On Kubernetes>的主题演讲,演讲就如何将DevOps理念与容器技术相结合,实现容器化场景下的快速交付进行介绍,并重点介绍了华为云容器服务提供的持续交付工具--容器交付流水线(ContainerOps). DevOps作为一种形而上的理念,其落地实施必然离不开CI/CD等一系列工具的支撑,CI/CD工具的出现大大提升了企业的软件行

华为云容器交付流水线 引领企业容器化之路

ContainerOps 12月16日,OSChina在深圳举办的"源创会年终盛典"上,华为云容器服务技术总监发表了名为<DevOps On Kubernetes>的主题演讲,演讲就如何将DevOps理念与容器技术相结合,实现容器化场景下的快速交付进行介绍,并重点介绍了华为云容器服务提供的持续交付工具--容器交付流水线(ContainerOps). DevOps作为一种形而上的理念,其落地实施必然离不开CI/CD等一系列工具的支撑,CI/CD工具的出现大大提升了企业的软件行

JENKINS管道部署容器化初探

目标服务器安装docker参考官方文档 https://docs.docker.com/install/linux/docker-ce/centos/ (可选)在目标服务器上安装docker私服 https://docs.docker.com/registry/ 目标服务器启动jenkinsdocker镜像容器 https://hub.docker.com/r/jenkinsci/blueocean/ 创建dockerfile进行后端编译环境的镜像搭建 参考官方教程:https://jenkin

容器化-Docker介绍

导读:本文章对Docker技术进行了介绍,阐述了Docker的技术发展历程.容器与虚拟机的差异.Docker原理.特点.Docker三组件和Docker带来的影响,为我们进一步理解Docker打下基础. 一.前言 2014年春天,我进入一家电商公司做反应式编程研究和落地工作,因为做的是平台工作,希望通过平台去满足不通的业务场景,业务部门只需要进行简单的适配和封装就能进行产品创新.此时就需要一种工具去快速搭建基础环境,环境之间不能相互干扰,业务部门还能方面使用.就这样和Docker进行了第一次偶遇

唯品会RPC服务框架与容器化演进--转

原文地址:http://mp.weixin.qq.com/s?__biz=MzAwMDU1MTE1OQ==&mid=405781868&idx=1&sn=cbb10d37e25c76a1845f593a222da3c9&scene=0#wechat_redirect 编者按:本文是邱戈川在 3 月 27 日数人云"百万并发"活动的演讲,授权「高可用架构」首发.转载请注明来自高可用架构公众号「ArchNotes」.   邱戈川,唯品会分布式架构平台产品经理

Kubernetes 集群的两种部署过程(daemon部署和容器化部署)以及glusterfs的应用!

ClusterIp:通过VIP来访问, NodePort: 需要自己搭建负载据衡器 LoadBalancer:仅仅用于特定的云提供商 和 Google Container Engine https://www.nginx.com/blog/load-balancing-kubernetes-services-nginx-plus/ port:相当于服务端口(对及集群内客户访问) targetPort: 相当于pods端口 nodePort: 宿主机端口(也是服务端口,只不过是对集群外客户访问)

Docker管理套件使容器化变得更加井然有序

Docker之前发布了一个新的容器控制中心,称为Docker数据中心(DDC),其设计目的是用于大型和小型企业创建.管理和分发容器的一个集成管理控制台. DDC是由包括Docker Universal Control Plane(也是同时发布的)和Docker Trusted Registry等不同的商业组件组成,它也包括了开源组件比如Docker Engine.这个产品让企业在一个中心管理界面中就可以管理整个Docker化程序的生命周期,更加方便. 负责产品管理的SVP Scott Johns

从研发到生产的容器化

Coding-Job:从研发到生产的容器化融合实践 大家好,我是来自 CODING 的全栈开发工程师,我有幸在 CODING 参与了 Coding-Job 这个容器化的编排平台的研发.大家对 CODING 可能比较了解, Coding.net 是一个一站式开发平台,具有代码托管,任务管理,产品演示和 WebIDE 等功能.整体功能看起来比较复杂且较为分散. 这是我们 Coding 的架构演进流程.那么怎么评判一个系统复不复杂,个人觉得看两个指标,一个就是运维人员用多久时间可以把新的代码部署上线.

kolla 容器化openstack

目前手动部署openstack都很繁琐 so all of people 都在研究怎么能快速 简单的部署openstack 最近也在研究 在官网看到了 kolla的这东东 经过调研 好多人在用 也就义无反顾的 跟随了 开始kolla的时代 一.系统环境 centos7.2 两块网卡 4c 8G 40G 二.kolla是做openstack容器化的镜像 而kolla-ansible是用来部署openstack插件 由于kolla对组建的版本以来较大 so 你懂得 只列出mitaka和ocata的依