当前位置:   article > 正文

s19.云原生发展经历的阶段与未来发展趋势_云原生的发展阶段

云原生的发展阶段

1.云原生发展经历的阶段与未来发展趋势

1.1 云计算的发展历程

“云”中的资源在使用者看来是可以无限扩展的,并且可以随时获取,按需使用,随时扩展,按使用付费。这种特性经常被称为像水电一样使用IT基础设施。

在这里插入图片描述
这是从华为PPT中摘的图,华为把云计算的发展分为两阶段,第一个阶段叫做传统云计算IaaS时代,第二个阶段叫做新兴云计算云原生阶段,它把它从2013年以docker为代表的现代应用容器技术的诞生为起点到今天为止被称为云原生阶段,而且华为认为传统云计算就像现在我们早期用的在互联网上申请几个虚拟机这个时代认为只是个中间过渡阶段,它不是云计算发展的最终阶段和目标,注定这个阶段是要淹没在历史尘埃中的,真正的云计算就应该是云原生所倡导的这种理念,尤其是像serverless应用按需运行真正的弹性,就像函数一样被调用的时候才运行起来,不被调用它就完全不运行,那很显然这种模式就更具有代表性,所以我们说这才是我们真正的云计算发展拥有的这种状态,才是我们倡导的云所具有的特点和特性,这就是为什么各公有云都在抢占云原生的高域的原因。

1.2 “云原生”是什么?

  • Pivotal的定义

在这里插入图片描述
云原生到底是什么?云原生概念提示2013年,Privotal公司由Matt Stine首次提出这一概念,而后2015年Matt Stine在他的一本书叫做《迁移到云原生架构》当中定义什么叫云原生应用,大概有这样几个特点,第一12要素应用,接着微服务架构,你的应用应该满足这12要素特性,然后是微服务架构的,然后还能支持自服务的敏捷架构,基于API彼此之间服务协作,而后具有抗脆弱性的能力,而在2017年Matt Stine又重新修订了他对云原生架构的定义,我们称之为云原生架构特性定义的2.0版本,大概有这样几个特性,第一仍然是微服务,第二可观测,第三可部署,第四可测试,第五可处理,第六可替换,而Matt Stine的东家,Pivotal公司在其网站公开定义自己认为的云原生定义,它认为云原生应用应该具有这4个特性,第一DevOps是一种文化,第二CD要自动化部署的,而后微服务,第四个容器化,四大典型特性,利用容器和容器编排系统借助于微服务架构来拆分微服务,借助于CD和DevOps完成敏捷,这是Pivotal的定义。

  • CNCF的定义

在这里插入图片描述
2015年7月份CNCF成立,Cloud Native Computing Foundation(云原生计算基金会),它是LSF旗下的一个自基金会,就是Linux软件基金会旗下的,而后2015年8月份,云原生定义的初始版成立,他认为云原生应用应该有这3个特性,第一应用容器化,说白了就是容器化运行,第二面向微服务,第三容器编排,那就是k8s,后来2018年云原生定义1.0出现的时候,又增加了两个特性,做了些调整,容器化不变,微服务不变,服务网格被放了进来,声明式API和不可变基础设置被放了进来,容器编排和容器化被当做了一个概念就叫容器化,在使用k8s的时候要部署一个应用怎么部署,就是写一堆yaml,那yaml本身就是一种编程语言,遵循kubernetes的资源规范的API,写yaml也是个编程过程,所以这也是编程,只不过我们调用这个API是一个声明式的,因为你写完以后它究竟怎么完成功能的,靠kubernetes的三大核心组件,scheduler、controller-manager和apiserver,apiserver提供API的规范定义,controller-manager用来提供了一大堆的controller,scheduler用来调度,而controller就是支撑apiserver当中的API来落地的,比如我写了一个pod的定义,那这个pod怎么跑起来,靠kubelet来完成,kubelet其实也是个最核心的controller,你写一个deployment,deployment怎么跑,deployment controller来完成的,为什么API是这几个规范只能写这几个字段,因为deployment controller定义了就支撑这几种定义,因此我们可以理解为声明式API就是一种更智能的API,它有一定的智能性编程,自身具有一定的智能性,但这个智能不是强智能不是通用意义上的智能,它只是一种专用意义上的智能,只是在一个范围内能帮你完成部分功能,所以它只是专用领域当中的智能,所以说像deployment controller就是一个智能器,你可以理解为就是个智能程序,帮助你完成部署智能的,它提供给我们就是个API,所以我们认为声明式API是建立在命令式API上的更具有一定意义上的智能性的API,比如说我现在有一辆车给它下个指令让它从北京开到上海去,如果它是命令式API,你自己开车你对于前进的每一步都要规划好,你才能开到上海去,但如果是个声明式API,不但给了你一辆车上面还有个司机,你告诉它到上海去,是不是就完了,你可以理解为那个司机就是controller,但如果没有那个司机你就得自己一步步来完成,所以它的智能性是靠司机来完成的,但司机不能帮你解决其它问题,只能帮你解决开车从北京到上海这一个问题,所以K8S当中最关键的组件除了API之外就是controller,没有controller你寸步难行,以至于后来我们学CRD你只是定义个CRD没有用,除非你的CRD背后的所有功能都是基于我们背后的基础的已有的资源来完成的,否则的话它就几乎没有什么作用,你定义了一个东西它存到apiserver当中它能干什么,对应的实际意义是什么,很多时候都做不到,但也有一些资源它确实不需要什么实际意义,你比如像configmap,你定义了它存下来就完了,它确实不需要controller帮它来干什么,但是像pod、deployment这些就不行了,还有service,都需要各种各样的controller,有些只是数据的意义,它不需要controller,但有一些需要数据意义的就必须要controller,这就是声明式API,这就是为什么后来大家发现我们很多的传统应用像redis、mysql要想能够部署到k8s去用,你只是部署上去还像正常的那种访问方式访问mysql它其实没有什么意思,或者说没有太大意义,只是让k8s帮助你完成了mysql的编排而已,你部署个pod帮你跑起来了,所以后来很多第三方公司开发了mysql的operator,为什么呢,几个诉求,第一mysql自己就是个有状态应用,它也有自己的API,有状态应用它里边的每一个实例的角色功能和价值是不一样的,而且是独有的,所以每一个mysql集群和另外一个mysql集群哪怕是主从复制都有可能不一样,它无法通用,有状态无法通用,不像deployment对无状态都是一样的编排逻辑,所以我们的statefulset所形成的功能非常基础,你会发现我们用statefulset去编排有状态应用是做不到的,你还需要些大量的代码才能完成,你可以想象一样我做一个mysql集群,启了一个主节点一个master,后来在启一个pod作为一个slave,这个slave怎么加入到master中,你不得让它读里边的二进制日志,需要大量的中间操作才能完成,所以它没法通用,因此各种各样的有状态应用都需要operator,而operator是干什么的,其实就是对于把有状态应用的整个集群本身当做一个原子化的单元来管理,我用operator可以之间允许你请求创建一个集群,这个集群究竟有一个主几从你可以自己写好,而这是不是就是个CRD,所以从这个角度上来讲,它把mysql的有状态的运维CRD化了,就是所谓叫声明式API化,那个CRD就是个声明式API,而背后的实现过程靠operator来完成,但是mysql自己的API依然是原生的,这个你没法改变,因为程序员调的就是都是mysql自己的真实IP,那有朝一日没准DB全部下沉到K8S以上,完全通过声明式API对外提供,程序员写程序的时候可能就声明式API来调用了,当然这可能太远,所以我们说其实operator就是把我们的运维人员的运维经验给泛化,通用化,代码化了,有了一大堆的operator以后,它就相当于一个有经验的DBA了,像kafka的operator就相当于一个kafka的管理员,所以中间这部分的职能需求就越来越少,这就是CNCF给出的云原生1.0的定义。

1.3 那么,云原生究竟是什么?

  • 我们得到了一堆术语

    • 12要素应用、微服务架构、自服务敏捷架构、基于API协作、反脆弱性
    • 模块化、可观测、可部署、可测试、可处理、可替换
    • DevOps、CD、微服务和容器化
    • 容器、服务网格、微服务、不可变基础设施和声明式API

    在这里插入图片描述
    所谓云原生就指的是我们的应用程序一定是紧密结合云端的现实状况云端所拥有的能力,而后最大化的让我们应用程序能够发挥其价值的一种机制,为什么会提到这里的云原生或者云原生的术语会进化到今天而且为什么Pivotal这家公司有这么大的话语权。

1.4 从云原生拓荒者Netflix的故事说起

  • Netflix

    • 最初是一家以发行DVD为主营业务的公司
    • 2007年将主营业务模式转变为在线租赁和视频站,以适应互联网化的大趋势
    • 2008年起,公司即遇到了层出不穷的各类稳定性、扩容等问题
      • 2008年8月,Netflix主要数据库故障导致了三天的停机
    • 2009年后,流量激增下,这种问题更加严重
      在这里插入图片描述
      流量增长实在太快了,不停的买服务器,而且它们在买的时候应该很忐忑,它们做决策的时候想着买了一大堆服务器放那,真正要构建系统的时候一定是按照峰值的承载能力进行构建的,但是买完以后如果以后访问量变小了网站不受欢迎了,这些投入是不是就打水漂了,它们后来很忐忑买的时候可能会比较谨慎,但是这样以来你会发现它的流量可能会出现一些波动但总体趋势还是不断向上增长的,但是问题是在当时做决策的人是没有办法看到未来是什么样的,所以它们做决策一定会非常忐忑尽可能就着当时的需求来做,以至于它们就在不断的加服务器的过程当中很难受。
  • 亟待解决的核心问题:扩容、性能、可用性
    在这里插入图片描述
    因此在扩缩容方面就面临着很大的问题,性能问题,单体应用,最早期就是基于springboot这样的编程语言所编写的一个应用,另外就是可用性的问题,因为单体应用一崩就全崩了,所以后来它们就采样各式各样的办法来试图来解决这里的问题。

  • 解决方案

在这里插入图片描述
其中它们所采取的解决方案,它们的CTO在2013年的公开演讲中提出了它们当时解决思路是这样的,在今天为止我们可能在实践上摸不着门的时候,而在2013年它们已经上线了并且总结出来是这么解决问题的,第一主要要面对业务复杂多变的环境用过去系统的几年不变的状态这种模式那种团队那种架构去构建不合适了,所以它们要追求的目标就是一切向着敏捷而前进,它们采用了公有云上云,上云最能解决的问题就是扩容,可以按量买虚拟机实例,真正流量下降了无非把这些实例退回去就行了,这是公有云一个最大好处之一扩缩容变得非常非常便捷,看上去买云端服务器比自己买物理机算上去还贵,考虑到波峰波谷的弹性调度再加上决策时面临的窘境事实上这是能非常大的节约资源的。

第二微服务化,微服务化最大的好处在于两点,第一使用单体服务我们的系统规模越来越大我们的应用越来越复杂我们的团队规模越来越大,当一个团队规模变大以后它内部的摩擦一定是增大的,为什么天下大势合久必分原因是一样的,当你的内部人员变多了带来史例的方向未必是同向的,尤其人多了就需要大量的时间进行沟通,可能有十分之八的时间在沟通,只有十分之二的时间在干活,而且十分之二的干活可能还有十分之一的时间在摸鱼,生产效率非常非常低,因而最好的方法就是分而治之,你一个团队很小大家都很容易聚焦,在一个单团队规模内它们是很难产生效率的;

微服务化就是让关注点分离叫separation of concerns,我们过去关注点可能就在那里沟通去给项目定方向,现在在一个很小团队范围内整个服务的目标都很小,哪有那么多时间去负责协商我们要构建什么系统,至少在每个开发的决策层不用这么干了,所以业务层就被敏捷了,带来的好处开发效率极大的提升;

第二消除了单点,本来程序就是单点任何一个模块出现崩溃会导致整个系统全崩溃了,这是单体的一个缺陷,所以走向分布式化以后消除单点就指的是一个微服务崩了不至于影响其它微服务,它只要不在核心链路上甚至于根本就不产生什么影响,如果是核心链路的话可能会有一部分的影响,那我们可以降级,可以通过其它策略来解决,这就消除了单点;还有数据的反范式化,从过去都使用SQL这样的结构化数据转为使用半结构化的借助于nosql来实现,甚至是非结构化数据,当然更多应该是半结构化数据,这种半结构化数据好处在于云端亚马逊的AWS云上有很多所谓的半结构化的云端的弹性的分布式服务这种存储系统;

下一个叫open source by default,就是默认软件不在自己造了能有开源的就不重复自己造轮子,利用开源软件所以开发就敏捷了,我们开源站在已有项目的成果之上通过改进的方式来解决问题了;

通过持续部署选择continuous deployment让部署敏捷;

借助于DevOps这样的文化让每一个开发人员自行在提交代码以后执行构建和部署操作,从开发到部署上线直接一体贯通,免得还需要让开发和运维进行交互什么时候上线,很显然这两方肯定是要博弈的,因为开发的kpi是快速上线快速迭代,运维的kpi是稳定,它处于稳定的目的肯定不会让你上线,变更是稳定的大敌,这样子两方随时扯皮就会导致生产效率会低下,因此DevOps+CD这种机制让谁开发的谁部署整个业务链条给它贯通,就免得了刚才所说的协同过程,上线完了业务有问题有故障那是你自己的事,你的kpi可能会受影响,一两周有问题可能是运维的问题,给它卡一个时间点;

让应用的程序员自己构建自己上线,如果有问题它自己都会很忐忑战战兢兢了,它自己也不会开发一个有bug的代码不管三七二十一就抛给运维去上线出了问题让运维去背锅了这种事就不再容易发生,关键的几点上云利用底层强大的伸缩能力来解决扩缩容的问题,利用微服务来提高开发效率达到业务敏捷,利用数据的非结构化或者称作半结构化的模式来解脱数据本身的受限制的受约束的这种情形,后面有了所谓的开源利用开源软件达到开发敏捷,利用CD达到部署敏捷,利用DevOps和Run-what-you-wrote来实现从前到后的业务链的贯通,这些整个下来就是敏捷,这里还有一项叫做ChaoEngines这叫混沌引擎,混沌引擎它实际上是一个所谓的叫做是一个稳效可用于测试的工具,是一个可运行测试的工具。

  • 扩缘之空解决方案:上云

    • 当时云计算市场并没有多大的选择空间,很容易想到,Netflix基本没有悬念地会选择AWS
    • 2011年起,逐步将系统迁移到AWS上
    • 节约了87%的成本!

    在这里插入图片描述
    Netflix后来总结说正是因为上云,2011年起,逐步将系统迁移到AWS上,到2013年的时候它们在做测算的时候就已经节约了87%的成本,这是多么显著的一笔买卖,所以扩缩容的问题就通过上云这种方式来解决了,我们也不需要买太多的服务器,我们按照可知当时的量来买就行了,遇到波峰的时候无非就是加节点,可以开发一个所谓自己的流量监控的平台一个节点调AWS云的API接口,当流量变大的时候就临时加节点,利用自己打好的镜像加节点,负载均衡扩容不就行了,当流量下来的时候缩容就行了,所以这个时候需要的是一个云管平台,能够尝试着利用云的接口根据现在流量需求来完成动态扩缩容,但开发出这个平台还需要相对功夫的,最大的好处是资源敏捷了。

  • “上云”之后的艰难决策

    • 系统重构:分布式、微服务化
    • 挑战:全新的安全、运维和组织模型
      在这里插入图片描述
      一旦采用微服务就是上图所示架构体系,而当时最为主流的java开发框架不就是spring,也包括后来的springboot和springcloud,但事实上Netflix在探索的时候springcloud发布是在2014年,springboot也是在2014年发布的,在此之前所用的框架就是spring,Netflix在自己摸索的基础之上也对它做了一些改进它们就开发了很多很多的服务来解决这类问题,一旦微服务化就会产生一个非常严重的可用性问题,虽然它消除了单点没错,但整个结构复杂了。
  • 分布式系统的可用性问题

    • 随时可能发生的级联故障
    • 整体可用性的不可控
      在这里插入图片描述
      复杂到什么程度,假如一个微服务它的可用性是99%,如果定义了500个微服务,整体系统的可用性是多少,是99%的500次方算下来就只有0.657%,可用性是急剧下降的,你的每一个服务都有可能因为节点网络应用本身产生故障,所以达到可用性99%虽然看上去不高,差不多1年不在线的时间也就3.65天左右,如果达到99.99%缩小了100倍,多一个9的提升所需要的投入资源和力量是巨大的,以99%来衡量看上去就不低了,但是你整体系统可用性是非常低的,因为你的任何一个环节都可能会出故障,怎么去解决问题,所以很容易产生级联故障的,任何一个服务的故障很可能会导致整体故障,事实上的结果可能会更严重,原因在于像上图的链条当中最后一个sinpoDB被调用了,如果sinpoDB down了它前面的服务假如叫C,C的服务就被阻塞了,那B也就被阻塞了,A也就被阻塞了,所以这整个调用链路就被阻塞了,同样的一个请求又被阻塞一个再来个请求又被阻塞一个最终资源会被耗尽,整个服务就会产生级联故障最终连雪崩掉都有可能,因而要想办法消除这种局部性故障,在讲envoy的时候将要消解局部性故障,envoy有多少种办法来解决,超时、重试、熔断等解决办法。
  • 提升可用性的策略(反脆弱):弹性处理局部故障

    • 快速失效(Fail Fast)和故障转移(Failover)
      • 超时并重新请求,由调度器将请求发往另一个副本{冗余}
    • 优雅降级
      • 所有副本都故障时,“熔断”上游服务,当前应用以“降级”形式继续提供服务
    • 金丝雀发布
      • 变更是导致脆弱更重要的原因,任何服务上线新版本时都应该基于灰度模式进行
        在这里插入图片描述
        Netflix近乎10年之前它们就探索出来了这种解决逻辑,在微服务的程序当中你必须得做,原因在于任何一个服务的可用性都不可能是100%,这样会导致系统的整体可用性是极低的,所以要必须弹性处理局部故障,你只要不做就没办法微服务化,微服务化就是噩梦,它探索出来的常用解决方案大概有以下几个,首先叫快速失败,如果一个服务A调服务B调服务C,如果服务C被阻塞了服务C出了问题了,如果说B一直在这里阻塞等着A也就被阻塞了,所以说通用的调用过程被阻塞的链条会越来越多整个服务就会崩掉的,为了避免这样的问题怎么做呢,叫快速失败,每个服务之间相互调用的时候设置超时,B调C我最多等你1毫秒,如果1毫秒不能返回就超时,超时以后要重试,你一重试这个调用可能就会被调度器调度到其它实例上去了,C的实例可能不止一个,我们阻塞的时候可能阻塞某一个实例上了,一重试故障转移,被冗余的同一个集群中的其它实例所处理,如果这个实例只要没故障这就通过所谓的快速失败和故障转移或者重试来解决问题了;

如果说B调C的时候发的第一个实例因为超时重试以后又被调到第二个实例又超时了怎么办,一共只有两个实例全超时了,所有副本都故障了就熔断上游服务,因为上游服务重试几次仍然都不能有服务我认为你的上游服务就可能出现暂时性故障了,现在再反复的重试会带来什么后果,假如后端服务假如就因为压力过大而无法响应,这里不停的重试会使后端的压力越来越大,这个结果肯定是恶化的,堆积的请求一定会越来越多,为了避免这样的问题怎么办,熔断别请求了给它腾出一些时间来处理那些积压的请求,等它时间腾出来可能就又能提供服务了,所以说要有熔断的逻辑来解决,而且熔断是怎么做的,正常服务我们反复请求已经有问题了那我们就熔断,熔断一段时间可能是30秒钟,30秒之后半打开发一个请求看对方有没有响应,有响应就直接熔断器就关闭了,就不用再熔断了,正常就表示服务又恢复了,如果说还没有响应熔断器再继续打开就不再重试了,只是测试性的打开以免再带去积压的请求,这就是熔断,所以说上游副本都故障的时候我们要熔断,熔断时B怎么办因为它要请求C得不到服务,就降级,以残缺的方式来运行,正常情况下B要得到C的内容以后把结果响应给A才能展示给用户的,但现在得不到C的内容,那B就只能以残缺不全的方式运行,然后在响应给A,什么叫残缺不全,一个电商的调用链条当中正常情况下可能用户浏览商品然后进行交易支付,支付完以后还可能要进行评价,下一步可能进行评价,调B和C两个服务,很显然如果B调用不了这里就无法完成了,这是核心链路,但是C如果不能评价了,评价服务出问题了不影响交易这好像也没太大的严重影响,只是告诉用户暂时不能评论了,对于用户而言这好像也不是什么致命的结果,用户恐怕也不会特别介意,所以如果说这里需要降级的时候有一个前提如果是核心链路的话降级不了核心降级就相当于整个服务就废了,或者也可以降级到接近残废的方式,既然不能交易了整个网站可以浏览不能买这也算是一种降级,暂时只能看你可以加购物车就是不能支付这似乎看上去也没太严重的问题,但对于公司来讲是很严重的,不能交易肯定是大事,但至少认为这是通过降级能解决的,但是C真正不会产生什么致命影响,无非就是不能评论了,过段时间评论修复后再上线再进行评论就好了,这就是所谓的叫降级的处理逻辑,正常我们的系统设计也应该是这样的,甚至以我们的系统控制逻辑当中对每个服务都有一个开关,比如当C这个服务实在是请求有问题的时候我们不让它熔断我们自己直接把这个开关给关掉这是一种方案,其实我们的调用链条当中还有另外一个重要环节,有些场景降级也可能不会那么致命,比如D是库存,当我们去买任何一个东西加购物车的时候你得知道库存有多少是不是能满足我们的购买需求,当库存服务出现问题了怎么办,如果库存有问题得不到响应了,我们展示给用户的时候随便给它展示一个值行不行,假如说我们库存有6个了用户下单10个,我们无非就是在上游采购商那再采购几个想办法解决问题不就是了,这其实也不算是什么致命的结果,只要你差别不太大,还有个办法可以缓存,这种查询库存是多少个可以把它放到缓存里边,从缓存读数据,虽然上游数据无法验证缓存的数据是否精确与否,但至少对应的缓存响应给用户如果有那么一点点差别在业务层进行处理似乎也不算有太过于致命的结果,这也是一种降级的处理方案,为什么要熔断,熔断以后要怎么办,这事实上不是运维视角能解决的问题,我们需要在开发在整个系统架构上想办法要解决的问题,你要有降级逻辑,要有熔断机制来解决,envoy支持熔断的,但envoy自己却没办法降级,能否降级取决于业务;

另外一个就是金丝雀发布,变更是导致脆弱的最主要原因之一,也是最常见原因,所以任何服务上线新版本的时候都应该以灰度方式基于金丝雀发布进行,这是最合理的做法,这是最为常用可用性策略了,基于灰度你可以理解envoy也支持很独特的逻辑,上线一个新版本只引1%的流量进行测试,新版本无论在线下怎么测也未必能测出来所有bug,因为它跟真实流量是不一样的,以至于后来很多大型公司测流量测应用的时候就不会在线下测了,集成测试模块化测试这些都没问题以后,直接把版本发到线上去,引一小部分真实流量进行测试,流量镜像测试对线上没有任何影响的,流量镜像也没什么问题了测试好像也没有太大问题那就引一部分真实流量进来做流量切割,流量切割以后也没问题那一部分就是金丝雀了,还没有问题通过流量迁移的方式把流量逐部的全迁上来不就行了,这里可以基于灰度基于蓝绿都行,至于后端是蓝绿提供的还是灰度提供的那是后端部署的逻辑,这不是发布逻辑,发布你可以理解为流量是怎么引入进来的怎么分配的,部署是后端系统是怎么提供上来的,事实上Netflix早些年在探索的当中就是利用这些方式来解决问题的,而且它们在这里的所有逻辑当中有个重要的前提就是冗余,故障转移肯定要冗余,这是最基本的逻辑叫副本,那在同一个机房中跨区域同时要跨地域在多机房当中部署系统,这样确保某一个地域的机房出现了问题在其它机房当中的服务一样能提供,这叫多地多中心多机房,你的主机没出问题你的骨干网出问题了或者机房停电了这种情况也不能说不会发生,在可用性要求非常高的场景当中这种多机房的部署应该还是很关键的,但多机房可能会涉及到数据同步的问题。

  • 数据持久性

    • 将非必须的RDBMS转换为分布式的NoSQL系统
    • 并借助于S3的快照进行数据备份

    在这里插入图片描述
    Netflix直接把非必须的RDBMS转换为分布式的NoSQL系统,直接利用亚马逊的SimpleDB,而且将数据放到S3存储系统之上利用S3的快照执行安全的云端备份,越来越依赖云的用的是分布式的Cassandra这是一种nosql系统,把Relational的数据全转换成nosql数据格式来进行存放,而且这是依赖于云端的能力的,这样就不用花时间对数据库不断的进行做容量规划,因为业务增长很快数据库容量规划也是个大问题,就不说线上系统容量规划的问题,数据量增长太快了,在物理服务器上数据库容量当时规划不够磁盘小了这是一个很难受的事情,而在云端的好处在于存储空间可以弹性扩大,所以这也解决了存储的问题,更何况用分布式数据库可以加节点来解决问题,这些在早期relational这种RDBMS的时候事实上是很难解决的。

  • 检测系统可用性:混沌工程

    • 最初的实现:随机终止在生产环境中运行的EC2实例,以快速了解正在构建的服务是否健壮,有足够的弹性,可以容忍计划外的故障等

在这里插入图片描述
我们用了故障局部处理的方式来提升可用性,但是系统通过冗余加局部故障处理逻辑究竟是不是足够可靠呢,我们也不知道,那怎么办,做测试,事实上混沌工程是系统可用性测试的一种手段,最初的实现,随机终止在生产环境中运行的EC2实例,EC2是亚马逊云的虚拟机,随机停几个类似于模拟拔网线,看看服务是不是能够正常工作,早期做故障处理演练真的是在机房拔服务器网线,但现在有了这样的云端环境以后直接通过混沌工程的方式直接去断掉EC2的连接就完了,这比拔网线效率要高的多,测试的结果展现的速度也要快很多,当然也很真实,这是混沌工程的逻辑是可用性测试的,因而跟流量镜像、混沌工程目标都是用来线上测试逻辑的,包括流量分割也算得上是其中的一部分但是它也是发布的逻辑。

  • 应用性能监控和分布式链路跟踪

在这里插入图片描述
日志采集指标采集都是单点的,系统都是面向一个节点离散的方式,采集完后你想分析它们的关联关系是做不到的,只有分布式链路跟踪才能做到去跟踪整个请求链路当中的关联关系,它能够跟踪并记录关联关系,很显然在分布式的系统当中这种分布式链路追踪应该是个基本组件,是基本的运维组件,没有它很多问题都很难定位,其实在2013年之前Netflix就已经开始使用这样的工具来完成相应的功能了。

  • 运维模型

    • 集中式 --> 分布式
  • 发布模型

    • 基于AMI(Amazon Machine Image)的红黑部署
    • “不可变基础设施”:每次变更都要通过发布进行,不允许通过SSH等连接到主机上进行变更操作

    在这里插入图片描述
    这么一圈探索下来Netflix的运维模型既然微服务化了就不需要一个集中式的运维团队了,它的运维模式就从集中式走向了分布式,从最初的集中式运维团队转换成了“Dev teams push production chanages on own schedule;no central coordination”(开发团队按自己的时间表推动生产变更;没有中央协调);在2013年之前Netflix就基于AMI的红黑部署发布模式,红黑部署也就是蓝绿部署,我们在云端当时docker技术还没有诞生的情况之下要启动一个虚拟机无非就是创建一个虚拟机实例选择一个镜像它就能起来了,它们的发布就做成了需要发布的时候直接把应用打成虚拟机镜像叫AMI,当需要发布新办法的时候直接基于新的虚拟机镜像启动新的实例而后逐步下线老的实例来做的,模拟不可变基础设施,严禁任何人通过SSH连到主机上去做任何变更操作,因为那不可追溯不可复现没办法把它重新恢复回来,它在那个时候就已经实施这种策略了,只不过那个时候的代价很大,那个时候AMI镜像可能就动辄几个G,这几个G的镜像还有一个坏处是极易被公有云厂商锁定的,很多公有云厂商它的格式互不兼容,它的虚拟机格式也不兼容,所以部署在亚马逊云上这种合作你不可能一直不出事,将来出事了想换个公有云厂商那都是很麻烦的事。

  • 团队的演进

  • 在这里插入图片描述

  • 最终实现的系统架构示意图

在这里插入图片描述
这是Netflix最终所实现的系统架构,生于云长与云,它就利用亚马逊云的各种各样存储、消息队列、软负载均衡、前端负载均衡器等各种组件来构建它们自己的线上系统,当然这里边可能还有复杂的云管系统,用来编排整个内部的服务的一种组合关系逻辑关系业务关系的管理都要靠这个系统来实现,这是与云端深度耦合的,会被公有云厂商锁定,等它2013年通过公开的演进把这个故事发表出来以后讲完以后很多其它的一线厂商都很有兴趣,它们也试图来想象一下Netflix是怎么干的自己摸索,因为Netflix没有把自己的技术系公开出来,它只能根据这个PPT来揣测Netflix是怎么干的然后自己摸索着去干,但是它们都很疑虑的一点就在于2013年前后可选的公有云厂商很少,尤其对我们来讲你可选择的余地就几乎不存在,这时候我们也想探索也想使用怎么办。

1.5 容器技术和Spring Clound框架的诞生

  • Netflix以上故事发生的时间点:2013年之前
  • 2013年这一年
    • 因不想被公有云厂商绑定,OpenStack项目的展开正如火如荼
    • VMWare、EMC和通用资本合资成立Pivotal公司
      • VMWare将所有的Spring项目都转入Pivotal公司,同年12月,Pivotal发布Spring框架4.0
        • 2009年,Vmware收购运行着Java社区最热火的框架Spring的公司SpringSource,以及Paas供应商Cloud Foundry
      • 随后的2014年,Pivotal发布Spring Boot 1.0
        • 用来简化新Spring应用的初始搭建以及开发过程
        • 它能够让基于Spring的开发、测试、配置、部署和监控都变得更加简便
      • 2014年10月,Pivotal发布了第一个Spring Cloud版本
        • 一系列框架的有序集合
        • 它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务注册和发现、配置中心、消息总线、负载均衡、断路器、数据监控等,都可以用Spring Boot的开发风格做到一键启动和部署
      • Spring Cloud只是抽象模型,是规范,Netflix的实现是Spring Cloud Netflix是其早期最终的实现之一
    • Docker开源项目诞生
      • 创造性的使用Image技术,将“系统容器”带入了“应用容器”时代
      • 几乎是从根本上,解决了IaaS时期“跨云难(虚拟机和镜像迁移、共享等)”的问题

1.6 Spring Cloud的核心目标

  • Spring Cloud关心的要素

在这里插入图片描述
微服务关心的要素,名满江湖的Spring Cloud Netflix实现微服务框架当中解决了局部性故障的问题,API网关叫Zuul,Hystrix实现熔断的,服务注册服务发现的,配置中心,认证的,服务发现Eureka,还有Ribbon等等,日志收集用的ELK Stack,监控用的Turbine,关注点有Config Managerment(配置管理),Service Discovery & LB(服务发现负载均衡),Resilience & Fault Tolerance(服务弹性和容错),API Management(API管理),Service Security(服务安全),Centralized Logging(中心化日志),Centralized Metrics(中心化的指标服务),Distributed Tracing(分布式链路追踪),Scheduling & Deployment(调度和部署),Auto Scaling & Self Healing(自动化的弹性和自愈能力),进展到2014、2015年前后微服务所需要的框架主体能力基本上就已经定义出来了,这些主体能力是什么,跟我们应用的业务逻辑有关系吗,没有任何关系,这只是服务治理的所需要的能力,它需要的是一种底层能力,这是一种高级网络机制,它不是业务本身应该关注的问题,但那个时候Spring Cloud框架当中这些能力在代码当中放的,后来它做成了SDK,要基于Spring Cloud代码开发的话要调SDK把这些功能内置进去,这有一个极大问题当SDK需要更新的时候所有的代码都要改一下,这是个极大的麻烦。

1.7 市面上主流的Spring Cloud的实现

  • Spring Cloud Netflix ≠ Spring Cloud
    在这里插入图片描述

1.8 12 factor application(12要素应用)

  • 2015年提出的12要素应用
  • 到底表达了什么?
    • 运行标准
      • Codebase (代码库)
      • Disposability (可处置性)
      • Dev/Prod Parity (开发/产品 平等)
    • 编排标准
      • Dependencics (依赖性)
      • Processes (进程)
      • Port Binding (端口绑定)
    • 弹性伸缩标准
      • Processes (进程)
      • Concurrency (并发性)
    • CI/CD机制
      • Build、Release and Run (构建、发布和运行)
    • 监控机制
      • Logs (日志)
      • Telemetry (遥测)

在这里插入图片描述

1.9 第一阶段的“云原生”小结

在这里插入图片描述
Netflix在它的探索之上利用公有云实现了统一的云资源管理完成了资源敏捷,同时通过调用云端的各种中间件包括数据库系统、分布式缓存系统和消息队列使得运维的精力从底层的资源管理上就是硬件的管理上、扩缩容的管理上极大的解脱出来了,让团队可以专注于微服务的研发,但是微服务框架Netflix当时并没有自己在探索,而Netflix本身就不是一个ToB的公司,它并不关系服务框架是不是真正能够规范出来,关系框架规范的实际上是pivolot,它在一直定义规范试图能为整个江湖提供一个统一的玩法,这是当时的状况。

1.10 Kubernetes横空出世

  • Kubernetes称为事实上的编排标准
    • 它为何这般茁壮?
      • Spring Cloud仅限于java,而Kubernetes适用于所有编排语言,且解决了更广泛的MSA问题
      • Kubernetes还支持配置环境、设置资源约束、RBAC、管理应用程序生命周期、启用自动扩展和自我修复等,自带反脆弱能力

在这里插入图片描述

1.11 Kubernetes和Spring Cloud

  • Kubernetes的问题
    • 没有针对不同的平台(例如Spring Cloud for JVM)进行优化
    • 非以开发人员为中心的平台,对DevOps目标的用户具有更友好的特性

在这里插入图片描述

1.12 第二阶段的“云原生”小结

在这里插入图片描述
到了这个时代云原生已经进化到第二个阶段了,因为至少就再也不用被公有云绑定了,不管你使用什么样的公有云服务,只需要在公有云上部署一个kubernetes,无非就是在使用微服务框架来编排微服务而已,至于它是不是被绑定的此处不关心,但至少已经不会被公有云厂商绑定了,CNCF当中所定义的要点就是要提供一个不会被公有云厂商绑定的统一的、易于迁移的这么一个微服务框架,到这个时代人们探索的微服务或者现代的分布式的系统的开发依然还处于被绑定到微服务框架上这个很尴尬的局面上。

1.13 微服务治理框架

  • 为了克服服务通信和治理的复杂性,例如服务发现、融合、节流和端到端跟踪的挑战,需要用到专门的微服务治理框架

    • 微服务框架,如HSF、Dubbo或Spring Cloud,将这些能力打包成代码库,形成SDK
    • 程序员开发微服务时,将这些代码库内置于应用程序中,并随应用程序一起发布和维护
  • 存在问题:库模型可能会抽象出满足微服务架构所需要的特性,但它本身仍然是一个需要维护的组件

    • 学习和使用库需要相当程度力量的投入
    • 本质上,服务通信和治理是横向连接不同部门的系统,因此与业务逻辑是正交的;但是,在微服务架构中,实现和生命周期是与业务逻辑耦合的,微服务框架的升级会导致整个服务应用的重新构建和重新部署
    • 代码库通常与特定语言绑定,因此难以支持企业应用程序的多语言实现

    在这里插入图片描述
    为了克服通信和服务治理的负责性,比如像服务发现、融合、限流,还有端到端跟踪的挑战,那我们这个时候就需要用到专门的服务治理框架,微服务框架有很多,像HSF、Dubbo 或 Spring Cloud,为了便于人们每一个团队,以微服务的理念开发出来微服务程序来,所以它把这些功能都通过框架,通过SDK来解决了,通过库来解决,所以我们作为程序员写程序的时候,我们只需要载入SDK,然后再去写自己的业务逻辑(Business Logic),形成应用程序就可以了,但这里有一个最大的问题,因为代码库是要内置于应用程序中的,因为基于这种方式必须把这些打包的时候这些库必须要跟应用程序放在一起运行,那我们要想基于某种SDK写程序,你必须对SDK有充分的了解,还得学习SDK才行,所以你要用基于dubbo开发,就要去学dubbo各种library当中的用法和使用,要基于spring cloud开发一样的逻辑,所以这里的都是由学习成本的,我们的程序员转型到这种开发上,你不但要熟悉自己的业务,还要熟悉SDK,所以我们说这就是它存在的一个巨大的问题,而这种我们就称为库模型,它可能会抽象出满足微服务架构所需要的特性,但是库本身依然是需要维护的组件,这维护要体现这样几个方面,第一学习和使用库是需要相当程度精力的投入,还有本质上,服务通信和治理是横向连接不同部门的系统,Business Logic和Library是正交的,也就意味着二者之间本身是不需要融合在一起的,但是在微服务架构中实现和生命周期是与业务逻辑耦合的,因为你基于SDK必须要打包到一个应用程序当中,所以这样以来会导致什么问题,你的微服务框架的升级,比如dubbo从2.1升级到2.2你会导致整个服务应用程序都要重新构建和重新部署,要不然你的库版本不协同,这就是我们早期服务治理的时候它面临的一个麻烦,一个最大问题,还有代码可以通常是有特定语言绑定的,像dubbo它支持的语言有限,还有spring cloud更是如此,所以它很难支持企业应用程序的多语言实现,但是一个企业一个庞大的好多团队,不同团队没准采用的是不同语言,现在我们要统一到一个分布式架构当中,一个微服务框架当中,大家统一再去学某一种特定语言的SDK,使用某一个特定语言来研发,没准这种困难就已经吓退了很大一批人,所以我们说服务治理框架这种问题在早期,至少在过去的某一段时间当中我们确实就是靠dobbo和spring cloud来解决问题的,但人们发现了问题开始来试图解决问题,怎么解决问题?

1.14 Sidecar

  • 下一个合乎逻辑的步骤

    • 将库中的功能整合进Network Stack是不可能的,许多从业者找到的解决方案是使用一个小巧的透明代理来实现
    • 使用Sidecar以辅助进程的方式,在应用程序旁边提供高级网络功能
  • Sidecar

    • 让服务集中解决业务逻辑的问题,网络相关的功能则与业务逻辑剥离,并封装为独立的运行单元并作为服务的反向透明代理,从而不再与业务紧密关联
    • 换句话说,微服务的业务程序独立运行,而网络功能则以独立的代理层工作于客户端与服务之间;专门为代理的服务提供熔断、限流、追踪、指标采集和服务发现等功能
      在这里插入图片描述
      下一个合乎逻辑的步骤,人们就开始想,既然Business Logic和Library是正交的正交的就把二者拆开,不需要放在同一个应用程序来完成,我们基于sidecar,大家学过k8s都知道sidecar的概念,这就是我们所谓的叫做容器模型,或者叫容器pattern当中必然面临的一个问题,我们的容器部署当中,有几个pattern有sidecar模式、adapter模式、Ambassador模式,比较著名的几个代表就所谓的叫边车模式、适配器模式、大使模式,它分别用于让我们的应用程序来适配到周边环境当中去的,一是自己访问别人,一是别人访问自己等等,sidecar就是这里边一个非常著名的代表,这里边要干什么,就是把刚才服务的实现既然是正交的既然跟业务逻辑本身没有强耦合关系,那我就把它独立成一个独立的进程来运行岂不是更好,那因此我们对于没一个应用程序都在这个应用程序的周边部署一个sidecar,让这个sidecar专职从事来完成我们要想构建分布式应用当中要解决的这些高级的网络问题,这里的sidecar要解决的只是高级的分布式协同中的只是网络层面的问题,第一叫Circuit Breaker叫断路器,还有Service Discovery我们称为服务发现,这里边典型列了两个,其实它只是称之为叫高级网络应用网络中的功能的组成部分,那因此我们把这部分独立出来,有一个单独的应用程序,不管它使用什么语言单独的应用程序来开发,并且通过某一个特定的协议接口给它共享出来,或者给它暴露出来,比如我们就通过http协议暴露出来,那因此我们的应用程序业务逻辑,当需要与我们的微服务体系相协同的时候它只需要通过以sidecar模式运行的组件进行交互就可以了,也就是说无论它去请求别人的服务还是响应客户端请求的时候都一律通过sidecar代理来完成,所以从某种角度上来讲,我们的sidecar就成了专用的运行与每个服务周边的代理应用程序,这个代理负责我们完成这个应用程序所需要完成的各种功能,服务发现、熔断、限流、降级、超时等等,全靠这一个组件来实现,而且二者之间的这种耦合关系是松耦合的,刚才说过是基于应用层协议http或者其它协议来协同的,这样一来就意味着只要你的服务支持通过那种协议对外发请求,它就能够被sidecar所代理,那也就意味着这些网络功能被做为一个独立的辅助进程来完成了,它运行在应用程序的旁边,来提供高级网络功能,让二者之间终于解耦了,这样一解耦你会发现刚才我们遇到的巨大问题都解决了,第一我们的这个业务逻辑开发的时候你不需要再去SDK了,你专注于自己的业务逻辑就行,当需要用到网络功能时调sidecar就行了,我只需要调代理就ok,所以熔断服务发现等等一众高级功能完全不需要自己实现,也不需要借助于SDK完成,一个使用python开发、一个使用java开发、一个使用go开完都没有问题,因为你只要遵循这里的协议就行了,只要遵循API规范我们称为接口契约就可以了,想想我们不在被语言所绑定,我们也不再需要任何一个程序员在开发的微服务架构应用程序的时候去学SDK,不需要了,你只需要理解接口契约正常能调就可以了,大家想想这就让服务集中解决业务逻辑的问题,网络相关的功能就与业务功能就真正剥离出来了,那因此各个微服务框架的此类解决方案往往你记住是几乎是一同实现的,比如像zookeeper,还有Eureka等。

各微服务框架的此类解决方案往往与基础设施组件一同使用,例如Zookeeper或者Eureka等

1.15 Service Mesh 的雏形

  • 将服务治理能力下沉到基础设施中,并将它们部署为服务消费者和服务提供者的独立流程
    • 每个服务都使用一个专用的代理Sidecar来完成高级网络功能
    • 各服务间仅通过Sidecar代理互相通信
    • 各代理之间形成了一个网状网络,2017年,William为其创建一个专用定义,并称之为Service Mesh

A service mesh is a delicated infrastructure layer for handling service-to-service communication. It’s reponsible for the reliable delivery of requests throuth the complex topoloay of services that comprise a modern, cloud native application.

In practice, the service mesh is typically inplemented as an array of lightweight network proxies that are deployed alongside application code, without the application needing to be aware.

服务网格是用于处理服务到服务通信的专用基础设施层。它负责通过构成现代云原生应用程序的复杂服务拓扑可靠地交付请求。在实践中,服务网格通常作为一组轻量级网络代理来实现,这些代理与应用程序代码一起部署,而无需应用程序了解。
在这里插入图片描述
服务网格是什么,看上图应该很形象,我们的分布式应用程序当中,每一个应用都是有业务逻辑和负责高级网络功能的sidecar来协同部署完成的,然后这些sidecar和sidecar之间才有通信,应用程序和应用程序之间不会做任何意义上的直接通信,都要通过代理来实现,那因此这个时候这些sidecar彼此之间就形成了一个支撑应用程序各种高级网络功能的一个专用的网络,我们把它称作网格,所以2017年William为这样一个功能创建了一个专用定义,并将其称之为Service Mesh,我们称之为叫服务网格,首先service mesh是一个专用于处理服务到服务通信的基础设施层,它的核心职责在于什么,透过负责的服务的拓扑结构来可靠的投递消息的,形成一个面向现代化的云原生的应用程序所必然要出现的负责的服务拓扑结构,在实践当中这个service mesh通常它的实现上是一个轻量的网络代理应用程序,sidecar就是个网络代理程序,你可以理解为它就是个http代理,像nginx,当然nginx本身不是为了这样的应用所设计的,所以这并不会使用nginx,这就是service mesh,流量都通过这里的sidecar来解决了,但是要注意的是你会发现这里还有一个问题,我们的每一个service与其它的service通讯的时候,我想找到那个目标service在什么地方,也就意味着sidecar当中该怎么配置,比如s1对应的有些服务要访问s2,有些服务要访问s3,那s2的访问路径在什么地方,到达s3的访问路径在什么地方,是不是要配置在s1里,那怎么配置,难道你面对数百个服务要一个个配置吗,早期我们用配置中心来解决这样的问题,当然配置中心可能有多种功能,第一个是集中分发配置的,第二个是我们调整配置不需要重新打包应用程序等等,但是配置中心很难实现真正意义上的控制功能,但你可以理解这就是所谓的配置中心,但这个配置中心本身所下发的不光是路由的相关功能,像刚才所提到的超时重试熔断等等,还包括鉴权以及安全通信,我们要配置它们通过TLS通信,这些就不是一个配置中心能够解决的问题,所以它可能需要更多辅助性的周边功能,以至于人们对第一代服务网格的基础之上添加了一个专门的控制中心,当然我们不把它叫做控制中心而称作叫Control Plane,叫控制平面。

1.16 新一代Service Mesh

  • 为Service Mesh中各独立工作的代理提供集中式的“控制平面”

    • 实际的服务流量仍然直接在各代理之间完成,但控制平面知道每个代理实例
    • 控制平面使代理能够实现诸如访问控制和指标收集之类的事情
      在这里插入图片描述
      在这里插入图片描述
      Service Mesh’s Control Plane它要负责下发配置,其实你了解istio的话,istio有4个核心功能,第一流量治理,第二策略,所谓策略就是黑白名单之类的功能,另外还像有安全,第四可观测性,也就意味着我们的指标收集很多时候不需要应用程序自己暴露内部指标的话,通信的网络指标完全可以通过sidecar来实现,那究竟我们要监控哪些指标获取哪些指标,都要通过service mesh control plane来进行下发和配置的,也就意味着我们这个服务网格中的sidecar要支持这类的需要才可以,大家没发现服务网格最早期是集中在sidecar之上的,而有了控制平面之后,这个sidecar通常所形成的网格被称之为data plane叫数据平面,而现在的istio的实现这两部分是一个不同的组件,sidecar的实现是envoy来完成的,istio只是为envoy所组成的服务网格提供了一个control plane,所以istio有两个关键组件,一envoy用来组成的数据平面,第二就是我们所谓的control plane就是istiod本身,当然早期可能有多个应用程序,所以我们说service mesh 当中个独立工作的代理提供集中式的控制平面就叫control plane,流量管理依然都是在各sidecar之间实现的,但是我们的控制平面知道每个代理的实例,有了控制平面有一个好处将来我们自己自定义配置的时候只需要通过control plane所提供的API进行配置就可以了,而后把我们的目标配置,提交给control plane,由control plane向下自动分发,这就是所谓的服务网格,到今天为止基于envoy服务网格的实现istio只是其中之一,还有一个非常轻量级的叫kuma,所以带有控制平面的服务网格我们称之为叫做新一代的也称为叫做第二代的service mesh。

1.17 第三阶段的“云原生”小结

在这里插入图片描述
Service Mesh有服务网格istio来实现,当然istio只是代表之一它还没能一统江湖,甚至可能到现在为止它已经无力一统江湖,kubernetes平台实现编排,底层如果不期望托管到公有云平台上很多组织也会选择将kubernetes部署到硬件上,因为只要不用公有云自己建一个私有云,买100台服务器上面跑一层openstack再跑一层kubernetes解决不论底层的扩缩容问题,当资源不够的时候还要加机器,这个问题依然解决不了,所以加一层openstack进行调度k8s本身也有这个能力,比如将应用错峰编排、业务混部等等k8s本身就能做到,那还要加一层openstack干啥,所以很多公司可能就直接选择把kubernetes部署到物理机上,反正底层的弹性都要自己解决,当然也有很多公司会选择将kubernetes部署到公有云之上,部署在物理服务器上中间加一层openstack基本上已经没有啥必要了,多一层封装多一层维护需求多一层麻烦多一层故障存在的可能性还多一层损耗,openstack是python写的性能不好,现在已经很少看到openstack了,kubernetes是一个以应用为中心的现代基础设施,这个基础设施起在什么方面呢,如果要使用公有云的话这些中间件可以基于弹性的方式利用云端的功能的,但现在如果没有使用公有云那这些中间件怎么办,无论是zookeeper、kafka或者是各种各样的分布式缓存都有operator来专门管理它们,这些operator本身就有很好的分布式管理能力,而且这些operator本身就基于CRD就是所谓的自定式的声明式API的接口将能力输出出来,因此service mesh也罢、应用程序开发也罢直接调这些CRD的功能就可以,而不用非得去调服务自己的socket,调CRD就能解决,只不过早期的kafka、zookeeper本身不是云原生的,越来越多的云原生直接提供接口都是CRD的,jenkins是非云原生的CI Server,但是tekton它是云原生的CI Server,这个CI Server到哪种程度,需要定义个pipeline,一般而言要用CI/CD的话就要定义pipeline,你要定义pipeline的话就直接调tenton的CRD就是一个yaml文件写入pipeline直接apply一下就跑起来了,这才是真正意思上的叫云原生,jenkins可不是云原生还要调它的socket打开它的UI等来管理这个功能的,可以理解为至少不是k8s云原生的,而tekton而是真正意义上的k8s云原生的,而CD方面Flux CD或者ArgoCD基本也都做到了云原生,通过一些CRD就能够去定义一个所谓的deployment的任务,当然它也提供给了我们更加便捷的图形化接口,因为毕竟写yaml不是所有人都会使用的条件的,因此越来越多的组件和服务恐怕都会变成叫k8s原生,这些把自己运行成一个基础的支撑能力,而把支撑能力通过CRD提供出来,这种趋势应该是不可避免的,而且这样的组件应该会越来越多,包括istio提供的是服务网格的控制平面,其实它对外输出的API接口也是CRD,也就是说当我需要使用istio为envoy下发配置的时候那个配置的定义是通过CRD定义的,直接通过CRD写一个yaml文件apply一下就好了,所有的使用风格和接口都是声明式API的k8s风格,你几乎看不见istio的存在,而knative也是如此,理解声明式API、理解控制器模式或者叫operator模式对我们将来能够用好k8s是至关重要的,这是第三个阶段的云原生。

1.18 企业IT数字化转型的“三阶段两转变”

在这里插入图片描述
企业IT建设的“三阶段两转变”,其实我们到今天为止,我们的企业IT架构大概经历了3代,转变1是资源自动化,有了所谓的IAS云来管理来提供,但它上层的软件系统仍然需要自行维护,转变2是应用自动化,kubernetes就是以应用为中心的现代基础设施,第一代以硬件为中心,第二代以资源为中心,是公有云时代,或者是云计算时代,IAAS时代,而到了kubernetes时代和云原生时代的时候就是以应用为中心,所有的部署管理我们只需要围绕应用来构建,底层的这些都有基础设施层来解决,将来我们可能是个基础应用工程师或应用工程师,就两级分化了,中间的那层就可能被抹去了,给各种现代化基础设施给掩盖了,而我们现在正面临从第二阶段到第三阶段转变的关键时。

  • 服务器阶段

    • 以硬件设备为中心,业务应用随不同厂商设备、操作系统、虚拟化软件的差异进行定制

    • 设备的安装、调试,应用的部署、运维基本靠人力完成,自动化程度低,缺乏统一的设备和应用管理能力

  • 云化阶段

    • 各类资源如计算、存储、网络由虚拟化软件统一进行池化管控,实现了资源管理自动化,做到了以资源为中心部署应用

    • 屏蔽了基础设施的一部分差异,为上层业务软件提供了统一的资源管理接口,应用的通用性得到增强

    • 虚拟化软件平台差异较大,容易被厂商锁定

  • 云原生阶段

    • 完全屏蔽底层基础设施(包括云厂商)的差异,应用部署无须再关注底层基础环境

    • 企业关注点转变为“以应用为中心”,包括应用敏捷交付、快速弹性、平滑迁移、无损容灾等

    • 业务通用能力也将下沉为基础设施的一部分

1.19 分布式应用的需求

  • Bilgin Ibryam在其一篇文章中将分布式应用的需求分为生命周期、网络、状态和绑定四个方面
    • 显然,要满足这些需求并创建出良好的分布式应用绝非易事

在这里插入图片描述
我们从单体走向分布式,再走向微服务是必然的进程,那为什么?Bilgin Ibryam在其一篇文章中将分布式应用的需求,也就是说看上去单体很简单,我们把一个应用程序组件一个团队给它研发出来,让它正常运行就可以了,但如果我们把它的功能分割出来,放到不同的程序组件中去运行,而这些每一个程序组件如果可以做一个独立进程,很有可能要跨网络协同的话,这个事突然之间就居然变得复杂起来,也就是说它的复杂度它的难度是指数级上升的,为什么这样讲呢?我们要构建一个合理的生产能用的分布式应用,大体上我们要解决这样几个问题,它把这个问题分成了4个层面,分别我们理解为叫做生命周期、网络、状态和绑定四个方面,但是要解决要满足这样的应用是很麻烦的,首先从第一个叫做生命周期管理(Lifecycle),大家都知道对应用程序的生命周期管理,从我们最早的研发,到研发出来以后的构建,打包,分发,部署等等,这些都是所谓的应用程序生命周期管理过程中的组成部分,也包括扩/缩容,到最后应用我不打算让它运行了,然后把它给关掉,销毁等等,所以我们称之为叫做打包,健康状态监测,部署,还有伸缩、扩缩容,以及配置等等都是生命周期中的管理部分,说到这我相信很多朋友应该就浮现出来没准过去所接触到的一些组件,像什么部署工具,CI/CD工具等等几乎都跟这有关系,那当然也包括我们k8s当中这种扩缩容的功能,事实上k8s本身就是个生命周期管理工具,只不过是容器化的形式来打包了每个应用程序而已;那接着第二部分我们称之为叫网络(Networking),其实分布式应用在构建时它是假设网络是可靠的,但事实上这是个悖论,网络本身很不可靠,网络传输还有很大的延迟等等,一共有8个这种所谓的悖论,等会会给大家介绍到,因此我们为了能够克服网络本身的不可靠特性,以及增强我们应用程序部署中的各种各样的功能,或者分布式应用程序协同中的各种各样的功能和特性,我们大体上也要解决以下这些问题,很多朋友没准在微服务架构中就听说过,比如说服务发现(Service discovery),这是分布式当中必然要面临的第一个问题,还有A / B测试(A/B testing),以及我们所谓的叫做金丝雀发布(canary rollouts),还有解决局部故障的解决方案,比如像Retry我们称之为重试,超时(timeout),还有断路器我们称之为circuit breaker,这些组件几乎都要去实现,只要分布式应用你必然要实现,不实现为什么后来就有了各种各样的脚手架,或者叫框架,它就是为了避免每个应用程序每个项目的开发时都要从头实现各种功能的,所以我们就有了开发框架,但而且开发框架对你而言也很麻烦,所以等会我们会通过演进的角度给大家解释,后面还有像P2P这种通信模型,网络通信模型分布式彼此之间通信有两种模型,第一点对点我们成为叫Point-to-point,还有发布/订阅模型叫pub/sub模型,一对一一对多,无论是SOA,还是MSA这样的架构几乎都要解决此类问题,还有Security以及observability,就是所谓的安全和可观测性,在分布式应用当中大家都知道可观测性要从三个维度来做,就要从所谓的指标监控,还有从日志监控,还要做性能监控,以及链路追踪等等这样的相关的功能,那分布式应用的每一个架构程序几乎必须要实现这里的所有功能,否则你构建出来的分布式架构各个地方你想到的角度都可能会出问题,这个各位要注意,因为网络原因也好,程序自身原因也好,我们分布式当中的每一个应用程序随时可能因为各种原因出现故障,因此我们必须要在网络这个级别,站在全局或者局部的角度来处理各种各样的问题,那我们通过冗余就是通过高可用通过负载均衡通过各种各样的方式来抵御这种局部风险,所以这是第二个叫做网络;第三个我们成为Binding所谓叫绑定,绑定是什么,第一个叫连接器(Connectors),应用程序组件和组件之间进行通信的时候它们要通过连接器互相进行通信,至少说被访问端要有API接口,那API接口与调用端和被调用端之间要有接口契约,我们必须要基于某种规范来进行开发,所以还有所谓的Proticol conversion(协议转换),以及Message transformation(消息格式转换),Message routing(消息路由),以及Transactionality(事务)等等,这些几乎都是我们称之为叫做绑定角度要面临的问题,那对一个分布式应用来讲内部的开发团队这些都要通过大量的内部规范内部契约来解决问题;还有State我们称之为状态,那提到状态各位应该都是非常熟悉的,我们的应用程序正常情况先,从单体很好说单体内部通信基于内存来共享状态很容易,但是我们要跨应用程序来实现难度几乎是无限级增加的,但是状态本身我们还必须要解决,通常情况之下分布式应用当中为了能够避免我们被状态绑定,应用自身通常要做成无状态的,但是状态这种保存转换获取怎么来实现,也一样必然要面临这样的问题,所以这里就有了像工作流管理(Workflow mgmt),以及幂等性(Idempotency),对于一个应用来讲,刚才讲到网络中的重试和超时,尤其是重试这里的概念,我们请求一个被访问端服务的API,请求一次之后没有正常得到返回结果,我再请求一次你会发现被调用端执行了2次,这就麻烦了,因此我们要确保我们的得是幂等的,无论多少次调用结果得是一样的等等这些问题我们都要解决,还有像Temporal scheduing就是我们的调度以及缓存,还有APPlication state就是应用程序自己的状态,所以构建一个分布式应用这几类的需要一一我们都要解决,因此从最初单体开始走向分布式的时候这样几个过程当中,人们就想出了很多种解决办法。

生命周期(Lifecrycle):Packaging(打包)、Healtheck(健康状态检测)、Deployment(部署)、SCaling(伸缩)、Confituration(配置)

网络(Networking):Service discovery(服务发现)、A/B testing,canary rollouts(A / B测试,金丝雀发布)、Retry,timeout,circuit breaker(重试、超时、断路器)、Point-to-point,pub/sub(点对点,发布/订阅)、Security,observability(安全性、可观测性)

状态(State):Workflow mgmt(工作流管理)、Idempotency(幂等性)、Temporal scheduing(时间调度)、Caching(缓存)、APPlication state(应用状态)

绑定(Binding):Connectors(连接器)、Proticol conversion(协议转换)、Message transformation(消息转换)、Message routing(消息路由)、Transactionality(事务)

  • 生命周期
    • 编写业务功能时,编程语言会指定生态系统中的可用库、打包格式和运行时(runtime)等
      • 例如,Java使用.jar打包格式,它将依赖到的所有Maven库视为生态系统,并使用JVM作为运行时
    • 随着发布周期变得更短,生命周期中更为重要的是以自动化的方式部署的能力、从错误中恢复的能力和扩展服务的能力
      • 这组能力广泛地代表了应用程序生命周期的需求
  • 网络
    • 从某种意义上说,如今几乎所有的应用程序都是分布式应用程序,它们都需要网络,但现代分布式系统需要从更广泛的角度去掌控网络
      • 包括服务发现和错误恢复、实现现代软发布技术和各种跟踪及遥测
    • 为了满足需要,我们甚至会在这个类别中包含不同的消息交换模式、点对点和发布/订阅方式,以及智能路由机制等
  • 状态
    • 此处的状态是指服务的状态
      • 一般我们认为,服务最好是无状态的
      • 但管理服务的平台本身却是需要状态的(即有状态)
    • 平台负责实现可靠的服务编排和工作流、分布式单例、临时调度(即周期式作业cron job)、幂等性、状态的错误恢复、缓存等,这些功能都依赖于底层的状态
  • 绑定
    • 分布式系统组件不仅要相互通信,而且要和现代的或以往旧式外部系统集成
      • 这就要求连接器(connector)能够转换各种协议、支持不同的消息交换模式,如轮询、事件驱动、请求/应答、转换消息格式,甚至能够执行自定义的错误恢复过程和安全机制

1.20 未来的架构趋势

  • 除了生命周期之外,现在我们已然可以直接使用网络监测、状态抽象、声明性事件以及端点绑定等功能,而EIP(企业集成模式)则是该列表中的下一个元素

在这里插入图片描述
将来要想构建云原生应用,典型玩法就是,在核心业务逻辑之外,附加3个sidecar,第一个sidecar就是istio极其数据平面envoy,第二个组件解决binding问题的Knative使用一个sidecar,第三个解决state问题的dapr使用一个sidecar,也就意味着我们将来部署应用程序的时候你的业务逻辑是核心,但额外我们需要部署3个辅助容器,这3个辅助容器要围绕在业务逻辑的周边来理解的话,你会发现他就成为了什么就不是sidecar问题了,就提供一个套装,因此它被为叫机甲,所以下一代的云原生就被称为叫机甲而不再称为叫sidecar,而且它把所有的数据平面istio的envoy加上dapr的sidecar加上knative的sidecar结合起来形成一个统一的sidecar,被理解为叫机甲,而不是分别运行为各自的sidecar了,但是目前还没达到这种程度,大家拭目以待,没准正在朝这个趋势正在演进。

  • 如果我们把不同领域进行创新的各种云原生项目进行叠加,那么最终将得到类似下图的组合形式

    • 需要注意的是,上图只是用于说明,它有目的地选择了具有代表性的项目,并把它们映射为分布式原语的一种
  • 实际上,我们不会同时使用所有这些项目,因为它们中的一些是重叠的,并且工作负载模型也并不兼容
    在这里插入图片描述
    在为了的架构趋势当中,大概上面这个表就应该更能说明问题了,k8s、Envoy、Dapr、Knative各自解决了什么问题,这个表应该更具有层次性,应该我们把它称为叫做叫Multi-runtime microservices boundary,叫多运行时微服务边界,就是刚才所说的机甲模型。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/580438
推荐阅读
相关标签
  

闽ICP备14008679号