实现云原生依赖于四大核心要素:微服务、容器化技术、DevOps、持续交付。
容器是一种沙盒技术,主要目的是为了将应用运行在其中,与外界进行隔离,以及方便这个沙盒可以被转移到其他宿主机器。本质上,它是一个特殊的进程。通过Namespace、Control groups、chroot等技术把资源、文件、设备、状态和配置划分到一个独立的空间。
通俗点的理解容器就是一个装应用软件的箱子,箱子里面有软件运行所需的依赖库和配置,开发人员可以把这个箱子搬到任何机器上,且不影响里面软件的运行。容器化的好处在于运维的时候不需要再关心每个服务所使用的技术栈了,每个服务都被无差别地封装在容器内部,可以被无差别地管理和维护,现在比较流行的工具是Docker和Kubernetes。
如图1-5所示,容器技术的演进非常快速,其中Docker和Google公司做出了重要贡献,两个关键的里程碑是Docker的发布和Kubernetes从CNCF“毕业”。
图1-5 容器技术的演进
在Docker的镜像格式和容器运行时成为事实上的标准之后,其他厂商也开始进入容器领域,为了加强创新和防止碎片化,容器行业的领导者和技术人员成立了开放容器项目(Open Container Initiative
,OCI)来制定一套容器技术标准,在目前的容器领域,Docker只是其中之一,其他著名的工具还有Podman
等。为了方便和统一,本书使用Docker来作为容器工具。
在容器技术中,镜像(Image)和容器(Container)是最重要的两个基础部分。其中镜像是文件,是一个只读的模板,一个独立的文件系统,里面包含运行容器所需的数据,可以用来创建新的容器;而容器是基于镜像创建的进程,容器中的进程依赖于镜像中的文件,容器具有写的功能,可以根据需要改写里面的软件、配置等,并可以保存为新的镜像。
容器技术是云原生应用的基础,在后继的章节中我们会持续介绍它的技术和应用。
微服务,又被称为微服务架构,是一种软件的架构方式。它将应用构建成一系列按业务领域划分的模块化、小型化的自治服务。在微服务架构中,每个服务都是独立的,并且实现了单一的业务功能。
简单来说,就是将一个复杂的系统按业务划分成多个子系统,每个子系统都是完整的、可独立运行的。子系统之间的交互可通过网络协议进行通信。所以,不同子系统可以使用不同的编程语言来实现,并且可以使用不同的存储技术。但是,因为子系统服务数量越多,管理起来越复杂,因此就需要采用集中化管理,例如Eureka、Zookeeper等都是比较常见的服务集中化管理框架;同时,使用自动化部署(例如Jenkins)可以减少人为控制,降低出错概率,提高效率。
微服务实现的是软件开发中一直追求的低耦合+高内聚。记得有一次我们系统的一个内部组件出了问题,结果影响了看起来毫不相关另外一个组件的处理,于是引起灵魂发问:“为什么这两个组件会互相影响?!”
微服务可以解决这个问题,微服务的本质是把一个大型复杂系统拆分成若干低耦合的模块,比如专门负责接收外部数据的模块,专门负责响应前台操作的模块,模块还可以进一步拆分,比如负责接收外部数据的模块可以继续分成多个负责接收不同类型数据的低耦合子模块,这样每个模块出现问题,其他模块不会受到影响,还能正常对外提供服务。
典型的微服务架构如图1-6所示。
图1-6 典型的微服务架构
DevOps一词包含Development和Operations两个部分,是开发和运营维护的总称,一般称之为开发运维一体化。
传统的软件组织将开发、IT运营和质量保障设为各自独立的部门。在这种环境下如何采用新的开发方法(例如敏捷软件开发)就成为一个需要解决的问题。DevOps是一套针对这些多个部门间沟通与协作问题的流程和方法。
如果对支持业务部门提出“每天部署10次”的要求,部署周期就必须要求很短,而且,软件也必须提供这种支撑,这种能力也被称为持续部署。
DevOps的引入能对产品交付、测试、功能开发和维护(包括曾经罕见但如今已屡见不鲜的“热补丁”)起到意义深远的影响。在缺乏DevOps能力的组织中,开发与运营之间存在着信息“鸿沟”——例如运营人员要求更好的可靠性和安全性,开发人员则希望基础设施响应更快,而业务用户的需求则是更快地将更多的特性发布给最终用户使用。这种信息鸿沟就是常出问题的地方。
DevOps经常被描述为“开发团队与运营团队之间更具协作性、更加高效的关系”。由于团队间协作关系的改善,整个组织的效率因此得到提升,伴随频繁变化而来的生产环境的风险也能得到降低。
在很多企业中,应用程序发布是一项涉及多个团队、风险很大、压力很高的活动。然而在具备DevOps能力的组织中,应用程序发布的风险较低,原因如下。
● 减少变更范围:与传统的瀑布式开发模型相比,采用敏捷或迭代式开发意味着更频繁的发布、每次发布包含的变化更少。由于部署经常进行,因此每次部署不会对生产系统造成巨大影响,应用程序会以平滑的速率逐渐生长。
● 加强发布协调:依靠强有力的发布协调人来弥合开发与运营之间的技能鸿沟和沟通鸿沟;采用多种协作工具来确保所有相关人员理解变更的内容并全力合作。
● 自动化:强大的部署自动化手段确保部署任务的可重复性、减少部署出错的可能性。
与传统开发方法那种大规模的、不频繁的发布(通常以“季度”或“年”为单位)相比,敏捷方法大大提升了发布频率(通常以“天”或“周”为单位)。
图1-7展示了在DevOps模式下,开发与运维连接为一体的紧密关系,以及软件生命周期各个阶段的转换关系。
图1-7 DevOps生命周期
持续交付(Continuous Delivery,缩写为CD),是一种软件工厂方法,让软件产品的产出过程在较短的周期内完成,以保证软件可以稳定、持续的保持在随时可以发布的状态。它的目标在于让软件的构建、测试与发布变得更快以及更频繁。这种方式可以减少软件开发的成本与时间,减少风险。
持续交付与DevOps的含义很相似,所以经常被混淆。但是它们是不同的两个概念。DevOps的范围更广,它以文化变迁为中心,特别是软件交付过程所涉及的多个团队之间的合作(开发、运维、QA、管理部门等),并且将软件交付的过程自动化。从另外一个方面看,持续交付是一种自动化交付的手段,关注点在于将不同的过程集中起来,并且更快、更频繁地执行这些过程。因此,DevOps可以是持续交付的一个产物,持续交付直接汇入DevOps。
有时候,持续交付也与持续部署容易混淆。持续部署意味着所有的变更都会被自动部署到生产环境中。持续交付意味着所有的变更都可以被部署到生产环境中,但是出于业务考虑,也可以选择不部署。如果要实施持续部署,必须先实施持续交付。
从代码提交开始,我们可以把整个持续交付归纳出四个关键要素:持续集成、自动化测试、自动化部署、交付流水线。
● 持续集成:持续集成保证了代码始终是可用的,编译正确并且通过所有单元测试和代码静态检测,这些动作都发生在代码部署到环境之前,是持续交付流水线的第一步。
● 自动化测试:通过自动化测试,实现快速回归测试,通过自动化测试平台来保障测试质量和测试覆盖率。
● 自动化部署:基于容器化的快速部署优势实现流水线快速推进;利用容器化高可扩展性的优势实现基于负载的自动伸缩;利用容器化更加轻量级的优势解决了应用和操作系统的强耦合问题;利于容器化高一致性的优势统一构建各环境,提高部署环境的一致性。
● 交付流水线:交付流水线包括了从开发提交代码,触发构建,部署测试环境,测试环境自动化以及测试、准生产环境部署到测试、上线审批、自动化发布上线及测试。
整个交付流水线是自动化和人工相结合的一个过程,测试环节需要人工测试的参与,任何节点如果自动执行失败的话,也要提供人工介入的入口,允许人工选择重新执行、终止流程等动作,涉及上线更需要人工审核才能触发自动化发布。所以,交付流水线也不是一味追求自动化,需要自动和人工的结合。