乐趣区

关于云原生:云原生架构及演进

本文是由 AIOps 社区举办的《云原生架构演进》meetup 转录而来,嘉宾张晋涛,Apache APISIX PMC Kubernetes ingress-nginx reviewer,containerd/Docker/Helm/Kubernetes/KIND 等泛滥开源我的项目 contributor,『K8S 生态周报』的维护者。对 Docker 和 Kubernetes 等容器化技术有大量实际和深刻源码的钻研,业内多个出名大会讲师,PyCon China 外围组织者之一,写有《Kubernetes 上手实际》和《Docker 外围常识必知必会》等专栏

单体架构

什么是单体架构

顾名思义,单体架构是将所有的业务服务都放在一个单体中的业务逻辑耦合的架构。以上面这张图举例,咱们申请某个域名,DSN 返回相应域名的 IP 地址,用户会依据理论地址拜访相应的服务器,最初服务器会做出相应。这是一个最简略的单体架构案例。

单体架构的劣势

  • 简略,所有的业务逻辑都蕴含在一个大单体中
  • 开发疾速,不须要思考各组件之间的调用链关系
  • 部署简略,间接打一个 jar 包或 rpm 包

单体架构的劣势

不便于多人协同开发
在多人团队合作开发过程中,单体架构的劣势就逐步显现出来了,当你想新增某一个性能时,它会影响到某些函数。但其余开发者并不知道这些函数被批改了,那么很可能会呈现代码跑不起来。或者会造成逻辑上呈现问题。

所以在多人协同开发的我的项目中,试想一下对咱们而言,最好的状况是不是彼此之间不要紧耦合,都心愿将咱们相干的功能模块尽可能的拆分。

保护老本过高
在单体架构下吗,所有的服务都耦合在了一个大单体中,如果其中某个性能有 bug,很可能会导致整个服务的不可用,所以单体架构的爆炸半径特地大。此外,随着业务复杂度的晋升,你的开发成本会显著回升。

举个例子,在开发过程中,你须要思考某一些性能是否要调用这个函数,如果你确定调用,那么你要十分十分的小心,这时候你可能会想,最简略的方法就是我新加一个函数,长此以往你会发现,在一个大型单体利用中会隐含着很多冗余的代码,甚至是一些暗藏的 bug,随着代码规模的变大,这个单体利用的开发成本会变得特地高

部署老本昂扬
随着单体利用规模的扩充,它的部署老本会呈线性增长,你会发现它耗费的服务器等资源会变多。在后续老本保护层面,其老本是越来越大的

单体架构的演进

为了让用户的拜访性更好,常见的做法是加缓存,让用户每次申请的时候,能够从缓存中读取数据。这样能够缓解数据库的压力。

然而在加了缓存当前,须要思考的事件就多了,比方遇到了缓存生效、缓存过期、缓存被穿透等状况,你是否有应答预案。所以还有一种形式,就是对数据库做一些拓展,比方做集群,在外层加上 lb 负载平衡、加 CDN 等操作来晋升用户拜访的可用性,

还有一种形式就是做拆分,将一个大单体利用通过多模块形式拆分,但因为它不是真正意义上的齐全拆分,各模块之间还是耦合的。所以长此以往,随着咱们业务规模的逐渐变逐渐变大,技术债也将会越来越大。

微服务架构

与传统的单体架构比,微服务架构外围特点是服务绝对独立,形象力度小。从上面这张图咱们能够看出,像 account service,shopping service 等服务相互之间是独立的,没有强耦合性。以 account service 来举例,咱们发现它有一个 Account DB,这样做的益处吃,当我这个服务出问题时,短时间内是不会影响其余服务的。

但这一模式造成的一个最大难题就是,你的微服务的形象力度不好把控,很多开发者都常常遇到过,团队里的很有教训架构师都有一些集体喜爱的拆分模式。这是你可能会问,如果换一种拆分形式是否也能够?其实都能够的,只不过是在于你不同的形象力度造成的。

微服务架构最次要的劣势在于它的复杂度绝对可控,因为每个小的微服务之间相互独立,如果它产生了故障,它的爆炸半径要远小于单体架构。此外,每个服务之间须要通信,比方限流、熔断等这些惯例需要,当用户侧的流量上来时如果后端的服务没有及时扩容,这时候就要启动熔断和限流的策略,以避免出现缓存被击穿,甚至雪崩的状况呈现。

微服务架构的另一个益处是,每个微服务都能够应用不同的技术计划来开发,或者说应用不同的语言来开发,各服务之间只需满足接口调用的规定即可。那么微服务架构有劣势么?当然也是有的。最大的劣势在于,咱们将一个大的单体拆分了很多小的微服务,那么在部署上线的时候,所有的都微服务都要部署一遍,部署老本直线回升。

在后面咱们说过,每个服务都有它本人独立的 DB。那么在资源在用方面可能不肯定那么高,然而你在做资源布局的时候,必须要给它调配相干的资源。从这个层面看,咱们会发现微服务架构下的整体部署复杂度和资源占用都会变高。另一方面,如果你对微服务拆分的过细,会发现组件过多,保护老本增大,拆分的不够细,组件之间可能还存在耦合,那么这就是个失败的拆分。

云原生架构

云原生架构次要以容器化技术 docker 和 Kubernetes 为首的容器编排技术。docker 给咱们提供了容器镜像和资源隔离这两方面能力。以前开发,咱们交付的可能是源代码或者一个 jar 包,当初间接交付一个容器镜像。交付形式产生了扭转。

另一方面,容器为咱们提供了根本的资源隔离,开发者不须要去思考服务运行过程中,各服务之间的端口是否会呈现抵触。因为每个容器环境下,每个服务都有本人的 network name。这对上文中提到的微服务爱狗是十分好的终局计划。

试想,在原来的微服务架构下,咱们拆分了泛滥小的微服务,这些服务可能会有一些外部类的服务,那必定须要去一个监听端口,咱们也不会将所有的微服务全副部署在不同的机器上,这样在做服务拆分的时候,咱们还须要思考这些服务彼此之间的端口是否会抵触,如何防止抵触。但 docker 能够帮忙咱们防止这些问题。但另一方面,尽管 docker 提供了资源隔离的性能,然而咱们都晓得它利用的是 Linuc 内核中的 c group、name space 等能力去实现了,它并不具备分布式的能力。并不可能间接把我的某一个容器间接调度到另外的其余的一些容器。

所以在 2014 年,Google 正式开源了本人的容器编排引擎 XXX,给咱们提供资源调度的能力,容许咱们将某些服务从一台机器调度到其余的机器上。

另一个就是以 Kubernetes 为首的容器编排技术,咱们先来它的整体架构是什么,以下图为例,它的整体架构分成两个局部,右边是咱们的管制面,蕴含最外围的 API server,须要去解决所有内外部 API 的申请,以及 Controller Manager、etcd 等模块

另外一部分是 Node 节点,Node 节点在 Kubernetes 中是工作节点,蕴含 Kubelet 与 Kube-Proxy 两个次要模块,Kubelet 是管制某一个 pod 是否在集群的节点失常的启动,Kube-Proxy 负责流量的转发。

在云原生架构下,因为所有的利用都是容器化的,所以它都须要容器镜像的存在,所以 CI/CD 就成为了最次要的能力之一。其次在整个云原生的顶一下,云原生架构还蕴含可观测性、弹性伸缩等概念。

云原生架构劣势

在云原生架构体系下,因为利用部署全副都变成了容器化部署,所以开发者能够不在意这个服务到底如何进行镜像构建,这让咱们更容易进行标准化。另一方面,因为云原生架构提供了故障转移,弹性伸缩等性能,所以咱们的保护老本是升高的。

再有就是效率的晋升,在物理机时代,咱们想要减少正本数量,或者上线一个新的服务,须要做很多的事件。然而当初我嘛能够通过一条简略的命令就能够实现

云原生的劣势次要体现在复杂性,咱们能够发现,云原生架构蕴含很多组件,无论是它架构的复杂度,还是学习老本都是比拟高的,

云原生场景下的基础架构改革

容器化 VS 虚拟化
云原生场景下,最小的调度单元是一个 pod,咱们所部署的服务也都变成了容器,所以在这里咱们来比照下容器化与虚拟化之间的区别

以下图为例,左侧是容器化利用,右侧是虚拟化利用。对于容器化利用而言,在 infra 这一层是主机的操作系统,再之上是容器运行时。在这个过程中只有一个操作系统存在。然而对于虚拟化而言,咱们能够发现,每一个虚拟机都有本人的操作系统,所以它的资源耗费变得更高。

当另一方面,如果咱们的某个利用呈现安全漏洞,对于容器化技术而言,最典型的就是容器逃逸,也就是说某个攻击者从容器中浸透进去,攻打到主机上。然而这种状况根本不会产生在虚拟机上,相比于虚拟机,容器化技术带来的劣势是轻量级,但它的劣势是隔离性有余。

基础设施重点不同
在基础设施这一层面上,如 aps、oecd、manage schedule 等,它援用了大量的组件,本来这些组件咱们基本不须要。而且这些组件还有一些零碎级的依赖。咱们就会发现,这个基础设施不仅引入了很多组件,咱们还须要思考很多组件的依赖,这就导致了咱们的攻击面减少了。
举个例子,比方你有一个组件,它依赖于某些服务和库,那么这些服务和库、甚至咱们的操作系统也可能存在安全漏洞。所以在基础设施层面,咱们会发现,引入了大量组件带来了攻击面的减少。

另一方面,网络拓扑的复杂性也减少了,在 Kubernetes 中,有一个典型的概念—容器网络模型(CNI),咱们会发现,在整个 Kubernetes 生态中,咱们有十分多的选型能够抉择。这些选型,有的会带来整体的效率升高,有的 CNI 基于 Linux 内核,对 Linux 的版本有要求。所以你整个的网络拓扑要更简单

存储架构选型
下图是 Kubernetes 中的容器存储构造(CSI)的截图,咱们能够发现,外面的可选项十分多。这就意味着,当你在做存储架构的选型的时候,须要去思考很多个方面,比方它的兼容性、可扩大能力、性能、数据安全等等

举个例子,如果是你的业务说须要多端读写的,这种场景要如何去满足,它是否能够与 Kubernetes 来兼容。咱们都晓得 IO 的耗费是一个比拟大的性能损耗点,不同的存储计划选型会导致它的性能不一样。另一方面,当你的某一个正本失落时,要如何来保障这些数据的安全性,当你的某哥存储节点挂掉了,我的整个寒假须要恢复过来不受影响,这些都是须要在存储架构选型时须要思考的。

日志架构
在日志方面同样面临着很多问题,首先通过这张图,咱们能够看到,有的日志是通过外层代理来的,这是零碎的拜访日志,还有其余诸如利用日志、用户行为日志等等。首先日志起源就形形色色。

其次,日志的存储地位也各不相同。存储包含两个方面,一个是产生日志后,我要写在哪个中央。另一个是最终要把日志存储在哪里。依照 Kubernetes 举荐的形式,咱们将所有的日志都输入到规范输入中,在采集日志时,咱们只有把容器运行时日志策略配置好,就能够从宿主机中读取到对应的日志

但如果咱们不依照这种标准来做,而是把某个日志写到容器内的某个目录下,要如何采集这个日志?首先能想到的方法是,咱们能够去在咱们的利用容器旁边挂载一个 sidecar,或者对这个容器进行革新

另一方面,日志的采集伎俩也是多种多样的,比方 elk 等等,那么咱们要如何能力做到保护的组件足够简略,同时日志又比拟标准,而且须要破费的老本还比拟低,这是咱们须要思考的事件。最初咱们还须要思考,在日志架构中,须要对立采集组件、对立存储指标、对立存储地位、并对日志构造进行革新。咱们会发现前两个局部是比较简单的,因为只需替换相干的组件,然而存储地位和日志构造须要咱们的利用侧进行批改。所以利用革新这个过程是咱们须要去解决的一个十分苦楚的点。

总结一下,目前日志架构面临的问题次要有以下几点

  • 日志起源多样
  • 存储地位多样
  • 输入指标不同
  • 采集伎俩多样

监控架构的挑战

后面咱们有说到,Pod 生命周期广泛较短,业务监控数据量个别都很大。那么在数据可视化层面,有没有好用的工具呢?

现如今,云智慧已开源数据可视化编排平台 FlyFish。通过配置数据模型为用户提供上百种可视化图形组件,零编码即可实现合乎本人业务需要的炫酷可视化大屏。同时,FlyFish 也提供了灵便的拓展能力,反对组件开发、自定义函数与全局事件等配置,面向简单需要场景可能保障高效开发与交付。

点击下方地址链接,欢送大家给 FlyFish 点赞送 Star。参加组件开发,更有万元现金等你来拿。

  • GitHub 地址:https://github.com/CloudWise-…
  • Gitee 地址:https://gitee.com/CloudWise/f…
  • 万元现金福利:http://bbs.aiops.cloudwise.co…

微信扫描辨认下方二维码,备注【飞鱼】退出 AIOps 社区飞鱼开发者交换群,与 FlyFish 我的项目 PMC 面对面交换~

退出移动版