本节书摘来自华章出版社《循序渐进学Docker》一书中的第1章,第1.3节,作者李金榜 尹烨 刘天斯 陈纯,更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1.3 为什么使用Docker
当深入了解Docker后,你想在公司或部门推广Docker,就需要给大家讲明白为什么要使用Docker。
当讲Docker是什么时,你的听众是一批Docker爱好者,Docker的原理和实现细节讲得越深入、越具体,就越受大家的欢迎;当讲为什么要使用Docker时,你的听众有领导,有开发、测试和运维人员,而他们可能从来没听过Docker,或者对Docker知之甚少,他们更关注Docker能带来什么价值,引入Docker需要对现有的系统或程序做多大改造,Docker是不是足够的稳定,学习和使用Docker的成本有多高等问题。
1.3.1 从代码管理说起
现在的软件项目,失败的原因主要是结构设计不合理、编程人员水平不高、代码bug太多等因素。不管项目有多大,参与的成员有多多,代码修改多么频繁,很少是由管理上混乱导致项目失败的。究其原因,主要是我们有非常优秀的代码管理工具——Git和SVN。它们有版本控制和中心仓库这两大核心功能,能保证大家不用担心下列问题:
快速把代码分享给别人。
多人同时修改一个文件,导致代码不一致。
分不清每个人在什么时间都提交过什么代码。
代码被误删误改,不知道哪些文件被删被改,也恢复不到以前的状态。
变更和新分支太多,混乱到无法维护的地步。
版本控制功能不仅能清晰记录每个开发者在什么时间交过什么代码,还能让大家在各个版本间自由地切换、融合。大家如果要对齐开发环境,不需要逐一列出文件的名字、文件的内容,只需要简单地说下版本号,就能保证大家的文件完全一致。
中心仓库可以保证多人协作有一个统一的平台,既可以与别人分享代码和开发进度,也可以对每个人的代码做异机备份,防止因为机器故障而导致数据丢失。
软件部署和代码管理面临很多相似的问题:
如何快速把一台机器的应用环境分享给其他机器使用,用于扩容和故障时服务转移。
同一个功能模块的多台机器,软件版本和配置文件镜像出现不一致,很难被发现。
多人维护一套系统,很难清晰地记录下每个人都做过什么操作、每次变更都有哪些内容,以便在故障时快速回退。
有些配置文件或数据被误删了,恢复不回来,甚至很长一段时间都察觉不到。
随着操作系统版本、软件、硬件的更新迭代,系统维护的复杂度直线上升,混乱不堪。
既然代码管理做得这么好,那软件部署为什么不借鉴代码管理的方法呢?
代码管理的对象是纯文件(代码),体量小,有统一规范的文件编码方式,对平台无依赖。而软件部署管理的对象是一个环境,除了文件,还有二进制的软件和它依赖的运行环境(包括操作系统和依赖库)。由于操作系统和依赖库的体量很大,难以完全照搬代码管理的方式,用版本控制和中心仓库来解决软件部署的问题。
1.3.2 当前的优化策略
下面让我们看看,对于软件部署,目前主流的解决方案是什么样子的。
把环境分为两个部分:基础环境和应用环境。
基础环境:包含机器硬件、操作系统、提供基础服务的应用(如ssh、syslog等)。
应用环境:包含应用需要的各种软件包和配置文件(虽然软件包中也可以包含配置文件,但对于一些变更频繁和需要个性化配置的文件,最好还是独立出来)。
对这两种类型的环境,采取不同的策略:
基础环境统一化,尽量保持完全一致。比如,使用相同的硬件服务器,运行相同版本的操作系统和基础软件。
应用环境分解出一个个独立服务,每个服务再分解为包和配置文件,使用版本控制和中心仓库来对包与配置进行管理。
整体的解决方案如图1-11所示。
在这个解决方案中,我们把软件包和配置都版本化,每次变更都提交一个版本到中心仓库,然后再下发到各台机器上。由于每台机器的基础环境都保持一致,所以软件部署时可以不关注底层操作系统的适配问题,在一台机器打包编译的应用可以快速迁移到其他机器。
这个解决方案,在基础环境一致的前提下,实现了分解版的版本控制和中心仓库,针对分解出来的软件安装包和配置文件,可以通过版本来管理,并且可以把包和配置提交到中心仓库,让所有其他机器分享。
这个方案,存在以下两个问题:
基础环境难以改动:因为上层应用环境的软件和配置文件都是基于基础环境编译与配置的,一旦基础环境发生改变,可能导致上层的软件包和配置不能正常工作。
应用环境的维护成本取决于包和配置的数量:由于应用环境不是一个统一整体,而是分解出一个个包和配置,随着包和配置的增多,维护的复杂性也随之增加。
1.3.3 Github版的应用部署解决方案
Github是最流行、最优秀的代码管理平台,Docker借鉴了Github的管理思路,打造了一个Github版的应用部署的管理方案。
如果使用Docker来管理部署应用,解决方案如图1-12所示。
和上一节的方案做下对比:
基础环境灵活,对硬件和操作系统都没有限制,只需要在每台机器上安装Docker Engine,用于运行Docker应用。
应用环境也不再分解为一个个包和配置文件,而是作为一个有机的整体,这个有机的整体包含应用需要的所有软件包、配置文件和它依赖的运行环境(操作系统和依赖库),带有版本控制功能,也可以提交到中心仓库供大家共享。由于Docker的镜像中包含应用运行需要的所有包、配置和系统环境,下发镜像后不需要做任何安装配置,应用就可以直接运行,不会随着应用中包和配置数量的增加,导致安装部署变得复杂。
Docker方案完美地把代码管理中的版本控制和中心仓库概念移植到应用部署领域,让大家顿时从应用部署烦琐、重复的工作中解脱出来,可以像使用Github管理代码那样优雅地管理应用的部署工作。
Docker这个方案能顺利实施,一个关键点是通过分层共享和增量变更技术把应用的运行环境(包括操作系统在内)这么一个庞大的体量顺利瘦身,让应用运行环境的安装和修改在大多数情况下与只装软件包一样轻量、简单。分层共享和增量变更技术在1.2.2节有过详细讲解,这里就不再复述了。
1.3.4 Docker应用场景
下面描述两个典型的Docker应用场景,如图1-13所示。
在这两个应用场景中,有开发、测试(QA)和运维人员,分别维护开发、测试和生产环境的服务,他们有一个私有的Docker仓库,存储着各种各样的Docker化的应用镜像。
场景一
现在有一个需求,需要对应用App1做修改、测试和发布新变更到生产环境,工作步骤如下:
1)开发者先从私有仓库找到App1这个应用最新稳定版本,假设为V1.0版,把这个App1:v1.0下载到开发机,修改,并提交新版本V1.1到私有仓库,并告诉测试人员测试。
2)测试人员下载开发者刚提交的新版本App1:v1.1,测试,并把测试结果反馈给开发者。
3)如果测试失败,开发继续修改,提交新版本给测试人员做新一轮的测试;如果测试成功,开发把要发布的应用的名称和版本号提供给运维同事。
4)运维人员根据开发提供的应用名和版本号,把相关镜像从私有仓库下拉到各个生产环境的机器上,停掉旧版本的Docker容器,启动新版本的Docker容器,完成发布。生产环境的机器上可以同时缓存应用的多个版本镜像,如果新发布的版本有问题,可以快速切换回原来的版本。
因为Docker的应用镜像包含应用运行需要的所有软件包、配置和操作系统,所以开发者打包好Docker镜像,测试和运维人员从私有仓库下拉,不需要做任何修改,就可以运行起来,并保证和开发者运行的环境完全一致。“一处编译,到处运行”,真的很方便。
场景二
有一个应用App2,目前在生产环境正常运行,但由于系统比较老、缺乏维护、开发和运维经历过更替且交接文档不全,现在谁都不知道该如何部署App2这个应用到新服务器上。
如果App2是Docker化的应用,它可以直接把运行的环境转换为一个带版本号的Docker镜像(比如App2:v1.0),提交到私有仓库,供开发者修改或运维人员发布新机器。
1.3.5 Docker可以解决哪些痛点
1.开发人员
不管在大公司还是小公司,开发人员经常被如下问题困扰:
为了节约成本,一台开发机多人使用,管理混乱,相互干扰。
一个开发往往只用一套开发环境,同时有多个开发任务时,不得不反复修改开发环境,以适应不同的开发任务。
多个开发人员希望保持相同的开发环境开发同一个项目,但开发环境难以复制,即便大家起初的开发环境一样,随着项目的滚动、开发环境的不停更新,很难保证每个人的开发环境都同步更新。
开发机硬件故障,需要更换新机器,重新搭建开发环境是件头疼的事。如果硬件故障,重要数据没备份,那就更让人崩溃。
打算调研下新软件,安装配置文档复杂,仅仅把软件安装、运行起来就要花费大半天时间。
上面问题带来的工作量不能体现开发人员的核心价值,但是是不得不面对的。
如果使用Docker,可以轻松解决上述问题:
Docker化的应用使用容器虚拟化技术,每个应用都运行在独立的虚拟化环境中,天然具有隔离性,不用担心一机多用造成的管理混乱。
开发人员在多任务开发时,可以并行启动这些应用的Docker容器,每一个Docker应用有一个独立的运行环境,互不干扰。
开发机硬件故障,在新开发机上,重新从Docker仓库下拉开发环境的镜像,一两分钟内就可以重新搭建一套开发环境,并且即便新旧开发机的硬件和操作系统不一致,重新搭建的开发环境仍能保持和原来的环境一模一样。另外,还可以通过Docker仓库,把重要变更及时备份到远端。
Docker的每个复杂软件都可以制作成Docker镜像,分享给大家使用。随着Docker的流行,几乎所有主流的软件都提供Docker化的部署方式。软件部署将成为再简单不过的事情。
2.测试人员
测试人员经常费了九牛二虎之力测出一些bug,和开发逐一核对,发现大多数bug都是开发和测试环境不一致造成的。
测试人员经常为配置不同的测试环境浪费大量的时间,还是不能保证和开发环境完全保持一致,开发人员虽然很认真负责地告诉测试人员如何配置测试环境,但还是经常性地遗漏一些配置。
使用Docker,不需要做任何配置,就能保证开发和测试环境完全一致,测试人员只需要关注测试本身就可以了。
3.运维人员
运维人员大部分时间都浪费在装软件、修改配置上,重复单调,经常半夜还要起来做紧急扩容、故障机服务迁移。如果使用了Docker,好处显而易见:
服务具备快速部署能力,扩缩容、版本回退在几秒钟内就可以完成。
基于同一个Docker镜像部署服务,可以保证每台机器应用完全一致。
由于Docker化应用是虚拟化,多个应用可以混合部署在一台机器上,互不干扰,可以提高机器使用率。
Docker化的应用可以运行在不同的硬件和操作系统平台下,在不同的环境自由迁移。
通过Dockerfiel管理Docker镜像,即使系统多次易手、交接文档不全,运维人员也可以快速了解系统是如何搭建的。
Docker倡导“Build once,Run anywhere”,再烦琐的活儿,只需要做一次,制作成Docker镜像,在任何环境下都可以运行;还可以基于这个Docker镜像做修改,制作新的镜像。
上面只罗列几条好处,运维在使用Docker的过程中,还会发现很多意想不到的好处。一句话,Docker可以让运维工作变得简单和易于维护。
1.3.6 Docker的使用成本
坦白说,Docker是有学习和使用成本的。
Docker虽然已经做得足够简单易用,但由于它的定位是虚拟化容器,是一个单机版的应用,如果要基于Docker构建集群或PaaS管理系统,如Web管理界面、任务调度策略、监控报警等,则还需要自己开发或从开源社区寻求支持。
另外,传统的运维是以机器为中心,而Docker是以应用为中心,它会颠覆我们一些固有的运维习惯和运维方式。
但好在Docker有非常活跃的社区,不但有大量的开发者为Docker贡献代码、修复bug,让Docker越来越好用、越来越稳定;还有大量的学习资料和问题解答。另外,很多公司和个人也为Docker提供大量优秀的第三方开源软件,如kubernetes、f?ig、etcd和cadvisor等。这些都有助于进一步降低Docker学习和使用的门槛。
如果你被上面的理由说服了,那就赶快跟着本书,学习和使用Docker吧!