月初,一篇题为《Docker 公司已死》的文章,预言了 Docker 公司将在 2018 年的某个时候不复存在。就这一观点,紧接着出现了一篇《Docker 公司不会死》的文章进行了反驳。
Docker 公司已死 !
Chris Short 在《Docker 公司已死》中写道,对于 Docker 公司而言,将 2017 年形容为艰难的一年恐怕都有些轻描淡写。
事实上,除了 Uber 之外,真的想不到其他哪家被沸沸扬扬的炒作新闻所包围的硅谷初创企业会像 Docker 这样经历糟糕透顶的一年。
未来的人们在回顾 Docker 公司的发展历程时,会将 2017 年视为这家重要软件公司被糟糕商业惯例所摧毁,并最终走向灭亡的起点。
Docker 是款好软件
需要明确的是,Docker 公司确实在软件开发的这一波革新当中发挥了重要作用。能够将 cgroups、命名空间、进程隔离等 Linux 原语纳入至同一工具当中绝对是个了不起的成就。
Docker 的崛起使得开发环境最终转化为一个简单且具备版本控制能力的 Dockerfile。
它的工具链将 Packer、Vagrant、VirtualBox 以及其他多种基础设施共同转移至 Docker 阵营当中。Docker UI 实际上也做得相当出彩!
Docker 硅谷的新宠儿
Docker 公司的早期成功使其快速以产品为核心建立起一套庞大的社区。此外,快速发展同样带来了极为顺利的资金流引入。
高盛、格雷洛克风投、红杉资本以及洞见风投等纷纷为 Docker 公司提供大量资金。截至目前,Docker 公司的融资总额已经达到 2.42 亿到 2.5 亿美元之间。
虽然产品本身的质量值得肯定,但公司遭遇了一系列人力资源失误。更遗憾的是,很多硅谷宠儿都存在这样的问题,且显然有必要作出改变。
Kubernetes 对 Docker 造成冲击
随着 Kubernete 的兴起,Docker 公司的厄运可谓加速降临。Docker 公司一直未能找到应对开源社区容器编排新宠 Kubernetes 的好办法。
Docker 公司旗下的 Docker Swarm 是其所拥有的唯一容器编排工具。尽管 Kubernetes 率先向 Docker 容器示好,但 Docker 仍然拿出了自己的竞争性方案。
而且根据记录,Docker 方面曾在 2017 年年初通过文章、会议乃至其他大型活动对 Kubernetes 表达不满。
但通过本届于奥斯汀召开的 DockerCon 17 大会来看,Docker 方面突然决定全力支持 Kubernetes。
这种突然的变化显然是承认了 Kubernetes 的崛起已经不可阻挡。而 Docker 在 2017 年 KubeCon + CloudNativeCon 北美大会上再次陈述此项决定,无疑更进一步强调了这一结论。
Moby?
没人了解 Docker 在去年 4 月的 DockerCon 17 大会上到底为什么要宣布 Moby。
Moby 据称属于 Docker 项目的新上游,然而考虑到事前毫无先兆,因此当 Solomon Hykes 在 DockerCon 17 大会上加以宣布时引发了大范围的震惊与争议性情绪。
为了解决这波冲突,GitHub 方面的工作人员甚至选择直接加以干预。Moby 部署的处理工作仍然困扰着从来者们,而 Docker 品牌亦可能因此受到损害。
Kubernetes 的冰冷拥抱
Docker 公司对于 Kubernetes 在***一刻才张开的迟到且尴尬的拥抱,代表着其即将遭遇崩溃。问题在于,Docker Swarm 还远远称不上成熟。
事实上,Docker Swarm 产品团队及其少数开源贡献者根本无法跟上 Kubernetes 社区那迅猛的发展步伐。
而且与 Docker UI 一样,Kubernetes UI 同样非常出色。就目前来看,Docker 公司本身似乎正开始沦为一家容器领域中的边缘咨询企业。
阴谋论:Docker 公司知道自己已经没戏唱了。技术人员们决定大规模推出 Moby,并突然接纳 Kubernetes,这些都是为了给自己争取一点喘息之机。 #Docker #DevOps
——Chris Short (@ChrisShort) 2017年12月29日
Chris Short 最终得出结论:Docker 公司的真正问题在于缺乏连续的领导。在该公司当中,每一任***都拥有自己的战略重点设定。
这种断代性虽然距离公司的核心越来越远,但却仍然存在。很明显,Docker 是在自取灭亡。
Docker“生死”记,这条船还能开出去多远?
Dylan Chris 在《Docker 公司不会死》中写道:虽然 Chris Short 的一些观点是对的,但 Docker 并不会这么快就退出舞台。
Docker 当然是款好软件
将 cgroups、命名空间、进程隔离等 Linux 原语纳入至同一工具当中,Docker 绝对是个了不起的好软件。
Docker 的简单界面降低了非管理员的入门门槛,允许开发者社区随手将其添加到他们的工作流程中。
Docker 发布了 EE / UCP,一些大型企业也加入进来。这对于开发人员、中小型企业和大型企业来说 Docker 都是一款很好用的软件,而且 Docker 也不会放慢开发的速度。
Docker 有朋友
微软 Kubernetes 的***工程师 Brendan Burns:“我很高兴欢迎 Solomon 和 Docker 加入 Kubernetes 社区”。在谈到 Docker 时很多人都会引用这个声明,认为这对 Docker 来说是一个很大的打击。
但谈到这一点的真正目的是谈论公司之间的合作,并不是纠结于“到底是谁加入谁的社区”。
我们“需要一个村庄一起来养一个孩子”,这个村庄由来自世界上许多大公司的一些最聪明的工程师组成,他们都在努力使 Docker 变得更好。Docker 和 Kubernetes 的合作,对 Kubernetes 与 UCP 来说都非常有意义。
Docker 有业务
Docker 公司不会被收购或闭门。Docker 并不缺领导,也有大量的资金,营销方面也不错,所有的迹象都意味着这家公司正在迅速成长,正在进入企业市场。但成长得并不容易。他们的“现代化企业应用”口号是***的。
这是一个基于 OSS 的公司,市场上有着大量的机遇。虽然 Iron 的其中一款产品是基于 Docker 的,但我们也会大量使用来自 OSS 公司的各种软件,也很乐意为 OSS 软件提供更高层次的支持和功能。
对于其他项目,我们经常通过 Open Collective 捐赠来帮助维护人员和小型开发团队。Docker 对 containerd 的捐赠是一个很好的举措,这是一个完全符合 CNCF 章程的项目。
虽然 Docker 正在向“上流社会”移动,但他们并没有抛弃真正的用户:开发人员。总之,Docker 公司有很大的增长空间,而在 2018 年,它将持续实现增长。
随后近期又出现了一篇“2018 疯狂微服务之死”的阴谋论文章,详细内容如下:
2018 疯狂微服务之死
近期微服务的话题非常火爆,有时可谓非常“疯狂”:
Netflix 在 DevOps 上做得很棒,同时 Netfix 也采用微服务。因此:如果我也用微服务,那么我也可以在 DevOps 方面做得很好。
很多情况下,为了解决手头的问题,我们付出了巨大的努力采用微服务模式,但是并不清楚它的成本和收益。
接下来我将详细介绍什么是微服务,这种模式吸引人的原因,以及它所面临的主要挑战。
如果你正在考虑微服务是否适合你的模式,我会在文章的***用一系列简单的问题来帮你做出选择。
微服务为什么如此受欢迎?
什么是微服务,它为什么如此受欢迎?首先从最基本的开始了解。下图是一个假想的视频共享平台的实现方式,左侧是传统的整体式架构(单个巨型单元),右侧则是微服务:
两种模式的区别在于***种是整体式架构,只有一个大单元。第二种则由多个小单元构成,每个小单元都是独立的服务。上图已足够细致,从中很容易找到微服务模式的吸引力所在。
以下是微服务架构的具体好处:
- 独立开发:小型的独立组件可由小型的独立团队构建。一个小组可以专门负责开发“Upload”服务,不用去管其他服务。每个组件的功能变得简单,这样一来,开发人员了解组件的时间大大减少,更容易开发新功能。
- 独立部署:每个单独的组件都可以独立部署。这样一来发布新功能的速度就更快,风险也更小。假设“Streaming”组件修复了 Bug 或者新增了功能,那么部署时并不会影响其他组件。
- 独立扩展:每个组件可以独立地进行扩展。在新节目刚发布的繁忙时期,可以扩展“Download”组件,以支持增加的负载,而不必扩展所有组件,这样一来扩展更具弹性并且降低了成本。
- 可重用性:每个组件各自实现一个小的、特定的功能。这意味着它们可以很容易地适用于其他系统、服务或者产品。“Transcode”组件可以被其他业务单元使用,甚至可以改写成一个新的业务,从而为其他组提供转码服务。
从以上细节层面可见,微服务模式相比整体式架构的好处显而易见。如果确实是这样的话——那为什么这种模式最近才开始流行呢?
微服务为什么没有很早就开始流行?
既然微服务好处多多,为什么没有很早就开始流行呢?原因有二:
- 它提升了我们的技术能力。
- 最近的技术进步让我们能够把它带到一个新的水平。
当我开始写这个问题的答案时,发现一两句话无法解释清楚,所以实际上我把它分成了另外一篇文章,稍后再发表。
因此在本文中,我将跳过从单个程序到多个程序的过程,忽略 ESBs 和面向服务的体系结构、组件设计以及有限的上下文等内容。
在很多方面我们已经开始使用微服务,随着近期容器技术(特别是 Docker)和集群技术(如 Kubernetes、Mesos、Consul 等等)的普及,从技术的角度来看,微服务模式变得更加可行。
如果我们打算实施微服务,那么在开始之前需要想清楚。从理论的角度我们看到了它的优点,那么它有没有弊端呢?
微服务有什么问题?
微服务模式优点多多,那么它的缺点是什么呢?据我所知它主要有下列问题。
开发的复杂性增加
对于开发者来说事情会变得更加困难。当开发人员开发一个新功能时,如果该功能依赖其他服务的话,那么开发人员不得不在他们的机器上运行所有服务,或者连接到这些服务。这通常比简单地运行单个程序更加复杂。
这个问题可以通过一些工具得到部分缓解,但随着构成系统的服务数量的增加,开发人员在整个系统运行时面临的挑战也越来越多。
运营的复杂性增加
对于维护服务的团队来说,潜在的复杂性是一个巨大的挑战。他们管理的服务不是简单的几个,而是数十、数百甚至数千个正在运行的服务。服务数量越多,通信链路就越多,那么出错的可能性就会变大。
DevOps 的复杂性增加
以上两点表示开发和运营是分开进行的,随着 DevOps 的普及(我是 DevOps 的忠实粉丝),DevOps 能够缓解这个问题吗?
如今有许多组织仍然依靠独立的开发和运营团队来工作,而也有一些组织更倾向于采用微服务。
对于已经采用了 DevOps 的组织来说,这仍然很难。既是开发者又是运营者已经非常艰难(但是要建立好的软件却很关键)了,还得了解集群容器系统的细微差别,特别是快速发展的系统,那就更困难了。
它需要资深专家
如果开发团队成员都是专家级别,那么结果可能会很好。但想象一下,一个使用单一的整体式系统运行的不是很顺畅。如果增加系统的数量,就会增加运行的复杂性。
通过有效的自动化、监控和集群等技术可以做到。但瓶颈很少在于技术本身,而在于找到能够有效使用这些技术的人。目前这些技能需求非常高,可能很难找到。
真实世界的系统往往界限不清
当我们描述微服务的好处时,经常谈到独立的组件。但是在很多情况下,组件并不是独立的。在论文中,某些领域可能看起来有限,但是当你深入细节时,你会发现他们比你预期的更具挑战性。
事情变得非常复杂。如果你的界限没有明确的定义,那么即使理论上的服务可以单独部署,你也会发现,由于服务之间的相互依存关系,你必须部署一组服务。
这意味着你需要一系列管理协同工作的服务版本,这些服务版本之间的协作需要通过验证和测试,你实际上没有可独立部署的系统,为了部署新功能,你需要仔细编排并同时部署许多服务。
状态的复杂性往往被忽略
在前面的例子中,我提到一个功能的部署可能需要同时部署多个版本的多个服务。
假设合理的部署技术可以缓解这种情况,例如 blue/green 部署(大多数服务编排平台可轻松应对),或者并行运行的多个服务版本,以及决定使用哪个版本的通道。
如果服务是无状态的,这些技术可以缓解大量的挑战。但是无状态服务非常容易处理。事实上,如果你有无状态的服务,那么我会倾向于考虑跳过微服务,而考虑使用无服务器模型。
实际上,大多数服务都需要状态。比如我们的视频共享平台例子中的订阅服务。新版的订阅服务可以用新的形式将数据存储在订阅数据库中。
如果你并行运行两个服务,则一次运行了两个模式的系统。如果你进行了 blue green 部署,而其他服务依赖于新的数据,那么必须同时更新这些服务,如果订阅服务部署失败并回滚,则需要层级回滚。
你可能会认为在 NoSQL 数据库中这些问题不存在,但事实并非如此。不强制执行模式的数据库并不意味着它是无模式系统。
它仅仅意味着模式在应用级而不是数据库级进行管理。理解数据的形状及其演变过程的挑战依然存在。
通信的复杂性往往被忽略
当你建立一个相互依赖的大型网络服务时,可能会涉及到很多服务间的通信,挑战随之而来。
首先,潜在的失败无处不在。假设网络调用失败了,那么当一个服务调用另一个服务失败时,它至少应当重试几次。服务之间的调用关系越多,那么情况将变得愈加复杂。
假设用户上传视频到共享服务中。那么我们需要运行上传服务,然后将数据传递到转码服务,此外,还得更新订阅和推荐服务。所有这些调用都需要一定程度的协调,如果失败,就得重试。
而重试逻辑可能很难管理。同步运行往往不是很稳定,很容易失败。在这种情况下,更可靠的解决方案是使用异步模式来处理通信。
此处面临的挑战是异步模式会使系统具有状态性。如前所述,分布式系统和状态系统很难处理。
当一个微服务系统使用消息队列进行服务内通信时,基本上会有一个大的数据库(消息队列或代理)将这些服务粘合在一起。虽然起初看起来似乎没什么问题,但模式始终是一个隐患。
新版本的服务可能会写入新的格式的消息,当发送服务更改发送消息的详细信息时,依赖于该消息的服务也需要更新。
当然可以拥有多个不同格式的消息处理服务,但数量一多就很难管理。当部署一个新版本的服务时,两个不同版本的服务可能会处理来自同一队列的消息,尽管消息来自不同版本的发送服务,这可能会导致复杂的边缘情况。
为了避免这些边缘情况的产生,***是只允许特定版本的消息存在,这意味着你需要将一组服务的版本作为一个整体来部署,以确保先前版本的消息被适当地排除。
这再次表明,当你深入细节时会发现独立部署的想法可能与预期的有所差异。
版本控制变难
为了缓解前面提到的问题,我们需要谨慎管理版本。遵循像 Semver 这样的标准能够解决这个问题吗?答案是否定的。
Semver 是一个利器,但是你仍然需要跟踪协同工作的服务和 API 的版本。
这件事颇具挑战,你可能自己都搞混,不知道哪个版本的服务可以一起正常工作。
在软件系统中管理依赖关系是非常困难的,无论是节点模块、Java 模块、C 库还是其他东西。独立组件和单一整体之间的冲突很难处理。
当依赖关系是静态,并且能够进行修补、更新、编辑的时候,挑战在所难免。但是如果依赖关系本身是实时服务,那么你可能无法仅仅更新它们 - 你可能需要运行许多版本,或者直到整个系统得到修复。
分布式事务
在需要跨操作交易完整性的情况下,微服务可能会非常痛苦。分布式状态很难处理,很多小的失败单元可能会很难进行集群操作。
可以通过操作幂等性、重试机制等方法来避免这个问题,这些手段在许多情况下能够起作用。
但有些情况你需要保证操作的事务性,要么成功,要么失败,而不能处于失败和成功的中间状态。在微服务模型中想要解决这个问题或者实现事务难度是很大的。
微服务可能是一种变相的整体式模型
单独的服务和组件可以独立部署,但是在大多数情况下,你将不得不运行某种集群平台,比如 Kubernetes。
如果你使用谷歌的 GKE 或者亚马逊的 EKS 这样的托管服务,它们会帮你完成复杂的集群管理。
但是,如果你自己管理集群的话,那么面对的是一个庞大而复杂的系统。虽然单个服务拥有前文提到的大量优点,但是你依然需要非常小心。这个系统的部署、更新、故障转移等等操作起来都不是那么简单。
在大多数情况下,优点能够得到体现,但是仍然不要轻视或低估管理一个庞大而复杂的系统的难度。托管服务可能会有所帮助,但这些服务大都刚刚新起(例如,亚马逊的 EKS 在 2017 年底才发布)。
微服务的狂热将开始降温
仔细考虑避免加入对微服务的狂热追捧。为了帮助解决这个问题,我已经注意到了一些你可能想问自己的问题,并列举了问题的答案:
- 点击下载 PDF 版本:microservice-questions.pdf(https://github.com/dwmkerr/blog/raw/master/2018/microservice-madness/images/microservice-questions.pdf)
不要把微服务和架构混淆
没有微服务架构一说。微服务只是组件的另一种模式或实现。不论微服务是否在系统中使用,它都与架构无关。
微服务在许多方面与打包和操作的技术过程有关,而与系统设计无关。组件边界仍然是工程系统中最重要的挑战之一。
无论你的服务体量有多大,是否在 Docker 容器中,你都需要仔细考虑如何将系统放在一起。这里没有标准答案,只是多一个选择而已。