企业迁移到云生应用架构时所需做出的变革

本文译自Migrating to Cloud Native Application Architectures第二部分,归档到https://github.com/rootsongjc/migrating-to-cloud-native-application-architectures

在变革中前行

从客户给我们下达订单开始,一直到我们收到现金为止,我们一直都关注时间线。而且我们正在通过删除非附加值的废物来减少这个时间表。

—— Taichi Ohno

Taichi Ohno被公认为精益制造之父。 虽然精益制造的实践无法完全适用于软件开发领域,但它们的原则是一致的。 这些原则可以指导我们很好地寻求典型的企业IT组织采用云原生应用程序架构所需的变革,并且接受作为这一转变所带来的部分的文化和组织转型。

文化变革

企业IT采用云原生架构所需的变革根本不是技术性的,而是企业文化和组织的变革,围绕消除造成浪费的结构、流程和活动。 在本节中,我们将研究必要的文化转变。

从信息孤岛到DevOps

企业IT通常被组织成以下许多孤岛:

  • 软件开发
  • 质量保证
  • 数据库管理
  • 系统管理
  • IT运营
  • 发布管理
  • 项目管理

创建这些孤岛是为了让那些了解特定领域的人员来管理和指导那些执行该专业领域工作的人员。 这些孤岛通常具有不同的管理层次,工具集、沟通风格、词汇表和激励结构。这些差异启发了企业IT目标的不同范式,以及如何实现这一目标。

开发和运维分别对软件变更持有的观念就是个经常被提起的关于这些矛盾模式的例子。 开发的任务通常被视为通过开发软件功能为组织提供额外的价值。 这些功能本身就是向IT生态系统引入变更。 所以开发的使命可以被描述为“交付变化”,而且经常根据有多少次变更来进行激励。

相反,IT运营的使命可以被描述为“防止变更”。 IT运营通常负责维护IT系统所需的可用性、弹性、性能和耐用性。因此,他们经常以维持关键绩效指标(KPI)来进行激励,例如平均故障间隔时间(MTBF)和平均恢复时间(MTTR)。与这些措施相关的主要风险因素之一是在系统中引入任何类型的变更。 那么,不是设法将开发期望的变更安全地引入IT生态系统,而是通过将流程放在一起,使变更变得痛苦,从而降低了变化率。

这些不同的范式显然导致了许多额外的工作。项目工作中的协作、沟通和简单的交接变得乏味和痛苦,最糟糕的是导致绝对混乱(甚至是危险的)。 企业IT通常通过创建基于单据的系统和委员会会议驱动的复杂流程来尝试“修复”这种情况。企业IT价值流在所有非增值浪费下步履瞒珊。

像这样的环境与云原生的速度思想背道而驰。 专业的信息孤岛和流程往往是由创造安全环境的愿望所驱动。然而,他们通常提供很少的附加安全性,在某些情况下,会使事情变得更糟!

在其核心上,DevOps代表着这样一种思想,即将这些信息孤岛构建成共享的工具集、词汇表和沟通结构,以服务于专注于单一目标的文化:快速、安全得交付价值。 然后创建激励结构,强制和奖励领导组织朝着这一目标迈进的行为。 官僚主义和流程被信任和责任所取代。

在这个新的世界中,开发和IT运营部门向共同的直接领导者汇报,并进行合作,寻找能够持续提供价值并获得期望的可用性、弹性、性能和耐久性水平的实践。今天,这些对背景敏感的做法越来越多地包括采用云原生应用架构,提供完成组织的新的共同目标所需的技术支持。

从间断均衡到持续交付

企业经常采用敏捷流程,如Scrum,但是只能作为开发团队内部的本地优化。

在这个行业中,我们实际上已经成功地将个别开发团队转变为更灵活的工作方式。 我们可以这样开始项目,撰写用户故事,并执行敏捷开发的所有例程,如迭代计划会议,日常站会,回顾和客户展示demo。 我们中的冒险者甚至可能会冒险进行工程实践,如结对编程和测试驱动开发。持续集成,这在以前是一个相当激进的概念,现在已经成为企业软件词典的标准组成部分。事实上,我已经是几个企业软件团队中的一部分,并建立了高度优化的“故事到演示”周期,每个开发迭代的结果在客户演示期间被热烈接受。

但是,这些团队会遇到可怕的问题:我们什么时候可以在生产环境中看到这些功能?

这个问题是我们很难回答,因为它迫使我们考虑我们无法控制的力量:

  • 我们需要多长时间才能浏览独立的质量保证流程?
  • 我们什么时候可以加入生产发布的行列中?
  • 我们可以让IT运营及时为我们提供生产环境吗?

在这一点上,我们意识到自己已经陷入了戴维·韦斯特哈斯(Dave Westhas)所说的scrum瀑布中了。 我们的团队已经开始接受敏捷原则,但我们的组织却没有。所以,不是每次迭代产生一次生产部署(这是敏捷宣言的原始出发点),代码实际上是批量参与一个更传统的下游发布周期。

这种操作风格产生直接的后果。我们不是每次迭代都将价值交付给客户,并将有价值的反馈回到开发团队,我们继续保持“间断均衡”的交付方式。 间断均衡实际上丧失了敏捷交付的两个主要优点:

  • 客户可能需要几周的时间才能看到软件带来的新价值。 他们认为,这种新的敏捷工作方式只是“像往常一样”,不会增强对开发团队的信任。 因为他们没有看到可靠的交付节奏,他们回到了以前的套路将尽可能多的要求尽可能多地堆放到发布版上。 为什么? 因为他们对软件能够很快发布没有信心,他们希望尽可能多的价值被包括在最终交付时。
  • 开发团队可能会好几周都没有得到真正的反馈。虽然演示很棒,但任何经验丰富的开发人员都知道,只有真实用户参与到软件之中才能获得最佳反馈。这些反馈能够帮助软件修正,使团队去做正确的事情。反馈推迟后,错误的可能性只能增加,并带来昂贵的返工。

获得云原生应用程序体系结构的好处需要我们转变为持续交付。 我们拥抱端到端拥抱价值的原则,而不是Water Scrum Fall组织驱动的间断平衡。设想这样一个生命周期的模型是由Mary和Tom Poppendieck在《实施精益软件开发(Addison-Wesley)》一书中描述的“概念到现金”的想法中提出来的。 这种方法考虑了所有必要的活动,将业务想法从概念传递到创造利润的角度,并构建可以使人们和过程达到最佳目标的价值流。

我们技术上支持这种使用连续交付的工程实践的方法,每次迭代(实际上是次每个源代码提交!)都被证明可以以自动化的方式部署。 我们构建部署流水线,可自动执行每次测试,如果该测试失败,将会阻止生产部署。 唯一剩下的决定是商业决策:现在部署可用的新功能有很好的业务意义吗? 我们已经知道它已经如广告中的方式工作,但是我们要现在就把它们交给客户吗? 因为部署管道是完全自动化的,所以企业能够通过点击按钮来决定是否采取行动。

从集中治理到分散自治

Waterscrumfall文化中的一部分已经被特别提及,因为它已经被视为云原生架构采纳的一个关键。

企业通常采用围绕应用架构和数据管理的集中治理结构,负责维护指导方针和标准的委员会,以及批准个人设计和变更。 集中治理旨在帮助解决以下几个问题:

  • 可以防止技术栈的大范围不一致,降低组织的整体维护负担。
  • 可以防止架构选型中的大范围不一致,从而形成组织的应用程序开发的共同观点。
  • 整个组织可以一致地处理跨部门关切,例如合规性。
  • 数据所有权可由具有全局视野的人来决定。

之所以创造这些结构,是因为我们相信它们将有助于提高质量、降低成本或两者兼而有之。然而,这些结构很少能够帮助我们提高质量节约成本,并且进一步妨碍了云原生应用架构寻求的交付速度。 正如单体应用程序架构导致了限制技术创新速度的瓶颈一样,单一的治理结构同样如此。架构委员会经常只会定期召集,并且经常需要很长的等待时才能发挥工作。即使是很小的数据模型的变化——可能在几分钟或几个小时内完成的更改,即将被委员会批准的变更——将会把时间浪费在一个不断增长的待办事项中。

采用云原生应用程序架构时通常都会与分散式治理结合起来。建立云原生应用程序的团队拥有他们负责交付的能力的所有方面。他们拥有和管理数据、技术栈、应用程序架构、每个组件设计和API协议并将它们交付给组织的其余部分。如果需要对某事作出决策,则由团队自主制定和执行。

团队个体的分散自治和自主性是通过最小化、轻量级的结构进行平衡的,这些结构在可独立开发和部署的服务之间使用集成模式(例如,他们更喜欢HTTP REST JSON API而不是不同风格的RPC)来实现。这些结构通常会在底层解决交叉问题,如容错。激励团队自己设法解决这些问题,然后自发组织与其他团队一起建立共同的模式和框架。随着整个组织中的最优解决方案出现,该解决方案的所有权通常被转移到云框架/工具团队,这可能嵌入到平台运营团队中也可能不会。当组织正在围绕对架构共识进行改革时,云框架/工具团队通常也将开创解决方案。

组织变革

在本节中,我们将探讨采用云原生应用程序架构的组织在创建团队时需要进行的变革。这个重组背后的理论是著名的康威定律。我们的解决方案是在长周期的产品开发中,创建一个包含了各方面专业员工的团队,而不是将他们分离在单一的团队中,例如测试人员。

业务能力团队

设计系统的组织,最终产生的设计等同于组织之内、之间的沟通结构。

—Melvyn Conway

我们已经讨论了“从孤岛到DevOps”将IT组织成专门的信息孤岛的做法。我们很自然地创造了这些孤岛,并把个体放到与这些孤岛一致的团队中。但是当我们需要构建一个新的软件的时候会怎么样?

一个很常见的做法是成立一个项目团队。该团队向项目经理汇报,然后项目经理与各种孤岛合作,为项目所需的各个专业领域寻求“资源”。正如康威定律所言,这些团队将很自然地在系统中构筑起各种孤岛,我们最终得到的是联合各种孤岛相对应的孤立模块的架构:

  • 数据访问层
  • 服务层
  • Web MVC层
  • 消息层
  • 等等

这些层次中的每一层都跨越了多个业务能力领域,使得在其之上的创新和部署独立于其他业务能力的新功能变的非常困难。

寻求迁移到将业务能力分离的微服务等云原生架构的公司经常采用Thoughtworks称之为的“逆康威定律”。他们没有建立一个与其组织结构图相匹配的架构,而是决定了他们想要的架构,并重组组织以匹配该架构。如果你这样做,根据康威,你所期望的架构最终会出现。

因此,作为转向DevOps文化的一部分,我们组织了跨职能、业务能力的团队,开发的是产品而不再是项目。开发产品需要长期的付出,直到它们不再为企业提供价值为止。(直到你的代码不再运行在生产上为止!)构建、测试、交付和运营提供业务能力的服务所需的所有角色都存在于一个团队中,该团队不会交接代码到组织到的其他部分。这些团队通常被组织为“双比萨队”,意思是如果不能用两个比萨饼喂饱,那就意味着团队规模太大了。

那么剩下的就是确定要创建的团队。如果我们遵循逆康威定律,我们将从组织的领域模型开始,并寻求可以封装在有限环境中的业务能力。一旦我们确定了这些能力,我们就可以创建为这些业务能力的整个生命周期负责的团队。 业务能力团队掌握其应用程序从开发到运营的整个生命周期。

平台运营团队

业务能力团队需要依赖于我们前面提到的”自助敏捷基础架构“。

事实上,我们可以这样来描述一种特殊的业务能力——开发、部署和运营业务的能力。这种能力应该是平台运营团队所具有的。

平台运营团队运营自助敏捷基础架构平台,并交付给业务能力团队使用。该团队通常包括传统的系统、网络和存储管理员角色。如果公司正在运营云平台,该团队也将拥有管理数据中心的团队或与他们紧密合作,并了解提供基础架构平台所需的硬件能力。

IT运营传统上通过各种基于单据的系统与客户进行互动。由于基于平台操作流来运行自助服务平台,因此必须提供不同形式的交互方式。正如业务能力团队之间通过定义好的API协议相互协作一样,平台运营团队也为该平台提供了API协议。业务能力团队不再需要排队申请应用环境和数据服务,而是采用更精简的方式构建按需申请环境和服务的自动化发布管道。

技术变革

现在我们将一些问题转移到了云中的DevOps平台。

分解单体

传统的n层单体式应用部署到云中后很难维护,

传统的n层,单体式企业应用程序在部署到云基础设施中后很难良好运行,因为它们经常对云基础设施无法提供的部署环境做出不可靠的假设。 例如以下要求:

  • 可访问已挂载的共享文件系统
  • P2P应用服务器集群
  • 共享库
  • 配置文件位于常用的配置文件目录

大多数这些假设都出于这样的事实:单体应用通常都部署在长期运行的基础设施中,并与其紧密结合。不幸的是,它们并不太合适弹性和短暂的基础设施。

但是即使我们可以构建一个不需要这些假设的单体应用,我们依然有一些问题需要解决:

  • 单体式应用的变更周期耦合,使独立业务能力无法按需部署,阻碍创新速度。
  • 嵌入到单体应用中的服务不能独立于其他服务进行扩展,因此负载更难于优化。
  • 新加入组织的开发人员必须适应新的团队,经常学习新的业务领域,并且一次就熟悉一个非常大的代码库。 这样会增加3-6个月的适应时间,才能实现真正的生产力。
  • 尝试通过堆积开发人员来扩大开发组织,增加了昂贵的沟通和协调成本。
  • 技术栈需要长期承诺。引进新技术被认为太冒险的举动,因为这可能会对整体产生不利影响。

细心的读者会注意到,该列表正好与“微服务”的列表相反。将组织分解为业务能力团队还要求我们将应用程序分解成微服务。只有这样,我们才能从云计算基础架构中获得最大的收益。

分解数据

仅仅将单体应用分解为微服务还是远远不够的。数据模型必须要解耦。如果业务能力团队被认为是自主的,却被迫通过单一的数据存储进行协作,那么单体应用对创新的阻碍将依然存在。

事实上,产品架构必须从数据开始的说法是有争议的。由Eric Evans(Addison-Wesley)在领域驱动设计(DDD)中提出的原理认为,我们的成功在很大程度上取决于领域模型的质量(以及支持它的普遍存在的语言)。要使领域模型有效,还必须在内部一致——我们不应该在同一模型内的一致定义中找到重复定义的术语或概念。

创建不具有这种不一致的联合领域模型是非常困难和昂贵的(可以说是不可能的)。Evans将业务的整体领域模型的内部一致性子集称为有界上下文。

最近与航空公司客户合作时,我们讨论了他们业务的核心概念,自然是“航空公司预订”的话题。该集团可以在其预定业务中划分十七种不同的逻辑定义,几乎不能将它们调和为一个。相反,每个定义的所有细微差别都被仔细地描绘成一个个单一的概念,这将成为组织的巨大瓶颈。

有界上下文允许你在整个组织中保持单一概念的不一致定义,只要它们在有界上下文中一致地定义。

因此,我们首先需要确定可以在内部保持一致的领域模型的细分。我们在这些细分上画出固定的边界,划分出有界上下文。然后,我们可以将业务能力团队与这些环境相匹配,这些团队将构建提供这些功能的微服务。

微服务提供了一个有用的定义,用于定义12因素应用程序应该是什么。12因素主要是技术规范,而微服务主要是业务规范。通过定义有界上下文,为他们分配一组业务能力,委托能力团队对这些业务能力负责,并建立12因素应用程序。这些应用程序可以独立部署的情况下,为业务能力团队的运维提供了一组有用的技术工具。

我们将有界上下文与每个服务模式的数据库结合,每个微服务封装、管理和保护自己的领域模型和持久存储。在每个服务模式的数据库中,只允许一个应用程序服务访问逻辑数据存储,逻辑数据存储可能是以多租户集群中的单个schema或专用物理数据库中存在。对这些概念的任何外部访问都是通过一个明确定义的业务协议来实现的,该协议的实现方式为API(通常是REST,但可能是任何协议)。

这种分解允许应用拥有多语言支持的持久性,或者基于数据形态和读写访问模式选择不同的数据存储。然而,数据必须经常通过事件驱动技术重新组合,以便请求交叉上下文。诸如命令查询责任隔离(CQRS)和事件源(Event Sourcing)之类的技术通常在跨上下文同步类似概念时很有帮助,这超出了本文的范围。

容器化

容器镜像(例如通过LXC、Docker或Rocket项目准备的镜像)正在迅速成为云原生应用程序架构的部署单元。然后通过诸如Kubernetes、Marathon或Lattice等各种调度解决方案实例化这样的容器镜像。亚马逊和Google等公有云供应商也提供一流的解决方案,用于容器化调度和部署。容器利用现代的Linux内核原语,如控制组(cgroups)和命名空间来提供类似的资源分配和隔离功能,这些功能与虚拟机提供的功能相比,具有更少的开销和更强的可移植性。应用程序开发人员将需要将应用程序包装成容器镜像,以充分利用现代云基础架构的功能。

从管弦乐编排到舞蹈编舞

不仅仅服务交付、数据建模和治理必须分散化,服务集成也是如此。企业服务集成传统上是通过企业服务总线(ESB)实现的。 ESB成为管理服务之间交互的所有路由、转换、策略、安全性和其他决策的所有者。我们将其称之为编排,类似于导演,他决定了乐团演出期间演奏音乐的进程。ESB和编排可以产生非常简单和令人愉快的架构图,但它们的简单性紧紧是表面性的。在ESB中隐藏的是复杂的网络。管理这种复杂性成为全职职业,从事这个工作成为应用开发团队的持续瓶颈。正如我们在联合数据模型所看到的,像ESB这样的联合集成解决方案成为阻碍幅度的巨大难题。

诸如微服务这样的云原生架构更倾向于喜欢舞蹈,它们类似于芭蕾舞中的舞者。它们将心智放置在端点上,类似于Unix架构中的虚拟管道和智能过滤器,而不是放在集成机制中。当舞台上的情况与原来的计划有所不同时,没有导演告诉舞者该怎么做。相反,他们只是适应。同样,服务通过客户端负载均衡和断路器等模式,适应环境中不断变化的各种情况。

虽然架构图看起来像一个缠杂的网络,但它们的复杂性并不比传统的SOA大。编排简单地承认并暴露了系统的原有的复杂性。再次,这种转变是为了支持从云原生架构中寻求速度所需的自治。团队能够适应不断变化的环境,而无需承担与其他团队协调的开销,并避免了在集中管理的ESB中协调变更所造成的开销。

本章小结

本章中,我们探讨了大多数企业采用云原生应用架构所需要做出的变革。从宏观总体上看是权力下放和自治:

DevOps

技能集中化转变为跨职能团队。

持续交付

发行时间表和流程的权力下放。

自治

决策权力下放。

我们将这种权力下放编成两个主要的团队结构:

业务能力团队

自主决定设计、流程和发布时间表的跨职能团队。

平台运营团队

为跨职能团队提供他们所需要运行平台。

而在技术上,我们也分散自治:

单体应用到微服务

将个人业务能力的控制分配给单个自主服务。

有界上下文

将业务领域模型的内部一致子集的控制分配到微服务。

容器化

将对应用程序包装的控制分配给业务能力团队。

编排

将服务集成控制分配给服务端点。

所有这些变化造就了无数的自治单元,辅助我们以期望的创新速度安全前行。

在最后一章中,我们将通过一组操作手册,深入研究迁移到云原生应用程序架构的技术细节。