关于 docker 是什么,有个著名的隐喻:集装箱。但是它却起了个“码头工人”(docker 的英文翻译)的名字。这无疑给使用者很多暗示:“快来用吧!用了 docker,就像世界出现了集装箱,这样你的业务就可以随意的、无拘无束的运行在任何地方(Docker 公司的口号:Build,Ship,and Run Any App,Anywhere),于是码头工人就基本都可以下岗了。”但是人们往往忽略了一个问题,隐喻的好处是方便人理解一个不容易理解的概念,但并不能解释其概念本身。
互联网技术行业的一大特点是,这里的绝大多数事物并不像现实生活那么具体,在这个行业中我们所接触的绝大多数概念都是抽象的、不具体的。所以现实生活中很多可笑的事情在互联网技术行业就不仅变的不可笑,反而可能很严肃。就比如,现实生活中你是几乎不可能看见两个神经正常的成年人争论到底是锤子更好还是螺丝刀更好这个问题的。而在我们这个行业,你可以很容易的被卷入到底是 java 好?还是 php 好?还是 js 好?或者类似的语言之争中。当然除了语言,其它的软件工具之争也比比皆是,比如经典的还有 vim vs emacs。
由于不具体和抽象,就需要隐喻来给投资人解释其价值,毕竟投资人大多数是外行嘛。至于 docker 到底是“集装箱”还是“码头工人”并不重要,即使这两个概念本质上冲突了都不重要,很少有人会去真的思考集装箱的出现导致码头工人几乎绝迹。只要能让大家明白 docker 是个重要的、有价值的、划时代的工具,骗到投资人的钱就足够了。也很少有投资人去考究集装箱的发明人到底有没有因此赚到钱?以及为什么没赚到钱?只要概念能忽悠人就行了。当然这个概念顺便也忽悠了所有懒得思考的技术工程师。
吐了一大段槽之后,回到我们的正题,docker 到底是什么?既然大家喜欢集装箱这个隐喻,那么我们也不妨先来看看集装箱的本质。大家应该基本都理解集装箱是怎么改变世界的吧?在集装箱之前,货物运输没有统一的标准方式进行搬运,于是铁路、公路、海洋等各种运输之间,需要大量的人力作为货物中转,效率极低,而且成本很高。集装箱出现之后,世界上绝大多数的货物运输都可以放到这个神奇的箱子里,然后在公路、铁路、海洋等所有运输场景下,这个箱子都可以不用变化形态直接可以承运,而且中间的中转工作,都可以通过大型机械搞定,效率大大提升。从此全球化开始,商业的潜力被进一步挖掘……牛逼之处我就不多说了,可是这个箱子为什么这么神奇呢?答案其实也就在上面的描述中,无非就是两个字:标准。
是的!标准!标准!标准!重要的事情说三遍。
因为规范了集装箱的大小和尺寸的规格标准,于是相应的船舶、卡车、列车才能按照规格制造出来使联运成为可能,所有的运输中转的自动化工具才能被设计建造出来并且高效的使用,才可以极大的提高效率,提升自动化水平,以至于码头工人才会失业。集装箱本身是一个产品,而这个产品无非就是“标准化”的这个概念穿上了马甲,马甲可以有红的、绿的、蓝的、花的,但是大小规格必须都一样。现实世界中的事实显而易见,就是这么简单。那么 docker 呢?
按照这个思路,docker 其实跟集装箱一样,或者说它想跟集装箱一样,成为穿着马甲的“标准化”。这样开发工程师就可以把它们开发出来的 bug 们放到“集装箱”里,然后运维人员就可以使用标准化的操作工具去运维这些可爱的 bug 们。于是实现了“海陆联运”,就好像运维工程师根本不需要了解其运维的软件架构,而开发工程师也并不需要了解其软件运行的操作系统一样……
这就是 docker 的实质:穿着马甲的标准化。docker 的发明人根据自己运维 PaaS 平台的经验,重新思考了自己的工作,将PaaS 平台的 devops 工作从各个角度标准化了一下,将系统底层实现的 cgroup、namespace、aufs|device mapper 等技术集成在一个使用镜像方式发布的工具中,于是形成了 docker。观察 docker 形成的思考过程,其实就是作者针对他所运维的场景如何做自动化运维的思考,大家可以参见其演讲的 PPT。这个演讲的名字就跟自动化运维相关:Docker: automation for the rest of us 。那么 docker 的实质是什么?在我看来就是个针对 PaaS 平台的自动化运维工具而已。众所周知(当然如果你不知道,那么我来告诉你):自动化运维的大前提就是标准化。
如果你正好是一个运维工程师,而且你正感觉你的运维环境一团糟,麻烦请你思考一下这是为什么?你是不是正在运维着一个使用 php、java、C# 甚至 C/C++ 等用各种语言编写的应用都在运行的环境里?这个环境是不是因为某种历史原因,使你的操作系统运行着各个版本的内核,甚至还有 windows?即使是同样语言编写的业务也运行着不同版本的库?你的整个系统环境是不是甚至找不出来两台硬件、操作系统、库版本以及语言版本完全一样的环境?于是你每次遇到问题都要去排查到底那个坑到底在那里?从网络、内核到应用逻辑。你每次遇到产品升级都要在各种环境上做稳定性测试,发现不同的环境代码 crash 的原因都不尽相同。你就像一个老中医一样去经历各种疑难杂症,如果遇到问题能找到原因甚至都是幸运的,绝大多数情况是解决了但不知道原因,和没解决自动好了也不知道原因。于是你们在一个特定的公司的环境中积累着“经验”,成为你们组新手眼中的大神,凭借历经故障养成的条件反射在快速解决不断发生的重复问题,并故弄玄虚的说:这就是工作经验。因为经验经常是搞不清楚原因时的最后一个遮羞布。当别人抱怨你们部门效率低的时候,你一般的反应是:”you can you up,no can no BB!“
我花了这么多口舌吐槽运维,无非就是想提醒大家”运维标准化的重要性“这一显而不易见的事实。标准化了,才能提高效率。标准化了,才能基于标准建设属于你们系统的自动化运维。那么我们再来看看 docker 是怎么做的?
首先,标准化就要有标准化的文档规范,要定义系统软件版本等一系列内容。规范好了之后,大家开始实施。但是在长期运维的过程中,很可能出现随着系统的发展,文档内容已经过时了,工程师又来不及更新文档的问题。怎么解决?docker 给出的答案是:用 dockerfile。dockerfile 就是你的文档,并且用来产生镜像。要改变 docker 镜像中的环境,先改 dockerfile,用它产生镜像就行了,保证文档和环境一致。那么现实是,有多少在使用 docker 的人是这样用的?你们是不是嫌这样麻烦,于是干脆直接在线 docker commit 产生镜像,让文档跟现场环境又不符了?或者我还是太理想,因为你们压根连文档都没有?
其次,标准化要有对应用统一操作的方法。在现实中,即使你用的是 php 开发的应用,启动的方式都可能不尽相同。有用apache 的,有用 nginx 的,还有用某种不知名 web 容器的,甚至是自己开发 web 容器的。如果操作范围扩大到包含 java 等其它语言,或数据库等其它服务,那么操作方式更是千奇百怪。虽然 UNIX 操作系统早就对此作了统一的规范,就是大家常见的把启动脚本放到 /etc/rc.d 中,SYSV 标准中甚至规定了启动脚本该怎么写,应该有哪些方法。但是绝大多数人不知道,或者知道了也不这么做,他们习惯用 ./start 作为自己业务启动的唯一标准。甚至 ./ 是哪个目录可能都记不住。于是 docker 又给出了解决方案:我压根不管你怎么启动,你自己爱咋来咋来,我们用 docker start 或 run 作为统一标准。于是 docker start 可以启动一个 apache、nginx、jvm、mysql 等等。有人病垢 docker 的设计,质疑它为什么设计上一个容器内只给启动一个进程?这就是原因:人家压根不是为了给你当虚拟机用的,人家是为了给启动生产环境的进程做标准化的!
第三,为了维护生产环境的一致性和配置变更的幂等,docker 创造性的使用了类似 git 管理代码的方式对环境镜像进行管理。于是:
- 你想做库版本升级吗?更新个镜像吧!
- 你想做 php、java 的版本升级吗?更新个镜像吧。
好方便!太爽了!
等等……神马?你想改变 apache 配置文件中的一个字段?做个新镜像升级吧!你的 php 代码写错了一行要改个 bug?做个新镜像升级吧……
在一群人吐血三升之后,于是有人出了个主意。唉,其实后两种需求没必要这么麻烦,有一种软件叫做 puppet、chef、salt、ansible、rsync ……
于是我们要在 docker 中启动一个 puppet。什么?你要用 ansible?好吧,我们来看看怎么在 docker 中启动一个 sshd?我有个计划任务要跑,起个 crontab 可以么?
你的 docker 是不是就这么变成了“虚拟机”的?
不过请注意:我并不是说 docker 不好,只是你是否真的评估了它标准化的方式是不是适合你的业务场景?锤子是用来砸钉子的,但是你非要用它来砸手指,我也没什么办法。
作为一个工程师,而且是受过专业训练的工程师,总是想设计出一套工具满足所有场景需求。因为工程师所受的思维训练是:你越是解决了更普遍的问题,你所创造的价值就越大。但是请搞清楚,这个任务一般是由标准委员会来完成的,每个工程行业都会有这么个组织来做这件事情。当然,不排除商业公司的产品可以深刻影响标准制定的情况。那么我们这些工程师最大的价值是什么?摆正自己的位置,看清自己的问题,帮小组所在的企业进一步提高效率,提高竞争力。每个企业都有其历史和当前特点,就运维工作来讲,根据企业的实际情况找到其标准化的最经济有利方式才是我们这些受聘用的职业工程师的核心价值。软件选型要要因地制宜,而不是跟风炒作。当然,如果你的核心价值是想要站在“技术前沿”,打算一直引领技术潮流,做一个出没于各大技术交流会的新技术吹牛逼者,并以此抬高自己身价的话,那我的话自然是对你不适用的。(说这话可能会得罪很多人,我要解释一下:对于那些真诚的想要分享自己技术,希望为社区发展做贡献的人,我是怀着深深的敬意的!谢谢你们!)对待新技术,大多数工程师的状态是:测试是为了上线的,测试出的问题都是要解决的而不是用来评估的,不上线就没有工作成果。我认为工程师对待新技术应有得态度是:激进的用新技术新方法来做线下测试,认真的总结评估测试流程和结果和现有环境的异同,保守谨慎的评估决策新技术是否在业务上大规模使用。
docker 是银弹么?真的能像集装箱那样改变世界么?我的看法当然不是。即使集装箱,也不能解决一些特殊的运输问题,比如大型飞机零部件的运输,或者小件零散商品的运输。如果说云计算行业真的要出现集装箱的话,那么首先这个行业要被几大云计算厂商瓜分完毕,市场成熟之后才有可能。为什么?因为让一个应用可以在任何地方跑的需求,主要应该来自云的用户,他们可能为了稳定性考虑既租用了阿某云,又租用了腾讯云(纯广告,自己所在的公司,所以请勿吐槽),还可能为了海外市场还用了某马逊云。这时用户会有需求说,我想要这些云的环境标准一致,以便我的应用可以在哪朵云上都能跑(Build,Ship,and Run Any App)。而现在,云计算市场刚刚起步,群雄逐鹿,正是差异化发展争夺用户的时候。出了云计算厂商外,其它公司的 IT 环境都不一样,标准化要求也就不可能一样。那么你觉得 docker 这个标准可能适合所有人么?
如果你用过了 docker,并且还觉得它非常合适你的环境,那么我希望你能回答这几个问题:
- 你的 docker 是用 dockerfile 产生的镜像还是直接 docker commit?
- 你的 docker 里面跑了多少个进程?
- 你的 docker 是当虚拟机用的么?
- 那么你用的是 docker 么?
最后,送大家一个段子,希望能博你一笑。
工程师:“嘿!有人发明了一个叫做集装箱的东西,这东西一定可以使运输成本大大下降!甚至改变世界!”
用户:“好兴奋!这东西可以运输我的波音787客机么?“
工程师:“额。。不能整个运,需要拆开再运,因为我们要符合集装箱的标准……”
用户:“那这东西可以运输我的空客380嘛?”
工程师:“额。。我们讨论的是同一件事情。”
用户:“不行是嘛?那不能改造一下集装箱让它可以运嘛?”
工程师:“额。。。这不仅仅是我们的问题,要到达运输目的地还要经过铁路,公路,他们可能也无法……”
用户:“真的不能改造集装箱么?可这东西是以后的发展方向啊!未来的世界都是应该是集装箱运输的!”
工程师:“额……”
老板:“嗯!这东西说不定真的是未来的发展方向!我们一定要实现用集装箱运输这些飞机!工程师们,你们赶紧去攻克这些技术难题,早日可以实现我们用户的特殊需求!让集装箱可以达到我们的业务要求!快去吧!加油啊!”
工程师:“额……”
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/54483.html