Docker:一场令人追悔莫及的豪赌
本文转自 | 编程无界
【编者的话】:
Docker纵然有其优势,但其背后亦存在大量设计不合理之处。这篇文章旨在阐述Docker的种种弊端,并指出相关依据。
每当我对Docker提出批判时,都会收到很多愤懑的回复。我曾于6个月前撰写一篇文章,即《为什么有人会选择Docker而非大型二进制文件?》,并终于在Hacker News上众多愤慨的批评声中看到了一些明智的评论。因而,今天的这篇文章主要是进一步阐述Docker的设计缺陷并回应未来可能将会面临的批判。
相比HFT Guy的经历而言,我想我已经足够幸运了。HFT Guy曾满腔怒火地表示,由于在金融公司的产品生产阶段使用了Docker而导致失败,想来其必然为此付出了不小代价。原文引用如下:
我收到了一份十分无礼的邮件,发件人明显是业余社区中的一员。这位仁兄在邮件中愤怒地表示:"白痴才会在Ubuntu上运行Docker。"该邮件中还随附了一份软件程序包列表以及在Ubuntu上运行Docker所需的高级系统调整方案。另外,这封邮件还特地表示:"任何人都可以通过谷歌在5秒内找到列表中的相关内容。"
人们倾向于在网上发泄其愤怒--尽管我不知为何,但事实的确如此。并且,当开发人员发现有人抨击其所深爱的技术时,往往会奋起反击,进而引发一场口水战。然而,这种不良情绪蒙蔽了他们了双眼,以至于其无法辨识相关方案有关现实使用方面的长远意义。
Docker承诺其能够提供可移植性、安全性以及资源管理与编排能力。因此,理智的人们自然希望了解:"Docker是否真的是获取可移植性、安全性以及资源管理与编排能力的最佳方式?"
在此之前,我想先回应我所收到的部分回复。尽管大部分回复中所持有的观点根本不值得讨论,但有一个论点引起了我的注意--我将在文末对其详加阐述。
有评论如下:
由于使用Docker所涉及的资源较少,并且与是否需要对相关资源进行处理以及使用方现有的处理能力无关。
是的。但参考对象又是什么呢?是让开发人员编写脚本以实现标准化构建、部署、编排以及资源使用吗?上述评论似乎想要表达的是"我并不是说开发人员应该选择这类操作,因为结果已经客观存在; 我的意思是希望其能够实现标准化。"
开发人员与管理人员偏爱Docker的原因无外乎其所提供的功能自定义空间有限、相对不那么混乱、更长久且更加标准化--或者起码存在实现这类效果的机会。然而事实上,Docker迄今为止带来的只是一团令人难以置信的乱麻(更多详细信息请参考:《生产阶段的Docker:一段失败的历史》)。尽管如此,仍然有很多人愿意相信目前Docker所存在的问题不久即可得以解决,并且届时Docker就能够为容器化场景提供稳定且一致的标准。这无疑是一场关于Docker的豪赌!几乎所有参与这场"赌博"的公司都为此付出了惨重的代价,但仍然有公司继续为此投注,以期有朝一日能够由此获取丰厚的回报。
在过去的两年时间里,我曾合作过的每家公司不是在使用Docker,就是在拟定有关使用Docker的计划。实际上,这些公司都为获取标准化解决方案付出了高昂的代价。
更可怕的是,我还没有听到任何一位技术管理者明确对这种"赌博"现状作出陈述。大多数支持Docker的群体仍在不断强调其带来的可移植性、安全性或者编排与配置能力。没错,Docker确实能够为我们提供可移植性、安全性或者编排与配置能力,但其代价也相当可观。在大多数情况下,编写特定脚本反而难度更低。
在我个人认为最出色的Docker论述文章当中,作者强调了使用Docker所带来的利弊权衡:
最好将Docker视为一种高级优化方案。没错,它很酷且功能相当强大,但其同时也会增加系统复杂性,且只有专业的系统管理员才能够理解如何在生产中安全使用Docker并将其部署在关键性任务系统之内。
就目前来看,您需要掌握更多系统专业知识才能使用Docker。事实上,几乎所有Docker相关文章都只展示过分简单的用例,而忽略了在多主机生产系统上使用Docker所带来的复杂性挑战。这无疑给人们留下了Docker的实际生产应用非常简单易行这一极为错误的印象。
在计算机编程领域,流传着这样一句至理名言:
"不成熟的优化是万恶之源"。
然而,今年以来我们的大部分客户都坚持
"我们必须从起步阶段就全部实现Docker化。"
因此不同于传统最初最佳实践要求的建立一套工作系统、将其投入生产、最后考量Docker能否带来比较优势的作法,客户们开始盲目推动Docker的标准化开发与部署。
可能很多朋友都遇到过以下场景:
我:"我们不需要在项目早期使用Docker。"
对方:"这款应用需要Nginx、PostGres以及Redis和一大堆环境变量。如果不用Docker,要怎么进行设置?"
我:"我可以写个Bash脚本、用make命令,或者使用其它类型的安装程序。反正方案多种多样,这么多年来我们一直都有办法。"
对方:"这简直是疯了。Bash脚本有可能中断,你就得花时间调试;而且跟容器相比,它不一定能在其它机器上正常运行。使用Docker,我们可以编写build脚本,而且保证它能够在任何一台机器上正常运行。"
很明显,这就是典型的销售代表场景--他们只会强调Docker最吸引人的特性。作为一款开发工具,Docker看起来确实拥有更出色的一致性水平,而且不像其它方案那么混乱。但在实际使用过程中,特别是在生产环境当中,Docker带来的往往只有痛苦。
您的开发团队可能拥有一位使用Windows机器的开发者、一位Mac用户、一位已经安装Ubuntu的开发者,外加一位使用红帽Linux的开发者。对于身为团队负责人的您来说,对他们使用的机器进行全面控制几乎是个不可能完成的任务。而乍看之下,Docker似乎能够确保在各类平台上提供相同的开发环境。(但这里我要提一句,千万别在Windows环境中使用Docker--任何告诉你Docker能够简化Windows机器开发流程的家伙都是在给你挖坑。)
但在实际生产过程当中,您将能够完全控制生产环境中运行的机器。如果您希望在CentOS上实现标准化,完全没有问题。您可以掌控数千台CentOS服务器,并利用旧有技术(例如Puppet)确保这些服务器拥有同样的运行环境。这意味着Docker并没有传说中那么重要。相比之下,在利用Docker进行开发时,开发人员往往会认为实际生产环境也将由Docker构建而成--但事实并非如此。
我当然可以列举更多与Docker问题相关的实际案例,但这些例子真的非常无聊。目前已经有大量博文在讨论Docker设计缺陷,相信您对这些已经有所耳闻--除非您身为Docker铁粉,而且对一切反对意见都视而不见。对于这部分朋友,他们会直接忽略此类文章,或者在勉强读完之后表示"Docker生态系统正在迅速发展成熟,相信到明年其就会非常稳定且适合用于实际生产。"这样的话在过去五年中每年都会出现。没错,也许这样的论断最终会变成现实,但回到开头--这是一场危险的豪赌。
尽管Docker存在上述问题,但其似乎仍然获得了成功--与我们使我几乎每家企业都渴望投向Docker的怀抱。为什么?据我所知,标准化是其中最为核心的理由。
再次强调,在发表于Hacker News上的文章的评论中,网友"friend-monoid"这样评价Docker:
我们拥有大量以不同语言编写而成的HTTP服务。以[超级]二进制方式对其进行整体管理是件苦差事--编写者必须提供一种用于端口设置及地址监听的方案,而我必须追踪每一种端口设置方式。有了net命名空间与更智能的iptables路由,Docker能够帮助我完成这项任务。
网友notyourday则给出了深得我心的回应:
当然,如果你采用其它方法并且遵循同样的编写方式与规则,也能达到同样的效果。事实上,后者的效果可能更好,因为其会提供更智能的命名空间与iptables,甚至允许你完全不用分心于应用程序的运作状态。
网友anilakar回应notyourday道:
在我看来,这正是Docker技能具备可转移性的核心所在。也就是说,如此一来,刚刚招聘的新人也能够很快上手新工作。很多企业仍然在使用能够切实满足基业务需求的构建/部署系统,但却无法提供能够在企业之外继续发挥作用的实用经验。
据我所知,这基本总结出了Docker的真正优势所在。没错,Docker的优势根本不在于能够让应用的部署、安全保障或者编排变得更加轻松--这完全 就是无稽之谈。事实上,Docker成为标准的惟一理由,就是人们能够将自己在一家企业中积累到的经验应用于另一家企业。Docker不像自定义Bash脚本那么混乱且独特。然而,这是否值得我们押上一切?
但说句不中听的,我觉得上述争论其实是混淆容器技术与Docker。而且相当一部分Docker支持派是在故意混淆这个问题。容器技术本身确实是个先进的概念,但由单一公司掌控的Docker却不可避免地存在着一定问题。继续来看HTF Guy给出的观点:
Docker不具备商业模式,也无法实现货币化。公平地讲,Docker公司正在以绝望的方式将其推向全部平台(Mac/Windows),并将所有功能特性硬凑在一起(Swarm),从而:
确保任何竞争对手都不具备任何显著的独特性;
确保每个人都使用Docker及Docker工具;
将客户完全锁定在其生态系统当中;
在此过程中发布大量新闻、文章与报道,增加炒作热度;
证明其估值的合理性。
Docker几乎完全不可能面向多种产品及市场进行水平与垂直扩展。(这里我们姑且不论这种扩展是否属于适当或者说可持续的商业决策,这又是另一个议题了。)
与此同时,Amazon、微软、谷歌、Pivotal以及红帽等竞争对手则在以各种方式进行竞争,而且通过容器赚到了远超Docker的回报。事实上,CoreOS也在开发操作系统并凭借其Rocket容器化技术参与竞争。
因此,即使您认同容器技术当中蕴藏的巨大能量,并高度赞扬由其带来的设置一致性能力,也并不同改变Docker本身根基不稳的事实。
好吧,这里我们暂时把Docker和容器看成是同一种东西。在这样的立场之下,我们再来回顾我之前发表的文章,看看其中哪些批评意见仍然符合现实。
我在前文当中错误地使用"大型二进制文件"这样的表达,并导致了很多误解。几小时之后,我发布了以下免责声明:
在这篇文章中,我使用"大型二进制文件"来表达一个包含所有依赖性的二进制文件。我的本意并不是指整个32位与64位转换。如果单纯立足Java与JVM领域,我会使用"uberjar"一词。但之所以没有使用,是因为我希望在表述中涵盖值得肯定的GO语言及其生态系统。
如果再来一次我绝对会使用"超级二进制"这个词,虽然它代表着我个人的工作主要集中在JVM领域,但其表意相对更为准确。这已经是我能想到的最好的表达,因此在这篇文章中,我转而使用"超级二进制"的说法。
我希望开发者们能够意识到,他们最喜爱的计算机编程方式可能并不适用于云端分布式计算体系。这里我要反复强调这一点,而且相信很多开发者已经感觉到,云计算体系需要越来越多地适应他们编写的PHP代码、Ruby代码或者是Python代码,而他们却从来不会在代码层面适应这个新的世界。
如果您正在着手启动新项目,并预计其规模将会逐渐增大--您可能需要因此考虑其可扩展性,或者单纯重视高可用性--那么您可以使用专为云环境设计的现代语言。目前,很多新语言都能提供前所未有的新鲜特性,我个人使用过且给我留下深刻印象的有Go和Clojure。我个人对Rust、Scala以及Kotlin经验不多,所以没法讨论太多。当然,它们应该也非常出色(在以往的文章中,很多读者朋友认为我是故意忽略了一些语言。我绝不是故意侮辱这些语言,但限于个人接触范围,我只会提及自己实际使用过的方案)。我读过一些与Scala Akka框架的文章,并发现其中包含不少非常精彩的思路。因此虽然没有实际使用过,但我认为其确实设计水平极高且充满现代感。
在我早前的文章中,网友btown写道:
任何认为一切现代Web应用程序都是使用Golang或JVM开发完成的人,都生活在一种奇怪的自我认知循环当中。
再次强调,很多语言都非常出色; 但我不可能了解所有语言,因此只能对其中一些我亲自接触过的语言作出评价。另外,我也会批评自己曾经使用过的旧有语言--包括PHP、Ruby以及最近人气爆棚的Python。它们源于一种旧有范式工,因此不适用于云端的微服务与分布式架构。我曾在《Docker正保护我们需要尽量摆脱的编程范式》一文中对此进行过探讨。现在看来,似乎大家并没有认真考虑这个问题。我想起2000年前后,面向对象编程掀起的狂热浪潮达到顶峰。那时候,几乎没人敢站出来反对这种模式。科技行业一直认为自身是完全开放的,但实际上其中仍充斥着各类驱动因素。在接下来的几年中,各参与者纷纷退却,留下一地鸡毛与吃瓜群众们的嘲笑声。结合本文的主旨,2000年XML与面向对象编程出现了过度炒作,而如今的Docker亦处于同样的状态之下。
Clojure语言我用得比较多,而其似乎非常适合用于编写应用程序并创建绑定依赖关系的uberjar。我也很清楚如何建立起像Jenkins这样的系统,因此我的Clojure build完全能够实现自动化运行。我听说很多企业选择了令人难以置信的极端路线,其在构建无外部依赖关系的应用程序时,会将数据库等全部绑定在uberjar当中。请参考《利用Clojure与AWS在7个月中实现600倍增长》一文中的内容:
这推动了决策二的出炉。由于数据集体积较小,因此我们能够将整个内容数据库添加至我们的某一版本当中。没错,您没看错。我们利用Solr的一个嵌入式实例构建我们的软件,并采取标准化、清洁化非关系数据库作为酒店库存管理方案,并将其共同塞进应用程序部署方案当中。
我们利用这种非传统处理方式得到了巨大收益。首先,我们消除了重要的故障点--即代码与数据间的不匹配问题。任何版本的软件都将能够正常工作--即使多年后我们将其转移至其它系统当中,且在此期间对内容数据库作出各类改动,都不会影响这一结果。在这种情况下,针对不同环境的部署与配置管理工作变得极为轻松。
其次,我们在面向用户层中实现了横向无共享可扩展性。其扩展能力相当相当可观。
如果不需要引入新技术(例如Docker)就能实现这种大规模扩展,那么当然没必要多此一举。以最简单的方式解决问题才是我们应当坚持的原则。如果从Ruby/Python/Perl转向新的语言及生态系统,而且能够以更少的技术与移动部件实现规模化,那么大家应当甚至说必须采取这样的处理方式。再次强调,我们的原则是尽可能以最简单的方式实现目标,而且在大多数情况下这意味着您应尽可能降低所使用技术的数量。受到Rich Hickey的启发,我将"简单"与"简易"区分开来。使用一门您已经了解的语言非常"简易",学习一门新语言很困难--但后者却更"简单",或者说能够减少系统中的技术总量。这里的"简单"意味着您的系统最终能够以更简单的方式运作--其代码规模更小、配置更单纯或者使用的技术数量更少。
在此前文章的评论当中,不少读者朋友认为我总是提到Jenkins的作法代表着我的心态已经过时--但有时候必须承认,无聊的东西不一定就不好:
无聊的好处(限制水平较高)在于,这些东西的功能相对更容易理解。而更重要的是,我们能够更轻松地了解其故障模式。……但对于闪闪发光的新技术而言,其中的未知因素要多得多,这一点非常重要。
换句话来说,已经存在了十年的软件更易于理解,而且未知因素更少。未知因素越少,运营开销越低,这绝不是坏事。
我意识到,很多开发者都存在着极强的偏见。在阅读这类文章时,他们倾向于揪住一个理由来驳斥整篇文章。因此如果我提到Jenkins、Ansible、Go、Clojure、Kotlin或者Akka等任何技术方案,他们都会专注于寻找这些技术中存在的缺陷,以此将文章本身贬得一文不值。而除了添加免责声明之外,我不知道要怎样才能跟这部分读者朋友真正沟通--事实上,我觉得即使是添加了声明,不想听的读者也仍然不会听。
在之前的文章中,网友tytso写道:
关于Go语言是大型二进制文件先驱的说法很明显是错误的。数十年以来,人们一直在利用静态二进制文件(有时候会配合内置数据资源)解决这个问题。MacOS就是其中的代表。
在这里,我要对自己的表意不清问题表达歉意。我实际上想要表达的是将所有依赖关系、一切必要配置乃至全部必要的资源都塞进同一个二进制文件,从而简化整体系统资源机制的作法。这种实践方式在概念范围上比简单的静态库链接更为广泛。现代持续集成系统可通过配置以确保各二进制文件皆被给予特定配置詶,而这些配置信息可能以惟一方式对应二进制文件的特定实例。因此即使您需要同时运行同一应用程序的上千个实例,亦可构建起上千个在配置方面略有区别的实例变种。当然,您可以使用Jenkins这类相对陈旧的构建系统完成这项任务。这些系统易于理解,但在另一方面也确实比较无聊。但无聊不应该成为您选择Docker的理由--其可能带来可怕的复杂性挑战。(当然,请别纠结于我在这里将Jenkins作为例子的情况,大家也可以根据喜好选择Travis、TeamCity或者Bamboo。我常常惊讶于很多开发者居然会因为一种方案的选择而放弃对整篇文章的认同甚至是阅读。)
有些读者表示:
Docker能够保护用户免受云服务供应商锁定问题的影响。
当然不是。任何一款标准化部署DevOps工具都能帮助我们解决供应商锁定问题。而且,这类工具选项可一点都不少见:
网友friend-monoid 写道:
如果我的同事无需了解如何正确部署应用程序,那么他们的工作内容将得到显著简化。如果我可以将他们的工作成果放进容器当中,而无需因语言或风格而受到影响,那么我的工作内容也将得到显著简化。我不必再为处理崩溃、无限循环或者其它代码错误而分神。
网友notyourday的回应则与我的态度不谋而合:
当然了,因为你只是把这套逻辑搬到了"编排"与"管理"层当中。你仍然需要编写代码以正确执行。就算给猪画口红,猪也仍然是猪。
更何况,如果您身在一家小公司,而且开发人员总共只有几个人,那么将不可避免地处理彼此的代码结果。而如果您身在大型企业,那么其中将具有独立于开发团队之外的DevOps团队--他们多年来一直专注于处理此类问题,包括利用各类健康状态检查方案。健康检查同样涉及代码编写,Docker的标准化范围并不能涵盖这部分工作。作为应用的开发者,您需要创建对应端点,从而将200条响应发送给DevOps以进行定期测试。在这种情况下,Docker实际上起不到任何作用。大部分DevOps团队都拥有专门用于测试应用程序是否活动的脚本,如果目标应用没有响应,那么其将被终止并重新启动。
网友Lazare写道:
举例来说,我正利用脚本语言(例如Ruby、PHP或者Node.js)构建基于旧式脚本模式的现有代码库。
.……我可以考虑如何将全部现有代码打包进Docker容器当中,并配合一些编排方案,而后进行发布。
根据这篇文章,我发现作者认为用(超级)二进制文件的效果更好。但情况是这样的:您可以对PHP应用程序进行Docker化,这并不困难。但我们要如何构建起(超级)二进制文件?如果你的答案是"用Golang重写整套代码库",那这显然毫无意义;我们首先没有足够的资源完成这项工作,其次就算这样做了,我们也不打算采取这种毫无性价比可言的方法。最后,无论如何,我们都不喜欢Golang语言。
在这个例子当中,这家企业长久以来一直在使用PHP应用程序,现在的目标则是对该应用程序进行Docker化。为什么会有这样的结论?发生了哪些变化,导致该应用程序需要进行Docker化?这就像是一个人为设定的例子。在Docker化之前,您的应用程序运作情况如何?旧有方法的问题是什么?您觉得Docker能够解决这些问题吗?
这款应用程序的最终目标是否能够与其它(或者其自身的更新版本)应用程序实现编排与协调?Docker加编排通常意味着Docker加Kubernetes。(当然,您也可以选择使用Mesos或者Nomad等来代替Kubernetes)。这是一套非常复杂的组合方案,企业在选择这一道路前应该进行认真思考。请参阅《K8s是否太过复杂?》如果您的应用规模不大,那么对其进行整体重写其实是个不错的选择; 而如果您的应用规模庞大,那么您应该思考是否存在其它更为简单的实现途径--例如编写一些Chef或Ansible脚本。
我曾经遇到过一款规模庞大的整体式应用,其以PHP编写而成,且使用到Symfony框架。这款应用出现了糟糕的性能问题。我们开始逐步对其进行拆分--将用于进行HTML模板渲染的Symfony保持原状,而对真正决定性能的部分以其它语言进行重新编写。我在《小型应用的架构问题》一文中已经对此作出了陈述。当时,DevOps团队正在利用Puppet及一些自定义脚本处理部署工作。这对我们来说已经足够了。无聊而稳定的技术,确实能够起到很好的效果。
请记住,您的时间是有限的。无论您投入多少时间对自己的PHP代码进行Docker化,您的时间都被占用了--这意味着您无法利用其完成其它现代化转型。因此,请确保投入能够带来切实回报。
而让人感到奇怪的是,人们在讨论Docker时,往往并不会列举那些真正需要进行编排的应用示例。我见过在Spark上长时间运行的数据分析脚本,其利用Nomad进行编排。我意识到这是一套庞大的系统,其每天都会将数TB数据添加至Kafka当中,而后来到Apache Storm,最后是ElasticSearch。这套系统拥有一套复杂的运行状态检查与监控功能,但对于大部分工作而言,Storm本身就可以充分编排工具。Web应用程序需要在处理海量数据之前,首先处理大量业务流程。Twitter就面对着规模可观的数据,其利用Aurora进行编排。您的规模能够与Twitter相提并论吗?如果您在普通网站上使用Docker与Kubernetes,请马上停下--我们有众多更简单的网站运行方法。我已经拥有长达25年的建站经验,相信我,绝大多数网站都不需要Docker。
网友mwcampbell写道:
"我真的不太赞同投入大量精力保持旧有技术正常运行的作法。"
我强烈反对这部分内容。为了真正在技术与文明方面取得进展,我们需要确保自己不会浪费时间重新创造业已存在的解决方案--换言之,我们应保持旧有技术的运作。因此,如果Docker能够让2007年编写完成的Rails应用正常运行,那实在是太赞了。事实上,我们仍然应该使用Rails、Django以及PHP等开发新的应用程序。即使不再时髦,我们仍有理由使用这些已经非常成熟的平台与工具。
"时髦"这个词不禁让我想到技术领域广泛存在的一种错误认知。我们能不能停止这种对时髦的盲目追捧?举例来说,非要把技术与流行文化混为一谈,就好像是认为摇滚音乐黄金年代出现的一切音乐作品如今都已经没有存在的必要。相反,好的技术并不是流行音乐; 在1993年能够顺利执行的方案,没准也仍然适合如今的需求场景。
这是一条明显属于反话的评论。很明显,自认为清醒的现实主义者认为我们应该把一切东西都Docker化,但像我这样的疯子则认为我们应该继续使用旧有DevOps工具并将其与新型语言加以结合。在其看来,我的选择是受到了"时尚"的驱动,而他们对Docker的热爱则是出于"真正在技术与文明方面取得进展"的伟大愿望。
我的观点是,只要陈旧而无聊的技术仍然能够发挥自己的分内作用,且不会因继续使用而带来额外的成本,我们就应该继续加以使用。但当技术的运行方式发生重大变化时,我们应当自问,某些技术是否已经不再适应新环境的需求。更具体地讲,随着云计算以及云环境下微服务架构的兴起,我们必须重新思考自身对技术方案的选择。其中的指导原则应该是,"我们完成当前目标的最简单方法是什么?"如果旧有技术能够完成目标,而且也属于最简单的方法,那么其就应该是最优选择。但如果新技术能够帮助我们简化系统,那么我们就应该积极接纳这种新方案。
网友chmike写道:
容器不仅是依赖关系的解决方案,同时也能够有效保护边界。
网友neilwilson则回应称:
这只是chroot的花哨强化版。不要相信那么多Docker宣传。多年以来,明智的管理员一直在做类似的事情,只是我们不会花大价钱进行公关推广。
这也代表了我个人的全部意见。
在前文中,我曾经提问"为什么不使用不存在外部依赖关系的超级二进制文件?"大家可能会回答,"Docker就是这么做的!它就是一个大型二进制文件,其中包含了应用程序运行所需要的一切!而且它还不依赖于任何语言!你可以使用其配合Ruby、PHP、Python、Java、Haskell乃至一切语言!"
说得没错,但我建议企业应该寻找机会减少其使用的技术方案的数量。也许大家可以利用现代语言与生态系统,从而以原生方式实现这种超级二进制设计。
很多人认为Docker的反对者们之所以提出批评,是因为其没有能力变更其所在企业中的技术方案。但我们的假设是,企业实际上是在自发使用异构混合技术,其中也包括一些不适合在云中以分布式计算实现的旧有技术。因此,Docker其实是一种"隐身咒",其实际作用就是隐藏企业无法调整自身语言与生态系统以适应云端分布式计算架构的现实问题。
从长远角度来看,这种拒不改进的态度会毁掉一家企业。我不造成一味追求科技领域的最新潮流,但我支持不断重新评估最有利于企业自我技术成果。目前,计算的总体实现方式正在发生变化,而被动接受传统应用终将成为企业的痛点,其会随时间推移而拖慢企业的发展速度。而真正到传统应用程序无法继续运行时,重新编写将给企业带来更大的风险。如果企业能够找到方法对现有应用程序进行拆分与现代化转型,那是再好不过。事实上,微服务架构最重要的特色就是其允许旧有应用程序以增量化方式实现现代化。我在《渐进式改善的珊瑚礁模式》一文中已经谈到过这一点。
在前文中,我提到过一家分析企业,其每天需要向Kafka当中添加上TB数据,而后将其分发至Apache Storm,最后再到ElasticSearch。这家企业长期以来一直使用Python。当遇到性能问题时,他们希望使用Python并发系统(例如Tornado)在其系统中实现大规模并发。他们将这个项目交给一位非常出色的工程师(他此前在英特尔公司效力),并给了他3个月时间进行新系统构建。结果--完全失败。他们无法获得自己希望得到的性能提升,Tornado甚至无法带来他们所期望的细粒度并发能力与并发水平。最后,他们终于接受了这样一个现实--他们不可能在各个层面都始终坚持使用Python。如今,他们开始转向Go与Elixir,并承认这才是能够真正解决问题的办法。(我相信这家企业肯定有点受伤--他们是真正的Python支持者,也是一群理想主义者。)
我对他们采取的重新评估方法表示造成,但我认为企业应该将这一环节纳入运营体系并定期执行。
下面是来自网友pmoriarty的最强Docker支持论据:
你也可以对一切配置管理工具(Ansible/Chef/Salt/CFEngine/Puppet)提出几乎完全相同的批评。它们都是一大堆乱七八糟的产物,起作用时你可以偷着乐,但不灵的时候也会带来可怕的噩梦。
所有这些工具至少还需要几十年才能彻底发展成熟。
是的,说得没错。
需要一套用于运行WordPress的recipe?Ansible能够提供,Docker也可以。同样的,Docker也能够在运行Drupal、MySQL或者无数其它任务时提供这样的帮助。至少在提供DevOps常规需求的默认设置方面,Docker的表现确实不错。
如果Chef或者Ansible能够发展得更成熟,那么我们今天也就不需要围绕Docker展开如此激烈的争论了。据我所知,一家初创企业曾在2013年专注于为Chef构建框架(他们希望自己的框架能够成为DevOps领域的Ruby on Rails)。他们遇到了一些问题,并在过程中发现其它更加有利可图的发展方向。最终,他们分神了,也失败了。尽管如此,他们未完成的工作可能终有一天会成功。这样的框架将具有直接依赖操作系统功能的优势,而无需像Docker那样彻底掩盖掉底层操作系统。
Chef与Ansible都曾经承诺为所有潜在的机器类型与一切常见的DevOps任务提供数千套脚本。很明显,二者一直都没能完全实现承诺。2005年,每家企业都会有一名DevOps人员为公司内的所有DevOps任务编写定制化脚本--这似乎非常正常。但到2010年,明显应该出现更为集中的常规任务脚本库,其具体程度应该高于Perl CPAN库,且高度关注资源管理与编排层面的一致性问题(以实现可移植性)与安全性问题。也是从这时开始,Chef快速飞腾,Ansible随后赶上,Docker也在几年后奋起直追。很多开发者认为Docker最终带来的正是Chef与Ansible长久以来承诺但却未能实现的效果。但长久以来,Docker一直只适用于内部开发工作。直到2015年,在生产环境中使用Docker仍然无异于自杀。即使是在2016年,试图利用Docker支持生产系统的企业仍然遭遇到痛苦的枷锁。而这一切在过去一年中,仍然没有出现显著改观。
在我看来,Docker有朝一日将被定性为一个巨大的错误。其中最强有力的论据在于,即使最终成为标准、始终最终发展成熟,Docker也只是为科技行业目前遭遇的种种难题贴上一张"创可贴"。由于缺少治本的能力,Docker的命运不可能迎来良好的结果。
我怀疑,从现在开始的五年之后,将会出现一种复杂度更低的方法实现云端分布式计算的标准化--请大家与我一道见证这一猜想。当然,就目前来讲,Docker仍然无处不在且人气爆棚。
后话
就如作者所言,很多时候,开发者对Docker的态度是因为新技术的潮流而趋势若骛,为了使用而使用,为了时髦而时髦,虽然如此,我们依然抵挡不住对新事物的狂热,我们依然希望能够学会,希望能在自己的项目,甚至是所在领域尝试使用它,个人觉得,也无可厚非,毕竟技术是不会被限定某个规则之内的,只要你觉得它合适用在你的项目中,他能给你带来效率或者性能的提升,它就是合适的。