喂 有了 有了好因为前面那个老师拖了点糖所以我们现在就开始吧感谢大家来参加今天分享我们今天跟大家分享的主题是多经济技术在蚂蚁内部落地的探索和眼镜的一个过程蚂蚁集团的话发展到今天这个规模不可避免的早就遇到了一些单点的一些瓶颈然后自然而然的我们就需要对服务还有数据做一些拆分最终走向了我们目前的一个多地多机房的一个部署的一个道路首先我们先简单回顾一下蚂蚁这十年来在架构上的一些眼镜的一些变化我们差不多在一五年之前蚂蚁在集团内部就已经完全落地了一个单元化的架构形成了一个异地多火的一个能力融灾的能力然后随着16年容器技术的一个火热的话我们开始了做容器化然后差不多到19年的时候KBS就成为了我们技术架构的一个标准的底座然后随着我们KBS不断地上线然后随着KBS集团数量不断地变多跨多个集团去管理一个应用的发布部署还有服务注册变得预发的困难然后我们在20年初的时候我们开始去探索KBS联邦的一个方案对然后一直到现在的话形成了一个蚂蚁云安生多级群的一个应用生态然后在探索多级群联邦的这个过程中我们不断地去思考说如何我们能在联邦层面去更好的管理一个应用的服务所以我们一开始在非常早期的时候我们自研了一套叫Fail Rated APP InstanceInstance的一个模型这个模型它尝试通过一个all-in-one的一个这么一个APP的模型去描述所有应用的一个这个我不太会用对OK它尝试在Fail的上去通过一个all-in-one的模型去描述所有的相关的一些资源包含了这个应用本身的一些Department的一些描述还有网络还有Gateway Ingress这一部分然后它在Fed上通过一个Placement来描述这个资源的分发的策略然后通过Override来描述这个级群它这个不同级群当中的一些特质化的一些配置然后但这个模型在落地的过程中遇到了很多的一些困难首先第一点就是它带来了一个更大的认知的复合因为整个KBS大家也了解到它以曲线本身已经非常地陡峭了然后我们又引入了相当于是在Fed层引入了一个模型在Members层又引入了一个APP Instance的模型然后这两层的模型让整个理解变得更加的困难了第二点是我们整个可读性变得非常的差因为引入了一个新的模型之后尤其它是两层的模型你没有办法从Fed这边乃至你没有办法从Members里面的APP Instance去看到最终生成的Department of Equest和Service的资源的实际的情况以及说当我们的业务变得非常非常的模型非常的复杂的情况下那我们在上面Fed这层的模型就变得非常的庞大而且会写出各种各样奇奇怪怪的一些Oride然后同时因为这两层的模型的Reconcile的话导致我们整个整个砲的provision变得非常的复杂整个砲的交付链路从Fed层开始经过了两次的多次的调和然后最终变成Department之后才会产生最终的砲出来然后在这个过程中它的链路很长然后导致我们去一旦出了什么问题去排查的过程中非常的不友好所以这个方案在落地了一段时间之后就被我们废弃了然后接着我们接着去尝试的社区比较火热的Fed VR的架构它相比之前那个模型的一个好处是它其实只有FedFed层这一层的架构然后底下的Memory跟KBS native是一样的所以你只需要在Fed这边去描述你的一个Fed Rated的APP包含Fed RatedDepartment of Service还有Oh, sorry这里有一个错误Fed Rated IngressFed Rated Service然后也是一样的通过Placement Override去描述你的集群的分发策略和每个集群当中单独的一些特殊化的配置但是Fed VRFed VR它还并不是足够的好因为我们可以看一下如果我要去写一个Fed Rated的Department它在不同的集群当中有不同的Replica的时候我需要通过一个很奇怪的Override通过一个Jesenpass的形式来描述不同的集群中有不同的Replica的Value那这个当我们需要去管理这个Department的一个滚动的过程的时候就需要去Override里面去找通过Jesenpass来找这个Value所以整个过程就用起来非常不方便经过了这两次的尝试之后我们就去思考就是说我们Fed Rated的Type它是不是一个必要的东西我们可以来看一下为什么我们需要Fed Rated的Type我们需要Fed Rated的Type其实只需要它里面的这三样的东西一个就是Template它描述的是这个应用了一些基本的配置它的Image是什么它的需要多少资源然后它的一些运行的参数之类的然后Placement来描述说我的这个服务它需要被分发到哪些Members的集群然后以及Override来描述一些特制化的一些配置可能我不同的环境会有不同的环境辨量它需要去使用不同的进向仓库之类的一些配置然后这些配置其实在我们整个开发的流程当中本质上最终其实还是交给用户来决定的如果我们能把这些所有的配置从KBS当中转移到用户内层用户他自己提前把这些事情都决定好了之后那我们是不是提前把这些资源决定然后这些对应的集群当中的Local的Type直接渲染好那我们是不是就不需要Federality的Type了所以经过一些尝试我们认为我们不应该把所有的复杂性都交给KBS来兜底我们希望把这个PlacementOverride和Template从KBS Scope转移到用户的Code里面去由他们自行的去决定这个集群的分发的策略以及特制化的一些配置相当于从KBS Scope转到AC的Scope来然后这样子我们就在KBS的这个层面去把这个PlacementOverride给移除了然后这个只是解决了第一步然后接着我们会发现整个KBS里面如果引入Federality之后我们会有两种不同的类型的资源一种叫做我们称之为Multi-class的资源Multi-class的资源它虽然称之为多集群的资源但实际上它本质上还是一个单集群的一个资源只不过它是存在于多个集群单中而已就像我们的Service或Department它其实是每一个集群单独是有各自的Department和Service只不过是在我们IC的时候渲染出每个集群特制的一些Workload Service的Page而已然后在这个过程中我们要解决的一个问题是说我们如何把这个渲染出来的资源通过一定的方式能够分发到它对应的集群当中去所以我们在内部引入了一个叫Class Gateway的一个组件它用来负责跟上面这个Provision进行交互它把这个东西OpenLine给GatewayGateway帮你转发到对应的集群当中去然后还有一种资源叫做Cross Class它其实就是真正的真正意义上的Fed的资源这部分的资源它实际上它就是应该存在于Fed Host Class里面的比如说会有跨集群的网关需要在Fed这边的视角去看到所有的Members集群里面所有的Service以及说我们会需要一个对一个应用进行跨集群的一个建设室的一个交付的这个能力对于跨集群的资源来说它需要解决的是一个开发者或者说Controller友好的一个问题就是说我怎么在Fed Host Class里面对Gateway和Route做Reconcel的过程中去方便地拿到所有Member Class里面所有它关联的一些资源所以在这个过程中我们内部为开发者提供了一个叫Fed Control Runtime的一个组件来讲话优化Operator开发者的一个体验这个Fed Control Runtime它实际上就是拓展了Controller Runtime的那个一个Client和Catch的两个Interface它为这个为这个Reconcel提供了统一的一个入口然后这个统一的入口就是让这个Fed Control Runtime能够通过相同的Interface去拿到不同的集群的一些Catch里面的数据或者说它可以通过一个Select告诉Catch Manager说我要所有集群里面匹配到的所有的数据而不需要Reconcealer去挨个集群去查询同时它也可以说我给一个特定的Context去告诉Client Manager说我要对某一个集群去写入一个数据然后你只要告诉通过标准的一个Context的接口告诉它然后它会把你去找到对应的集群发过去由于这两个接口它其实都是一个标准的Interface所以我们很容易的把整个架构进行一个降级因为我现在是部署在一个Fed模式上的所以我很容易的就是如果我的Interface里面没有这个Member这两个Member或者没有这个Fed我可以把它部署成一个Local的模式这个模式是有什么用呢大部分情况下我们会通过Local的模式做一些测试或者做一些E2E的工作因为在测试或者E2E的过程中我们很难去构建一个Fed host的它比较费势费力所以你只要写一份代码你的operator就可以在Federation或者是Member的这两种模式下都可以部署了然后我们来看两个例子我们基于刚刚FedControl Run Time然后做的两个例子一个是我们跨集群的Gateway的一个例子在我们的服务将拆分部署到多个集群之后每一个集群里面会有一个自己的Service当我们没有FedGateway的模型的时候我们的每一个集群的Service它都需要单独的注册到对应的网络中心去做服务发现这个过程就会变得非常的繁琐在没有Gateway这个模型的时候所以我们需要在Fed这层有一个统一的视角去看到说我的这一个服务它跨了多个集群它在每个集群里面的Service是怎么样的在我们整个这个模型里面是有这么三层的结构第一层是一个跨集群的Gateway它就是一个流量的一个统一入口你可以认为它就是一个七层的路由的一个描述在左边这边有一个简单的例子它描述了一个TeslaAlipay的Con一个Fold Pass它应该转发到对应的这两个Target里面去然后其中FoldTarget的V1版本是拥有90%的流量V2版本是拥有16%的流量然后这个Cross-class的Service它描述的是对下面的不同的Service做一些更细分的一些区分比如说我可以做一些版本上的区分或者是灰度的一些区分或者是把它们分为不同的环境然后最终它下面就是对应到真实的集群当中的Service然后关联到对应的Port对然后我们可以发现Gateway Controller的话它是运行在FatHouse的Cross里面的然后它需要它同时需要去WatchFatHouse-class里面的Gateway和Cross-class的Service以及对每个Member-class里面的Service如果在没有FatController Runtime的情况下它需要相当于是为每一个class都建立一个Client和Catch然后去挨个的操作但我们引入FatController Runtime之后它相当于直接跟FatController Runtime做交互然后由这个这些每一个的Wall去和写的复杂度就完全交给FatController Runtime来去解决了这个然后它的Gateway Controller它就可以像处理本地数据一样去处理所有不同集群当中的数据然后第二个例子是一个跨集群的一个Rot的例子它因为我们的服务都是异地多火的架构一个服务它需要被部署在多个部署单元当中也就多个部署单元部署在分散在不同的集群当中去所以整个过程的话在我们内部会有两种不同的角色去协作SRE来控制这个服务它的一个渐进式发布的一个过程比如说一些交付的策略比如说一些回渡发布或者是分批的一些策略以及说还有一些不同的环境的发布的一些顺序之类的然后对于这个APP的Owner来说它其实就是做一些开发然后开发完了之后它就直接去更新对应的一个服务然后当它把这个服务做了一个更新之后由这些服务来触发触发这个Fattson的Route然后它会过去到这些更新的事件然后最终的发布的流程是通过Fattson的Route来控制的然后这部分的话我们相当于是把这部分的这个功能的话最早的时候我们内部是通过Fat那个Pass平台平台层的一个产品来控制的然后它会需要通过这个平台层跟多个非常复杂的周边的系统像灰度中心发布中心流量中心进行多次复杂的一些交互最终才能完成我刚刚说的整个的建议是多级讯建议是交付的这么一个发布的流程然后现在我们把整个这一部分的能力从平台那边全部下沉到KBS当中去然后通过一个跨集群的Route组建来完成整个建议室的一个交付的一个过程左边是一个这个建议室交付的一个例子它通过一个Route的Workload Reference通过Label Select来选中多个集群的Stable Set对 然后这边是一个Route Strategy它们描述了一个快速分辨的一个策略这个框起来的意思就是说我要把这个服务整个分成5P来交付每一批你都需要给我暂停进行一个人工的确认OK 我们现在来看一下有两个Demo第一个Demo是我会通过Route来控制两个不同集群当中的Workload的总共10个副本的交付第一个例子是它总共分了两批第一批是每一个集群都发一个砲的然后这个砲的无误了之后由那个开发者确认然后继续出发了之后它会把剩下来的八个砲的全部发布完成OK能看到吗OK 这个这个例子左上角这是一个集群A的五个砲的然后右上角是集群B的五个砲的然后左下角是一个现在这个Fed的Route的一个状态然后右下角这边是我做的一些操作首先我先触发了一个更新然后呢现在是进入了一个D0的批次它就开始跑了然后两个集群它同时开始更新一个砲的然后可以看到这边这个集群被更新了然后我接着去继续触发然后剩下来的四个砲的全部会不会更新这边剩下来的四个砲的也全部会被更新然后这个这个整个Route就结束了这是我们第一个例子因为视频我做了一些加速所以看起来会比较快然后第二个例子的话是跟刚才有一点点差别也是通过Fed的层的Route来控制但是它因为分为两个不同的环境我可以认为左边是一个灰度发布的环境右边是一个生产的环境那么我们在灰度发布开始的时候我先发一个砲的然后当这个炮灯无误了之后我再去触发下一批的更新然后等整个左边这个机房发布完了之后再去发被右边这个机房整个布局是跟刚才一样的然后右下角我去触发第二次的Route的设计然后你可以看到左边这边会先更新一个更新一个实力出来然后右边是不动的这个机群是还没有被触发然后第一批已经结束了被暂停了然后接着你去触发下一次的更新然后Class A这边就全部被更新了然后现在是第一批然后它正在跑然后等着左边这个机群全部跑完了之后那个它被有点快然后停了停了之后它就会继续Continue然后第二批就开始然后右边这边会被全部的更新OK然后整个的Route过程就结束了然后那我们发现就说当我们引入了Fat的Controller之后Fat的程度的Controller它就需要LeastBoard去所有的Member机群的资源那么随着整个介入的机群越来越多导致整个Fat的压力Controller的压力就越来越大单线的Controller的架构Operator的架构其实已经不太能满足我们麻衣内部这么大规模的一个需求了所以下面请我的同事来给大家介绍一下我们在这么大的规模的过程中我们使用了一个新的Controller Match的架构来优化Operator的一个工作的流程好的我们谢谢张俊的刚才对多级群架构的一个精彩演讲接下来我们继续讲一些稍微硬核一点的技术我们继续刚才讲到多级群OK作为多级群的一个控制面的运行师一个Operator其实他可能需要去调和所有级群的资源随着级群的增加或者说是单级群规模的逐渐扩大会给我们的运行师或者说是便更带来更多的问题要挑战在大多数情况下我们为了保证Operator处理任务的一致性和稳定性它其实会采用一个选主的工作机制也就是说我们在不少Operator后它实际上真正去调和去处理任务的就一台机器也就是一个炮的显然意见的处理更多的资源必然会导致我们单点的一个高负载这时候我们可能就需要更多的计算存储和网络资源来保证我们的一个任务处理的稳定性和它的一个及时的交付另外呢Operator的Informer在启动时会去做资源的缓存也就是我们常说的历史的卧尺机制它会去先把收入资源去list到本地的一个缓存中然后再去卧尺集群论的所有的变更事件然而呢这个list的过程它的时间是取决于我们集群内资源的数量的也就是说它其实是跟集群资源的数量是成正比的我们曾经尝试过去List得了70万的炮的大约花了10分钟左右的时间然而这意味着什么呢这意味着对于一个我们有高可用的一个需求的一个平台说我们是完全无法容忍的而且在一个更极端的情况下呢可能我们List的花了时间太久而导致我们在建立一个卧尺连接的时候呢它会出现一个爆炸可能一些开发者会遇到开发者会遇到过它会爆一个因为你当时拿到那个卧尺已经可能已经被缓存中刷过去了我那卧尺连接就建立不起来导致我们的整个operator呢可能完全就起不来另外这种单帘负载的一个工作模式它也是无法进行一个水平扩展和挥露升级的一旦出现问题呢它其实它往往是一个毁灭性的比如说我们曾经做过一次发板然后把一个新版本发到了一个机群只是因为易航的一个错误代码然后造成了我们一整个机群的业务容器进行了全量成器但是还好我们那个机群没有一些核心的业务其实这些问题无论是在单机群中或者是说多机群其实它随着你的规模的主要上升它其实都是会遇到的那我们需要什么呢最核心的一个我们是想要解决变更风险我们需要一个operator一个挥动能力比如说我们能够按照Name Space的维度做一个金色学发布的一个流程我们可能一个新的版本上线之后我们需要在一个Name Space里或者说在一些风险比较低的一些Name Space里做一些做一些验证不好意思然后呢随着我们然后呢逐渐扩大我们的挥动范围然后直到把我们的新的版本推到整个机群毕竟谁也不想说我们今天上午发布下午上热搜了祝福保诈明天我们可以说是覆盖走人了是吧开个玩笑不好意思然后我们另外还需要什么能力呢另外一个就是要解决我们的运行室的风险我们需要operator能够具备一个水平扩展的能力比如我们能将资源按照Name Space去花分为一个花分为多个分区然后每个分区能够被不同的operator泡的所附在实现不同分区的相互隔离在每个分区内它其实都会有一个独立的Leader的operator泡的然后独立的调和各自分区下产生的一些变更事件从而能够降低我们的单点的压力然后也能够降低我们的一个故障的爆炸半径比如说我们可能一个Leader泡的发生了一些物理机的疼罗然后这时候它只会使一个分屏下的泡的可能发生一次准备切换而不是说影响整个机群的一个可能性为了实现这些能力我们其实借鉴了一个Soviet Smash的架构然后实现了一个针对operator的一个Controller Mash的架构并且这套架构目前已经在蚂蚁成功落地能够保障我们的计数设施的一些operator应用的评伪的运行它与Soviet Smash的架构其实是类似的Controller Mash它也分为一个控制平面和数据平面在控制平面我们会做一些配置的管理和分发然后在数据面它是由异组代理容器也就是说我们常说的塞特卡组成它与每个operator实力是不处在一起的并且能够负责处理operator和外部的一些服务之间通信比如说像APSO或者是说其他的一些外部的平台这里最核心的就是通过代理APSO或者请求来实现我们的一些管理方案而且这套架构对于operator来说它是一个透明的无心入的它就像我们所了解的Esteal一样一个Label可能就能实现我们的一个容器的注入过程然后进行我们operator也请求代理和转发基于这套架构我们通过sidecard代理了operator所有请求能够针对请求轻松地实现一些安全的防护策略比如说像容断线流对然后那么我们怎么实现对operator所处理的资源的一个限制呢我们之前前面说过Informer在List的资源的时候它实际上是会去建立缓存的通过List的去建立缓存然后然后wash去监听你的集群内的一些变更事件然而这就给了我们一个可成之机我们可以夹带点私货进去我们像List的wash的请求中带一个Label selector的参数然后通过Label selector来限制我们operator所管理的资源范围那么这个Label又是在哪里呢这个Label也是由我们的Mash Manager负责统一地去添加到你的资源上当然你也可以用你一些自定义的一些Label也都是可以的我们把这些配置以CRD的形式去实现然后用Manager去负责这些配置的坚定和分方比如说这里我们定义了一个容断线流的配置这里因为我们可以代理到APS-O的请求那么我们可以轻松地解析出来这个请求的内容是什么比如说它这个请求要去删除一些泡的然后我们可以根据这些行为做一些针对性的一个限制除此之外我们也支持一些通用的一些限制能力比如Rest的请求的一些地址限制或者说是一些黑白名单的一个限制策略当然最核心的便是我们的一个分片配置我们这里展示了一个自动分片配置它它可以按照Name Space去定义一个我们需要的一个挥作分片它可以去指定你想要的一些Name Space的范围然后可以定义一些均匀的分片配置比如说我想把集群均匀的划分为两个区然后每个区有独立地利得去工作然后这个分片下会有两个泡的然后有有一个主 一个背然后我们还需要配置我们这个分片下就是在这个配置下需要进行分片的资源比如说我们只需要分配只需要把泡的做水平分片处理的话那么只需要在这里写一个泡的一个资源配置就可以将单点部署换为一个分片部署的模式之后能够有效降低我们利得了一个资源的占用均匀的能够不好意思均匀的将这些资源占用分散到多个分片内这里展示了我们在线上环境的一次切换过程我们将单点部署改为了一个三分片的一个部署模式我们可以看到分片的降低了我们的CPU以及Memory的一个单点的一个消耗情况降低了我们的一个单机的一个资源需求One more thing除此之外我们还定制了针对Alperator的场景就是Alperator分辨场景的一个滚动的发布流程因为我们知道原生的Vocalode它不会关心你的它随时主随时背在最坏的情况下如果你用Diploman或者StealSide做发布的时候它可能会做多次的准备切换过程最坏的情况下它可能会切换你的副本术的次数Replica次为了解决这种问题而且还要解决我们分片场景下的一个发布流程我们推出了一个定制化的一个AlperatorRolling Upgrade的一个过程比如说我们这里有一个采用两分片部署的一个Alperator我们在发布的时候它会去先发一个回头分辨的泡的然后再去发我们第二个就是第二个分辨下的备用泡的然后再把备用泡的Leader做发布然后再去发最后一个分片的备用泡的然后再把最后一个分片的Leader发布完成这样呢相对于原本的那种Ukulele的发布方式它是可以一定程度上提高你整个发布过程中的一个可用性的到目前为止我们已经实现了分片管动升级容断线流等一些能力当然基于这种Satica代理的一种模式也能够轻松的做到一些可观色性或者说是一些故障注入的能力这些呢我们也在接下来的后续的规划中我们现在会去演示一个ControlMesh的一个Demo我们先去将我们的CtrlMesh安装到我们的集群里这个Demo可能时间会稍微久一点然后呢我们去尝试安装了一个常规状态下的就是不分片的一个Operator的一个部署情况我们看到它其实当前是只有一个Leader在工作的稍等一下我们把它卸载掉这里我们是在Helm里配置了一个分片的配置然后它是由一个两分片还有一个灰度的分片在这里我们现在去下发一个带有分片配置的一个Operator我们来带着配置把这个Operator部署到集群中它会Mesh Manager会自动的往我们的容器里去注入一个Sidecar容器然后来应用我们的一个分片的一个配置我们可以看到现在它的这个配置已经生效到我们的Operator里了然后在每个分片下其实它有一个独立的Leader在工作比如说灰度分片下有一个编号为0的机器然后在Sharding1中它有一个编号为1的机器然后Sharding2中它是由Pod3去负载然后我们可以看到这里它去注入了一个代理的容器都是自动完成的然后我们去尝试去Delete掉它的一个LeaderDeleteLeader后它会有原本分片下的一个备用的机器去正常的一个接管OK 因为时间关系我们单码就演示到这OK我们今天带来的演讲就到此为止如果有大家有宝贵的意见或者说是有一些建议的话可以下面的二维码来参与到我们的CurrentStack的社区建设中来我们刚才讲到的CtrlMesh还有Operating的一些能力的目前在最近已经开放了0.1.0的版本大家有兴趣的话可以参与到我们的社区建设中来好的 谢谢下面是科学环节有什么问题然后大家可以提问我想问一下这个CtrlMesh它支持的大概是什么样的规模然后到达一个什么样的性能规模和性能对吧目前我们在线上已经就是单级群部署的话其实可以明显支撑一个几百万级的规模的单级群当然它取决于它也取决于你的一些配置模式比如说随着你级群的数量可能你有你千万级的级群你可以比如说你可以配置十个分片然后你每个分片去负载你的一个百万级的规模其实它并不是说取决于你整体的数量而是取决于你分片的数量因为你的级群规模上升OK我可以去拓展我更多的分片你好我想请问一下这个根据Name Space做分片的话怎么去处理那些级群级别的资源这是一个很好的问题谢谢因为我们知道带了一个我们是只带了一个Name Space的一个Label在上面就是我们的Names Manager会去往Name Space打一个Label这个Label去描述了这个Name Space但是对于一个没有Name Space的一个资源来说它可能它无法给你这个Name Space去做一个标识这时候呢我们可能需要用户去比如说你想对如果你想对一个Cluster Role的资源做分片的话你可能需要自己去实现你的一个分片逻辑就是你需要往你的资源上去做标记然后这个你标记之后你可以把你的Label去配置到你的分片配置里对只不过说这个标记不再由Manager去做而是由用户去做对当然如果说你有更好的想法或者是说有能够让Manager去帮你去实现你的Cluster Role资源的一个划分的话其实我们也非常欢迎你去参遇到我们里面能力的建设中来好的 谢谢我补充一点就是Cluster Scope的资源不一定能够分片许个例子就是你Cluster Role和Role Binding来说的话就是他们其实对于Role Binding他其实是需要拿到所有的Cluster Role才能做决策的假设你对他做了分片的话那肯定是某一分片拿到的Cluster Role就只有其中的一部分了那么这个时候他一些工作的时候可能就会有问题了所以并不是所有的Cluster Scope的资源都能分片所以这部分的话我们Control Match本身是没有办法说自动的BindingBinding去做这个事情对所以可能需要开发者自己来决定这个事情如果没有问题的话我们今天就到此为止好的 谢谢大家