云原生技术详解
什么是“云原生”?云原生该怎么落地?
什么是“云原生”?云原生该怎么落地?
云原生的四要素
微服务:几乎每个云原生的定义都包含微服务,跟微服务相对的是单体应用,微服务有理论基础,那就是康威定律,指导服务怎么切分,很玄乎,凡是能称为理论定律的都简单明白不了,不然就忒没b格,大概意思是组织架构决定产品形态,不知道跟马克思的生产关系影响生产力有无关系。
微服务架构的好处就是按function切了之后,服务解耦,内聚更强,变更更易;另一个划分服务的技巧据说是依据DDD来搞。
容器化:Docker是应用最为广泛的容器引擎,在思科谷歌等公司的基础设施中大量使用,是基于LXC技术搞的,容器化为微服务提供实施保障,起到应用隔离作用,K8S是容器编排系统,用于容器管理,容器间的负载均衡,谷歌搞的,Docker和K8S都采用Go编写,都是好东西。
DevOps:这是个组合词,Dev+Ops,就是开发和运维合体,不像开发和产品,经常刀刃相见,实际上DevOps应该还包括测试,DevOps是一个敏捷思维,是一个沟通文化,也是组织形式,为云原生提供持续交付能力。
持续交付:持续交付是不误时开发,不停机更新,小步快跑,反传统瀑布式开发模型,这要求开发版本和稳定版本并存,其实需要很多流程和工具支撑。
云原生的定义
很多人都会问“到底什么是云原生?”
实际上,云原生是一条最佳路径或者最佳实践。更详细的说,云原生为用户指定了一条低心智负担的、敏捷的、能够以可扩展、可复制的方式最大化地利用云的能力、发挥云的价值的最佳路径。
因此,云原生其实是一套指导进行软件架构设计的思想。按照这样的思想而设计出来的软件:首先,天然就“生在云上,长在云上”;其次,能够最大化地发挥云的能力,使得我们开发的软件和“云”能够天然地集成在一起,发挥出“云”的最大价值。
所以,云原生的最大价值和愿景,就是认为未来的软件,会从诞生起就生长在云上,并且遵循一种新的软件开发、发布和运维模式,从而使得软件能够最大化地发挥云的能力。说到了这里,大家可以思考一下为什么容器技术具有革命性?
其实,容器技术和集装箱技术的革命性非常类似,即:容器技术使得应用具有了一种“自包含”的定义方式。所以,这样的应用才能以敏捷的、以可扩展可复制的方式发布在云上,发挥出云的能力。这也就是容器技术对云发挥出的革命性影响所在,所以说,容器技术正是云原生技术的核心底盘。
云原生的技术范畴
云原生的技术范畴包括了以下几个方面:
- 第一部分是云应用定义与开发流程。这包括应用定义与镜像制作、配置 CI/CD、消息和 Streaming 以及数据库等。
- 第二部分是云应用的编排与管理流程。这也是 Kubernetes 比较关注的一部分,包括了应用编排与调度、服务发现治理、远程调用、API 网关以及 Service Mesh。
- 第三部分是监控与可观测性。这部分所强调的是云上应用如何进行监控、日志收集、Tracing 以及在云上如何实现破坏性测试,也就是混沌工程的概念。
- 第四部分就是云原生的底层技术,比如容器运行时、云原生存储技术、云原生网络技术等。
- 第五部分是云原生工具集,在前面的这些核心技术点之上,还有很多配套的生态或者周边的工具需要使用,比如流程自动化与配置管理、容器镜像仓库、云原生安全技术以及云端密码管理等。
- 最后则是 Serverless。Serverless 是一种 PaaS 的特殊形态,它定义了一种更为“极端抽象”的应用编写方式,包含了 FaaS 和 BaaS 这样的概念。而无论是 FaaS 还是 BaaS,其最为典型的特点就是按实际使用计费(Pay as you go),因此 Serverless 计费也是重要的知识和概念。
云原生思想的两个理论
在了解完云原生的技术范畴之后你就会发现,其所包含的技术内容还是很多的,但是这些内容的技术本质却是类似的。云原生技术的本质是两个理论基础。
- 第一个理论基础是:不可变基础设施。这一点目前是通过容器镜像来实现的,其含义就是应用的基础设施应该是不可变的,是一个自包含、自描述可以完全在不同环境中迁移的东西;
- 第二个理论基础就是:云应用编排理论。当前的实现方式就是 Google 所提出来的“容器设计模式”,这也是本系列课程中的 Kubernetes 部分所需主要讲解的内容。
基础设施向云演进的过程
首先为大家介绍一下“不可变基础设施”的概念。其实,应用所依赖的基础设施也在经历一个向云演进的过程,举例而言,对于传统的应用基础设施而言,其实往往是可变的。
大家可能经常会干这样一件事情,比如需要发布或者更新一个软件,那么流程大致是这样的,先通过 SSH 连到服务器,然后手动升级或者降级软件包,逐个调整服务器上的配置文件,并且将新代码直接都部署到现有服务器上。因此,这套基础设施会不断地被调整和修改。
但是在云上,对“云”友好的应用基础设施是不可变的。
这种场景下的上述更新过程会这么做:一旦应用部署完成之后,那么这套应用基础设施就不会再修改了。如果需要更新,那么需要现更改公共镜像来构建新服务直接替换旧服务。而我们之所以能够实现直接替换,就是因为容器提供了自包含的环境(包含应用运行所需的所有依赖)。所以对于应用而言,完全不需要关心容器发生了什么变化,只需要把容器镜像本身修改掉就可以了。因此,对于云友好的基础设施是随时可以替换和更换的,这就是因为容器具有敏捷和一致性的能力,也就是云时代的应用基础设施。
所以,总结而言,云时代的基础设施就像是可以替代的“牲口”,可以随时替换;而传统的基础设施则是独一无二的“宠物”,需要细心呵护,这就体现出了云时代不可变基础设施的优点。
基础设施向云演进的意义
所以,像这样的基础设施向“不可变”演进的过程,为我们提供了两个非常重要的优点。
- 1、基础设施的一致性和可靠性。同样一个镜像,无论是在美国打开,在中国打开,还是在印度打开都是一样的。并且其中的 OS 环境对于应用而言都是一致的。而对于应用而言,它就不需要关心容器跑在哪里,这就是基础设施一致性非常重要的一个特征。
- 2、这样的镜像本身就是自包含的,其包含了应用运行所需要的所有依赖,因此也可以漂移到云上的任何一个位置。
此外,云原生的基础设施还提供了简单、可预测的部署和运维能力。由于现在有了镜像,应用还是自描述的,通过镜像运行起来的整个容器其实可以像 Kubernetes 的 Operator 技术一样将其做成自运维的,所以整个应用本身都是自包含的行为,使得其能够迁移到云上任何一个位置。这也使得整个流程的自动化变得非常容易。
应用本身也可以更好地扩容,从 1 个实例变成 100 个实例,进而变成 1 万个实例,这个过程对于容器化后的应用没有任何特殊的。最后,我们这时也能够通过不可变的基础设施来地快速周围的管控系统和支撑组件。因为,这些组件本身也是容器化的,是符合不可变基础设施这样一套理论的组件。
以上就是不可变基础设施为用户带来的最大的优点。
云原生关键技术点
当我们回过头来看云原生关键技术点或者说它所依赖的技术理论的时候,可以看到主要有这样的四个方向:
- 如何构建自包含、可定制的应用镜像;
- 能不能实现应用快速部署与隔离能力;
- 应用基础设施创建和销毁的自动化管理;
- 可复制的管控系统和支撑组件。
云原生(Cloud Native)的定义
Pivotal 是云原生应用的提出者,并推出了 Pivotal Cloud Foundry 云原生应用平台和 Spring 开源 Java 开发框架,成为云原生应用架构中先驱者和探路者。
Pivotal最初的定义
早在2015年Pivotal公司的Matt Stine写了一本叫做迁移到云原生应用架构的小册子,其中探讨了云原生应用架构的几个主要特征:
- 符合12因素应用
- 面向微服务架构
- 自服务敏捷架构
- 基于API的协作
- 抗脆弱性
我已于2017年翻译了本书,详见迁移到云原生应用架构。
CNCF最初的定义
到了2015年Google主导成立了云原生计算基金会(CNCF),起初CNCF对云原生(Cloud Native)的定义包含以下三个方面:
- 应用容器化
- 面向微服务架构
- 应用支持容器的编排调度
重定义
到了2018年,随着近几年来云原生生态的不断壮大,所有主流云计算供应商都加入了该基金会,且从Cloud Native Landscape中可以看出云原生有意蚕食原先非云原生应用的部分。CNCF基金会中的会员以及容纳的项目越来越多,该定义已经限制了云原生生态的发展,CNCF为云原生进行了重新定位。
以下是CNCF对云原生的重新定义(中英对照):
Cloud native technologies empower organizations to build and run scalable applications in modern, dynamic environments such as public, private, and hybrid clouds. Containers, service meshes, microservices, immutable infrastructure, and declarative APIs exemplify this approach.
云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中,构建和运行可弹性扩展的应用。云原生的代表技术包括容器、服务网格、微服务、不可变基础设施和声明式API。
These techniques enable loosely coupled systems that are resilient, manageable, and observable. Combined with robust automation, they allow engineers to make high-impact changes frequently and predictably with minimal toil.
这些技术能够构建容错性好、易于管理和便于观察的松耦合系统。结合可靠的自动化手段,云原生技术使工程师能够轻松地对系统作出频繁和可预测的重大变更。
The Cloud Native Computing Foundation seeks to drive adoption of this paradigm by fostering and sustaining an ecosystem of open source, vendor-neutral projects. We democratize state-of-the-art patterns to make these innovations accessible for everyone.
云原生计算基金会(CNCF)致力于培育和维护一个厂商中立的开源生态系统,来推广云原生技术。我们通过将最前沿的模式民主化,让这些创新为大众所用。
云原生架构定义
现在我们将探索云原生应用架构的几个主要特征,和这些特征是如何解决我们前面提到的使用云原生应用架构的动机。
12因素应用
12因素应用是一系列云原生应用架构的模式集合,最初由Heroku提出。这些模式可以用来说明什么样的应用才是云原生应用。它们关注速度、安全、通过声明式配置扩展、可横向扩展的无状态/无共享进程以及部署环境的整体松耦合。如Cloud Foundry、Heroku和Amazon ElasticBeanstalk都对部署12因素应用进行了专门的优化。
在12因素的背景下,应用(或者叫app)指的是独立可部署单元。组织中经常把一些互相协作的可部署单元称作一个应用。
12因素应用遵循以下模式:
代码库
每个可部署app在版本控制系统中都有一个独立的代码库,可以在不同的环境中部署多个实例。
依赖
App应该使用适当的工具(如Maven、Bundler、NPM)来对依赖进行显式的声明,而不该在部署环境中隐式的实现依赖。
配置
配置或其他随发布环境(如部署、staging、生产)而变更的部分应当作为操作系统级的环境变量注入。
后端服务
后端服务,例如数据库、消息代理应视为附加资源,并在所有环境中同等看待。
编译、发布、运行
构建一个可部署的app组件并将它与配置绑定,根据这个组件/配置的组合来启动一个或者多个进程,这两个阶段是严格分离的。
进程
该app执行一个或者多个无状态进程(例如master/work),它们之间不需要共享任何东西。任何需要的状态都置于后端服务(例如cache、对象存储等)。
端口绑定
该应用程序是独立的,并通过端口绑定(包括HTTP)导出任何/所有服务。
并发
并发通常通过水平扩展应用程序进程来实现(尽管如果需要的话进程也可以通过内部管理的线程多路复用来实现)。
可任意处置性
通过快速迅速启动和优雅的终止进程,可以最大程度上的实现鲁棒性。这些方面允许快速弹性缩放、部署更改和从崩溃中恢复。
开发/生产平等
通过保持开发、staging和生产环境尽可能的相同来实现持续交付和部署。
日志
不管理日志文件,将日志视为事件流,允许执行环境通过集中式服务收集、聚合、索引和分析事件。
管理进程
行政或管理类任务(如数据库迁移),应该在与app长期运行的相同的环境中一次性完成。
这些特性很适合快速部署应用程序,因为它们不需要对将要部署的环境做任何假定。对环境假设能够允许底层云平台使用简单而一致的机制,轻松实现自动化,快速配置新环境,并部署应用。以这种方式,十二因素应用模式能够帮我们优化应用的部署速度。
这些特性也很好地适用于突发需求,或者低成本地“丢弃”应用程序。应用程序环境本身是100%一次性的,因为任何应用程序状态,无论是内存还是持久性,都被提取到后端服务。这允许应用程序以易于自动化的非常简单和弹性的方式进行伸缩。在大多数情况下,底层平台只需将现有环境复制到所需的数目并启动进程。缩容是通过暂停正在运行的进程和删除环境来完成,无需设法地实现备份或以其他方式保存这些环境的状态。就这样,12因素应用模式帮助我们实现规模优化。
最后,应用程序的可处理性使得底层平台能够非常快速地从故障事件中恢复。
此外,将日志作为事件流处理能够极大程度上的增强应用程序运行时底层行为的可见性。
强制环境之间的等同、配置机制的一致性和后端服务管理使云平台能够为应用程序运行时架构的各个方面提供丰富的可见性。以这种方式,十二因素应用模式能够优化安全性。
微服务
微服务将单体业务系统分解为多个“仅做好一件事”的可独立部署的服务。这件事通常代表某项业务能力,或者最小可提供业务价值的“原子“服务单元。
微服务架构通过以下几种方式为速度、安全、可扩展性赋能:
- 当我们将业务领域分解为可独立部署的有限能力的环境的同时,也将相关的变更周期解耦。只要变更限于单一有限的环境,并且服务继续履行其现有合约,那么这些更改可以独立于与其他业务来进行开展和部署。结果是实现了更频繁和快速的部署,从而实现了持续的价值流动。
- 通过扩展部署组织本身可以加快部署。由于沟通和协调的开销,添加更多的人,往往会使软件构建变得更加苦难。 弗雷德·布鲁克斯(Fred Brooks,人月神话作者)很多年前就教导我们,在软件项目的晚期增加更多的人力将会时软件项目更加延期。 然而,我们可以通过在有限的环境中构建更多的沙箱,而不是将所有的开发者都放在同一个沙箱中。
- 由于学习业务领域和现有代码的认知负担减少,并建立了与较小团队的关系,因此我们添加到每个沙箱的新开发人员可以更快速地提高并变得更高效。
- 可以加快采用新技术的步伐。大型单体应用架构通常与对技术堆栈的长期保证有关。这些保证的存在是为了减轻采用新技术的风险。采用了错误的技术在单体架构中的代价会更高,因为这些错误可能会影响整个企业架构。如果我们可以在单个整体的范围内采用新技术,将隔离并最大限度地降低风险,就像隔离和最小运行时故障的风险一样。
- 微服务提供独立、高效的服务扩展。单体架构也可以扩展,但要求我们扩展所有组件,而不仅仅是那些负载较重的组件。当且仅当相关联的负载需要它时,微服务才会被缩放。
自服务敏捷架构
使用云原生应用架构的团队通常负责其应用的部署和持续运营。云原生应用的成功采纳者已经为团队提供了自服务平台。
正如我们创建业务能力团队为每个有界的环境构建微服务一样,我们还创建了一个能力小组,负责提供一个部署和运行这些微服务的平台。
这些平台中最大好处是为消费者提供主要的抽象层。通过基础架构即服务(IAAS),我们要求API创建虚拟服务器实例、网络和存储,然后应用各种形式的配置管理和自动化,以使我们的应用程序和支持服务能够运行。现在这种允许我们自定义应用和支持服务的平台正在不断涌现。
应用程序代码简单地以预构建的工件(可能是作为持续交付管道的一部分生成的)或Git远程的原始源代码的形式“推送”。 然后,平台构建应用程序工件,构建应用程序环境,部署应用程序,并启动必要的进程。 团队不必考虑他们的代码在哪里运行或如何到达那里,这些对用户都是透明得,因为平台会关注这些。
这样的模型同样适合于后端服务。需要数据库? 消息队列或邮件服务器? 只需要求平台来配合您的需求。平台现在支持各种SQL/NoSQL数据存储、消息队列、搜索引擎、缓存和其他重要的后端服务。这些服务实例然后可以“绑定”到您的应用程序,必要的凭据会自动注入到应用程序的环境中以供其使用。从而消除了大量凌乱而易出错的定制自动化。
这些平台还经常提供广泛的额外操作能力:
- 应用程序实例的自动化和按需扩展
- 应用健康管理
- 请求到或跨应用程序实例间的动态路由和负载均衡
- 日志和指标的聚合
这种工具的组合确保了能力团队能够根据敏捷原则开发和运行服务,从而实现速度,安全性和规模化。
基于API的协作
在云原生应用架构中,服务之间的唯一互动模式是通过已发布和版本化的API。这些API通常是具有JSON序列化的HTTP REST风格,但也可以是其他协议和序列化格式。
只要有需要,在不会破坏任何现有的API协议的前提下,团队就可以部署新的功能,而不需要与其他团队进行同步。自助服务基础设施平台的主要交互模式也是通过API,就像其他业务服务一样。供给、缩放和维护应用程序基础设施的方式不是通过提交单据,而是将这些请求提交给提供该服务的API。
通过消费者驱动的协议,可以在服务间交互的双方验证协议的合规性。服务消费者不能访问其依赖关系的私有实现细节,或者直接访问其依赖关系的数据存储。实际上,只允许有一个服务能够直接访问任何数据存储。这种强制解耦直接支持云原生的速度目标。
抗脆弱性
Nassim Taleb在他的Antifragile(Random House)一书中介绍了抗脆弱性的概念。如果脆弱性是受到压力源的弱化或破坏的质量系统,那么与之相反呢?许多人会以稳健性或弹性作出回应——在遭受压力时不会被破坏或变弱。然而,Taleb引入了与脆弱性相反的抗脆弱性概念,或者在受到压力源时变得更强的质量系统。什么系统会这样工作?联想下人体免疫系统,当接触病原体时,其免疫力变强,隔离时较弱。我们可以像这样建立架构吗?云原生架构的采用者们已经设法构建它们了。Netflix Simian Army项目就是个例子,其中著名的子模块“混沌猴”,它将随机故障注入到生产组件中,目的是识别和消除架构中的缺陷。通过明确地寻求应用架构中的弱点,注入故障并强制进行修复,架构自然会随着时间的推移而更大程度地收敛。
如果这篇文章帮助到了你,你可以请作者喝一杯咖啡
![](https://img2020.cnblogs.com/blog/938105/202010/938105-20201013171833350-276632012.png)