谷歌:云原生架构的 5 条原则

阅读数:4391 2019 年 7 月 8 日

在 Google Cloud 中,我们经常把“云原生架构”这一术语作为迁移或构建在Google Cloud Platform(GCP)上的应用程序所期望的最终目标。但云原生究竟是什么意思呢?更重要的是,你如何着手设计这样一个系统?

从高层次来看,与传统的本地基础设施相比, 云原生架构意味着要适应云提供的许多新的可能性,但架构约束有着很大的不同。以下是我们作为软件架构师应该考虑到的高层次元素:

  • 系统的功能需求(它应该做什么,例如“以这种格式处理订单…”);
  • 非功能性要求(如“每分钟至少处理 200 个订单”);
  • 约束(超出变更范围的内容,例如“订单必须在我们现有的大型机系统上更新”)。

虽然功能方面不会发生太大变化,但云提供(有时需要)的用来满足非功能性需求的方式差别很大,对架构的约束也有很大的差别。如果架构师未能使他们的方法适应这些不同的约束,他们设计的系统通常就会脆弱而昂贵,并且难以维护。另一方面,架构良好的云原生系统应该在很大程度上是自修复、经济高效的,并且可以通过持续集成 / 持续交付(CI / CD)轻松进行更新和维护。

好消息是,构成云的服务器、磁盘和网络与传统基础设施相同。这意味着几乎所有优秀的架构设计原则仍然适用于云原生架构。但是在云中时,关于这种结构如何执行的一些基本假设会发生变化。例如,在传统环境中配置替换服务器可能需要数周时间,而在云环境中则需要几秒钟,应用程序架构要把这点考虑在内。

在本文中,我们列出了云原生架构的五个原则,这些原则将有助于确保设计充分利用云,同时避免将旧的方法引入新平台的陷阱。

云原生架构的原则

云架构(即云原生架构)的构建原则,侧重于如何针对云的独特功能优化系统架构。传统的架构倾向于为固定的、高成本的基础设施进行优化,需要大量手动的修改。因此,传统架构侧重于相对固定且数量较少的组件的弹性和性能。然而,在云中,这样一个固定的基础设施没有多大意义,因为云是根据使用量进行收费的(这样可以通过减少空间占用来节省资金),而且自动化也更容易(自动放大和缩小要容易得多)。因此,云原生架构的重点是通过横向扩展、分布式处理,以及自动更换故障组件来实现弹性和扩展。

原则 1:自动化设计

自动化一直是软件系统的最佳实践,但云技术使得基础设施以及位于其上的组件自动化变得前所未有的简单。尽管前期投资通常会更高,但从中期来看,无论从投入的角度,还是在系统的弹性和性能方面,几乎总能获得回报。自动化流程可以比人更快地修复、扩展和部署系统。正如我们稍后会讨论的那样,云上的架构并不是一次性的,自动化也不例外,因为会找到新的系统操作方法,所以将发现新的东西可以自动化。

自动化云原生系统的一些常见领域是:

  • 基础设施:使用Google Cloud Deployment ManagerTerraform之类的工具,自动创建基础设施并对其进行更新;
  • 持续集成 / 持续交付(CI/CD):使用Google Cloud BuildJenkinsSpinnaker等工具自动构建、测试和部署构成系统的软件包。不仅应该自动部署,还应该努力实现金丝雀测试和回滚等过程的自动化;
  • 伸缩性(Scale Up/Down):除非系统负载几乎从未发生变化,否则应该根据负载的增加自动扩展系统,并根据负载的持续下降进行收缩。通过扩展,可以确保服务仍然可用,并通过按比例收缩来降低成本。这对于大型应用程序(如公共网站)以及具有不规则负载的较小应用程序(例如在某些时段非常繁忙但在其他时间几乎不使用的内部应用程序)来说是很有意义的。对于有时几乎没有流量并且可以容忍一些初始延迟的应用程序,甚至应该考虑将其收缩为零(删除所有正在运行的实例,并在下次需要时重新启动应用程序);
  • 监控和自动恢复:应该从一开始就在云原生系统中纳入监控和日志记录。日志记录和监视的数据流可以很自然地用于监视系统的运行状况,除此之外还可以有许多用途。例如,它们可以对系统的使用和用户的行为(有多少人在使用系统,他们在使用什么部分,他们的平均延迟时间是多少等)提供有价值的见解。其次,它们可以通过汇总来衡量整个系统的健康状况(例如,磁盘又快满了,它的填写速度比平时快吗?磁盘使用量和服务占用之间的关系是什么?等等)。最后,它们是添加自动化理想的地方,当磁盘要填满时,可以自动调整磁盘大小以保持系统正常运行,而不仅仅只记录错误。

原则 2:善用状态

存储的“状态”,可以是用户的数据(例如,用户购物车中的条目,或他们的员工编号)或者是系统的状态(例如,作业中运行的实例数量,运行中的代码版本),这是构建分布式、云原生架构最难的方面。因此,设计系统时应该有意地去了解何时以及如何存储状态,并尽可能设计无状态的组件

无状态的组件可以很容易实现以下功能:

  • 伸缩:要扩展,只需添加更多的副本。要收缩,可以引导实例在完成当前任务后终止;
  • 修复:要“修复”一个失败的组件实例,只需尽可能优雅地终止它并启动一个替换;
  • 回滚:如果部署得不好,无状态的组件更容易回滚,因为可以终止它们并启动旧版本的实例;
  • 负载均衡:当组件处于无状态时,负载均衡要简单得多,因为任何实例都可以处理任何请求。有状态组件的负载均衡要困难得多,因为用户会话的状态通常驻留在实例上,这迫使该实例处理来自给定用户的所有请求。

原则 3:支持托管服务

云不仅仅是基础设施,大多数的云提供商都提供丰富的托管服务,提供各种各样的功能,让我们轻松管理后端软件或基础设施。但是,许多组织对利用这些服务持谨慎态度,因为他们担心被某个供应商给“绑定”。这是一个合理的担心,但托管服务通常可以极大地节省组织的时间和运营开销。

广义上讲,从资金和技能两方面来看,是否采用托管服务取决于可移植性与运营开销。粗略地说,今天可能会考虑的托管服务分为三大类:

  • 托管开源或开源兼容服务:托管开源(例如 Cloud SQL)或提供开源兼容的接口(例如 Cloud Bigtable)的服务。这应该是一个简单的选择,因为使用托管服务有很多好处,而且风险很小;
  • 节省高运营成本的托管服务:某些服务不能直接与开源兼容,或者没有直接的开源替代方案,但是比替代方案更容易使用,它们值得承担风险。例如,BigQuery因为易于操作而经常被组织所采用;
  • 其他情况:然后是困难的情况,没有容易的迁移途径可以离开服务,它提供了不太明显的运营效益。需要逐个分析这些问题,考虑到服务的战略意义、自己运行它的运营开销以及迁移所需的工作。

但是,实践经验表明,大多数云原生架构都偏爱托管服务,但必须让迁移的潜在风险,低于云提供商大规模管理服务所带来的时间、精力和运营风险方面的巨大节省。

原则 4:深入实践防御

传统的体系架构非常重视周边安全,粗略地说,它建立了一个强化的网络边界,内部有“可信赖的东西”,外部有“不受信任的东西”。不幸的是,这种方法总是容易受到内部的攻击,以及鱼叉式网络钓鱼(spear phishing)之类的外部威胁。此外,提供灵活的移动办公的压力越来越大,进一步破坏了网络边界。

云原生架构起源于面向互联网的服务,因此始终需要处理外部的攻击。因此,它们通过在每个组件之间应用身份验证,并通过最小化这些组件之间的信任(即使它们是“内部的”)来实施深度防御。因此,没有内部外部”之分

云原生架构应该将此想法扩展到身份验证之外,包括速率限制和脚本注入等内容。设计中的每个组件都应该设法保护自己免受其他组件的影响。这不仅使体系架构具有很强的弹性,而且使产生的服务更容易部署在云环境中,在云环境中,服务与其用户之间可能没有可信任的网络。

原则 5:架构不止

云原生系统的核心特征之一是它总是在进化,这同样适用于架构。作为一个云原生架构师,随着组织需求的变化、IT 系统环境的变化以及云提供商自身的能力的变化,您应该始终寻求优化、简化和改进系统的架构。尽管这无疑需要不断的投资,但过去的教训是显而易见的:要发展、增长和响应,IT 系统需要生存、呼吸和改变。过时的、僵化的 IT 系统会迅速使组织陷入停顿,无法应对新的威胁和机遇。

唯一不变的是变化

在动物界,生存有利于那些适应环境的个体。这不是从“坏”到“最佳”或从“原始”到“进化”的线性旅程,而是所有事物都在不断变化。随着环境的变化,对物种施加压力以进化和适应。同样,云原生架构并不能取代传统架构,但它们更适合于非常不同的云环境。云正日益成为我们大多数人工作的环境,许多物种都证明,不能发展和适应的都不是长期的选择。

上面描述的原则并不是创建云原生架构的神奇公式,但希望能为如何充分利用云提供强有力的指导。作为额外的一个好处,云架构的变化和调整给了我们以其他方式改进和调整的机会,并使它们能够更好地适应下一次环境的变化。改变可能是困难的,正如十几亿年的进化所展示的那样,不必是生存得最好的,只需要能够去适应。

原文链接5 principles for cloud-native architecture

收藏

评论

微博

发表评论

注册/登录 InfoQ 发表评论

最新评论

赵钰莹 2019 年 07 月 09 日 09:21 0 回复
这篇文章的观点很有参考价值啊~推荐给关注云原生领域的架构师
没有更多了