云原生的发展历程:不了解就落后了

发表时间: 2022-07-19 09:19

伴随着云计算的火热浪潮,云原生Cloud Native的概念应运而生,都 2022 年了,如果你还不懂云原生,那就真的 out 了。

既然都提到了云原生,却很少有人完整的说明什么是云原生。通过搜索找到的资料来看,云原生好像分布到方方面面,什么都能带上云,比如云+校园、云+工业等,那这些算是云原生吗?

什么是云原生?

云原生是一种构建运行应用程序的方法,是一套技术体系和方法论。云原生是一个组合词,CloudNative=Cloud+Native。Cloud表示应用程序在云上,包括数据,Native表示应用程序从设计开始就考虑在云上运行,充分利用云的弹性和分布式的优势。

可见,云原生并不是简单地使用云平台运行现有的应用程序,它是一种充分利用云计算优势对应用程序进行设计、实现、部署、交付和操作的应用架构方法。

云原生架构的主要特征

云原生 12 要素

1、基准代码:一份基准代码,多份部署

2、依赖:显示声明依赖关系

3、配置:应用配置存储在环境中,与代码分离

4、后端服务:将通过网络调用的其他后端服务当作应用的附加资源

5、构建、发布、运行:严格分离构建、发布和运行

6、进程:以一个或多个无状态进程运行应用

7、端口绑定:通过端口绑定提供服务

8、并发:通过进程模型进行扩展

9、易处理:快速启动和优雅终止的进程可以最大化应用的健壮性

10、开发环境和线上环境一致性:尽可能保证开发环境、预发环境和线上环境的一致性

11、日志:把日志当作事件流的汇总

12、管理进程:把后台管理任务当作一次性进程运行

这里强调一些我认为比较重要的要素:

  • 要素 2 依赖:这个要素值得特别提及,因为它在 Go 编程中可能没有那么重要。通常,云应用不应该依赖系统已经存在的任何必需的库或外部工具。应明确声明依赖性(例如,使用 Node.js 应用的 npm package.json文件),以便包管理器在部署应用的新实例时可以提取这些依赖。在 Go 中,应用部署通常为静态编译的二进制文件,其中已经包含所需要的库。然而,即使是 Go 也可能依赖外部工具,例如 C 库,这就需要容器引擎的帮助,例如 Docker
  • 要素 3 配置:配置可以是任何类型的数据,可能因不同的部署而不同个,例如外部服务和数据库的连接数据。这类数据可以通过环境变量或配置文件传递给应用。
  • 要素 4 后端服务:确保应用的依赖服务可以轻松替换,例如数据库地址,本地的mysql://root:root@localhost/test和生产的mysql://root:XXX@prod.XXXX.eu-central-1.rds.amazonaws.com
  • 要素 9 易处理:在云环境中,需要预期突然停止(例如,在规模缩小时会意外终止,在故障时会终止),要求应用具有快速启动时间(通常为几秒),允许快速部署新实例。此外,优雅终止是另一个要求。当服务器关闭时,操作系统通常会发送SIGTERM信号来通知应用关闭,应用可以捕获信号,完成当前处理的请求然后退出。

云原生计算基金会(CNCF)对云原生的定义:云原生技术有利于各组织在公有云、私有云和混合云等新型动态环境中构建和运行可弹性扩展的应用。

代表技术包括容器、服务网格、微服务、不可变基础设施和声明式 API。这些技术能够构建容错性好、易于管理和便于观察的松耦合系统,结合可靠的自动化手段,云原生技术能使工程师轻松对系统做出频繁和可预测的重大变更。

云原生技术

1、容器

容器是一种相对于虚拟机来说更加轻量级的虚拟化技术,能够提供一种可移植、可重用的方式来打包、分发和运行应用程序。容器提供的方式是标准化的,可以通过模板 Dockerfile 生成镜像,这种机制直接打包了应用运行所需要的整个操作系统(文件系统),从而保证了本地环境和云端环境的高度一致性。

例如,把一个 Java 虚拟机、Tomcat 服务以及应用程序本身打包到一个容器镜像,用户可以在基础设施环境上使用这个镜像启动容器并运行应用程序,这可以把容器运行的应用程序和基础设施环境隔离。

容器具有高度的可移植性,用户可以在本地开发,在测试、生产环境中运行同样的容器。

Docker 只是容器技术的实现,在新版的 kubernetes 中,已经不强依赖 Docker 了。

因为具有轻量级的隔离性,容器技术已然成为云原生时代应用程序开发、部署和运维的标准基础设置。使用容器技术开发和部署应用程序有如下好处:

  • 应用程序的创建和部署更敏捷
  • 可持续开发、集成、部署
  • 提供环境一致性
  • 提供应用程序可移植性
  • 资源利用率更高
  • 实现了资源隔离

容器技术大大简化了云原生应用程序的分发和部署,是云原生技术发展的基石。

2、微服务

微服务是一种软件架构方式,可以用微服务架构把一个大的单体应用按照功能模块拆分成多个独立的微服务,每个微服务只需实现一种功能,具有明确的边界。微服务专注于无状态和水平扩展,能够很好地与现代云环境配合使用。

微服务基于分布式架构,主要特点为:

  • 单一职责:微服务架构中的每个服务,都应符合高内聚、低耦合以及单一职责的业务逻辑单元、不同的微服务通过 REST 等形式的标准接口相互调用,进行灵活的通信和组合。
  • 独立:每个微服务都是独立的组件,可以被单独部署、测试、升级、发布。

基于分布式计算、可弹性扩展和组件自治的微服务,与云原生技术相辅相成,为应用程序的设计、开发和部署提供极大遍历。

  • 简化复杂应用:一个微服务只负责一个模块,降低了开发人员的心智负担,毕竟相对于完成一个大型应用程序,实现和理解一个只提供一个功能的小型应用程序容易很多。每个微服务都能单独开发,可以加快开发速度,提升敏捷性。
  • 简化应用部署:在大型应用中,即使只修改了一小段代码也需要对整个系统进行重新构建、部署、测试、交付,浪费了很多时间。而微服务可以对单独的某个组件进行构建、部署、测试、交付。
  • 灵活组合:在微服务架构中,可以重用一些已有的微服务组合成新的应用程序,降低应用开发成本。
  • 可扩展性:根据微服务不同的负载情况,可根据资源指标横向扩容
  • 技术异构性:通常在一个大型的应用程序中,不同模块具有不同的功能特点,可能需要不同团队使用不同技术栈开发。可以使用微服务拆分大型应用,只要对外开放接口不变,可以对某个微服务进行升级,其他服务不受影响。
  • 高可用性、高容错性:微服务独立部署和自治,当某个微服务出现故障时,其他微服务不受影响

虽然微服务具有这么多特点,但是需要有相应的技术成本,而众多的微服务也增加了运维的复杂度,恰当好处地拆分微服务也考验架构师的能力。

3、服务网格

随着微服务逐渐增多,大型的应用程序可能会变成成百上千个微服务互相调用,服务与服务内部互相通信,如何管理和监控服务的连接关系和保障服务通信,就成了一个挑战。服务网格(Service Mesh)可以作为服务间通信的基础设施层,能够解决上述问题。

服务网格是轻量级的网络代理,能够解耦应用程序的重试、超时、监控、追踪和服务发现等,能够做到应用微服务无感知,非侵入性。

服务网格的实现通常为服务提供一个代理实例,和应用微服务部署在环境中,这种模式成为 Sidecar 模式。也有最近大热的 ePBF 模式,能在操作系统内核中运行沙箱程序,被用于安全并有效地扩展内核的能力而无需修改内核代码或者加载内核模块。

与微服务架构相比,服务网格具有 3 个方面的优势

  • 可观测性:所有服务间通信都需要经过服务网格,所以可以捕获调用的相关指标数据,比如来源、目的地、协议、URL、状态码等,可供观测
  • 流量控制:服务网格可以为服务提供给智能路由、超时重试、熔断、流量镜像等控制能力。
  • 安全性:服务网格提供认证服务、加密服务间通信以及强制执行安全策略的能力。

4、DevOps

DevOps(Development & Operations,开发运维)是开发人员和运维人员之间合作,目的是高效地执行自动化交付软件和基础架构更改流程。

开发人员通常以 CICD(持续集成和持续交付)的方式,快速交付高质量应用程序。

持续集成指开发人员能频繁把开发人员合并到主干分支,这些开发分支都经过持续编译、构建和测试,能快速检查和验证其中存在的缺陷。

持续交付是软件产品可以稳定、持续地保持随时可发布的状态,目的是促进产品迭代更频繁,开发更敏捷,持续为用户创造价值。

  • 避免重复性劳动,减少人工出错:自动化部署可以把开发运维人员从应用程序集成、测试和部署等重复性劳动中解放出来,而且人工操作可能会延时出错
  • 频繁迭代:缩短了从开发、集成、测试、部署到交付的各个环节的时间,整个过程敏捷且持续,大大提高了应用程序的迭代效率
  • 提前发现问题:CICD 能够让开发和运维人员更早获知应用程序的变更情况,更早进入测试和验证阶段,也就能能早发现和解决问题。

5、不可变基础设施

在应用开发测试到上线过程中,应用通常需要被频繁部署到开发、测试和生产环境中,在传统的可变架构时代,需要管理员保证所有环境的一致性,而随着时间的推移,靠人工维护的环境很难保证环境一致性,而环境不一致可能会导致在开发环境运行没有问题,一到生产就报错的情况发生。这种由人工维护、经常被更改的环境就是我们常说的“可变基础设施”。

与之相对的就是不可变基础设施,指一个基础设施环境被创建后不接受任何方式的更新和修改,而这个基础设施可以作为模板来扩展出更多的基础设施。

不可变基础设施的优势在于能够保证多套基础设施的一致性和可靠性,而基础设施的创建和部署过程也是可预测的。在云原生架构中,借助 kubernetes 和容器技术,云原生不可变基础设施提供了一个全新的方式来实现应用交付。

  • 能提供应用交付效率:基于不可变基础设施的应用交付,能保证应用在各个环境上表现一致。
  • 能快速、可靠地水平扩展:基于不可变基础设施的配置模板,快速创建已有基础设施环境一致的新基础设施环境。
  • 能保证基础设施的快速更新和回滚:基于同一套基础设施模板,若某一环境被修改,可以快速回滚和恢复,若需要对所有环境升级,只需要更新模板就能升级。

6、声明式 API

在 kubernetes 中,声明式 API 就是指集群期望的运行状态,如果有任何与期望状态不一致的情况,kubernetes 会根据声明做出相应的动作来符合期望。

如果不使用声明式 API,就会需要增加和减少两个动作,会产生一致性等问题。

使用声明式 API 能够使系统更加健壮,当系统中组件出现问题,只需要查看声明式 API 的状态就能确定需要执行的操作。