1.2.2 云原生技术

本节我们将简要介绍现阶段云原生领域所蕴含的核心技术。

1.微服务

微服务的去中心化管理、独立部署等特性让应用获得了巨大的灵活性。而容器也做了一把助燃器,推动微服务架构越来越流行。相对于单体应用而言,这种基于业务模块形成的独立单元更容易被容器化,因此也更容易上云。另一方面,微服务之间是基于API进行协作的,并且以可被访问的方式暴露出来,这恰恰和十二要素中的“端口绑定”理念吻合。微服务架构的这些特性让它更加适合在云上发布、部署和运行。这也就是为什么业界一致认为云原生应用应该是面向微服务的。

2.容器和编排

云原生生态是伴随着容器及编排市场的发展而逐渐成形的。与虚拟机相比,容器基于操作系统的隔离机制,具有更高的效率和运行速度,它可以以更细的粒度使用云上资源,低开销创建和销毁的特性使它更容易完成应用在云上的动态伸缩。基于容器这种应用组织形式,我们也更容易完成应用的部署和分发。而要完成大量容器的调度和管理就需要编排技术。如何调度容器,如何管理容器生命周期,如何维护应用现实状态和期望状态的一致,这都是编排的核心。随着容器编排市场的稳定,Kubernetes成了该领域的事实标准,而整个云原生生态的构建,最初都是围绕着Kubernetes展开的。因此我们可以认为,在现有的技术手段下,容器及其编排技术是云原生的基石,不可动摇。

3.服务网格

服务网格是从2017年起才逐渐被人们熟知的新技术。根据技术成熟度曲线,笔者认为服务网格依然处在发展的中前期。即便如此,CNCF也在修订的云原生定义中提及了服务网格,可见其重要性。

简单来说,服务网格就是一个用来管理服务间通信的基础设施层,通过一组边车(Sidecar)代理提供的能力,进行服务间流量的管理。如果将Kubernetes称作云原生应用的操作系统,那么服务网格就是云原生应用的网络层,为微服务应用解决流量管理难题。随着服务的增多,微服务需要进行治理和管控,服务网格正是用来管理服务间通信的解决方案。另外,服务网格的产品形态是基于边车代理的,而边车代理正是容器技术提供的能力。

服务网格和云原生的理念是高度契合的。云原生架构希望开发者只关注应用的构建,而将非功能性需求都下沉到云平台。服务网格正是这一理念的践行者,它以边车代理方式将通信管理相关功能下沉到基础设施,让应用具有流量管理、安全和可观察性等方面的能力,而且对应用来说,这些都是完全透明的。各大云厂商和团队都非常看重这一领域,开源和托管的产品相继被推出,也出现了很多服务网格生态产品。服务网格的出现改变了微服务架构的通信管理方式,相比侵入式的类库来说更有优势,是云原生技术的重要组成部分。

4.无服务器计算

无服务器计算(Serverless)是指在无状态的计算容器中运行应用程序,这些容器是由事件触发的,时效短暂,使用时类似调用函数一般。

无服务器计算进一步细化了应用程序对资源的使用粒度,可以提高计算资源的利用率。比如,一个单体应用中的各个模块被调用的次数是不一致的,有的模块比较“热”(访问多),有的模块比较“冷”(访问少)。为了让这些热模块能支持更多的响应,我们不得不连同冷模块也一起扩容。微服务架构改善了这种情况,通过将冷热模块拆分成服务,我们只需要对热服务进行扩容。无服务器计算在这个基础上更进了一步,将资源的利用粒度细化到了函数级别。有请求就启动相应的计算实例,没有就销毁,按需付费。由此,功能即服务(FaaS)的理念被发展出来。

和服务网格一样,无服务器计算也遵循云原生的理念,即只关注功能的实现,而不需要关注如何创建和销毁所使用的计算资源,这也是无服务器计算名字的内涵。CNCF的蓝图中也为无服务器计算开辟了专门的模块,收录相关的平台、框架、工具等生态产品。

5.不可变基础设施

不可变基础设施(immutable infrastructure)是指基础设施实例(如服务器、虚拟机、容器等),一旦创建就应该是只读的,若要修改就必须通过创建新的实例来替换。从概念上讲,可变和不变最大的差异在于如何处理实例的生命周期,如创建、修改、销毁。早期我们使用可变基础设施,如服务器时,这些机器会随着应用的运行而不断发生变化,比如修改配置、升级系统、更新应用程序等。频繁修改让服务器变得特殊化,难以复制,一旦它出现问题,我们很难找到替代品。

云计算按需使用的理念为不可变基础设施提供了条件。不可变基础设施完美契合了使用时启动,不用时销毁的要求。通过这种方式,应用和环境高度一致,可以动态伸缩,持续交付也成为可能。在实施上,我们主要以云端的虚拟基础设施为基础,利用容器技术进行打包和部署,通过镜像进行自动化构建和版本管理,并持续集成和交付应用。因此,不可变基础设施是在云上构建一个具有弹性伸缩能力且能应对快速变化的应用的重要基础。

6.声明式API

声明式(declarative)是指,我们描述期望的结果后,系统内部自己实现满足这个期望结果的功能的过程。与之对应的是命令式,命令式告知系统怎么做(how),而声明式告知系统要什么(what)。

最被熟悉的声明式编程语言是SQL,它主要描述想要什么样的数据,我们不需要以命令的方式告知SQL怎么执行查询引擎,怎么去数据库查找数据。声明式API是Kubernetes的一个重要能力,通过声明式配置方式可定义我们期望的状态。如果使用命令式请求方式,Kubernetes的API服务器一次只能处理一个请求,而声明式API服务器可以一次处理多个写操作,具备合并的能力。也正因如此,Kubernetes才能在外界无干扰的情况下完成从实际状态到期望状态的调谐过程,这也是Kubernetes编排能力的核心体现。因此,CNCF特别强调并将声明式API作为云原生的一个特性。

7.DevOps和CI/CD

DevOps是一种整合软件开发与运维的工程实践,能够帮助企业更快地发展和改进产品。借助自动化的软件交付流程,构建、测试、发布软件的过程更加快捷、频繁和可靠。

在传统的组织结构中,开发和运维是分离的,在沟通协作上很难高效完成交付任务。开发团队关注的是功能性需求,需要频繁交付新特性;而运维人员关注的是非功能性需求,即系统的可靠性、性能等。运维人员希望尽量避免修改从而降低发布风险,这和开发人员想要频繁交付功能的目标冲突。另一方面,运维人员对代码不了解会影响他们选择运行时环境的正确性,而开发人员对运行环境的生疏又导致他们无法及时对代码做出调整。

DevOps的出现打破了这种组织结构壁垒,可以让整个流程高速运转,从而跟上创新的脚步和市场变化的节奏。通过小步快跑的迭代方式来降低交付风险,可促进开发和运维的协作。通过持续集成和持续交付实践,发布的频率和速度将提高,产品创新与完善也将更快地实现。云上应用的一大特点就是具有冗余性和不断变化性,DevOps和持续交付为应对快速变化提供了保障。因此Pivotal将其作为云原生的重要特性也不为过。图1-4展示了DevOps的工作方式。

图1-4