OK 那我们就开始然后 大家好然后可能这个现场比我预想的人要多一点感谢大家饿着肚子来听我的演讲对 然后今天分享的 我这边分享的是Control and Time然后一些新的一些特性然后包括我们在做的一些探索性的一些事情对然后我叫王思宇然后我是来自阿里云容器服务团队的Star Engineer然后我也是Open CruiseCoordinated的联合发起人和Maintenor然后也是Control and Time的Maintenor然后我主要在这个KBS的进行管理工作负载 包括调度就是现在在负责一些AI GC on Kubernetes的一些架构对 然后但今天分享的主题还是Control and Time但关于这些其他的一些方向的话对大家有兴趣最后我有个人的RMA可以联系我交流对OK然后我先介绍一下什么是Control and Time这个其实我理解大部分同学可能都了解就是它是社区提供的开发Control and Time开发Operator的一个核心的一个SDK库那其实大家可能熟悉的会用的更多的可能是库语或者Operator SDK就这两个其实它是两个一个类似于脚手架的一个工具然后这个工具可以帮助我们去生成我们Custom的一个Operator那在生成出来的Operator里边其实还有一些额外的工具就是包括了Control and Time它其实也是和Control and Time是我们是一个社区在维护的一个独立项目它是负责为我们的Operator去生成一些gold files比如说deep copy然后包括生成一些YAMOS像CRD,Webhook,IBSA这些定义然后就是我们最核心的Control and Time它其实就大家在我们生成出来的Operator里面看到它其实是一个核心的一个SDK就是它提供了一系列gold的库包括去构建我们的Controller也好还有Webhook也好然后它是我们Operator整个运行时最核心的一个Gaussian的依赖大概是这样一个角色在Control and Time里面其实简单化的一个示意图这里其实是我们在一个完整的Operator里面大概得养一个形态就是说上层其实是我们真正开发者去定义的代码包括它的面入口包括它的Controller它里面有自定义的Event Handler然后包括有自定义的Webhook在底下这一层其实是整个Control and Time包括Control and Time封掉的Cranko的这一层Control and Time里面现在主要几个核心的点一个是ManagerManager它的角色就是说帮助我们的Operator去管理它所有的Operator里面的这种Client也好Cache然后Controller Webhook它是一个All-in-one的一个管理器管理器底下其实有Clust抽象这个底下我们会讲到这个是老版本的Control and Time里面是没有的除此之外还有像Deligating Client当这里我打了个新号因为Deligating Client0.14.15所有版本的话其实这个抽象已经被去掉了它其实整个融合到了Client里面去大家可能用的主流版本里面可能还会有这样一个定义它其实是把底下的Client和Cache这一层去封装了一下它透出的表象就是说大家在用Deligating Client的时候它在读写是被分离的它的读是落到了Cache里面默认情况下然后它的写是落到了Client里面除此之外就是像Control的一些运行室的管理Deligating就是选主包括Webhook还有一些正础管理再往下其实Control他们内部还依赖了就是KBS的可安购去做一些底层的一些Informer的一些维护包括一些底层的一些工具大概是这样一个形态这地方其实我简单给大家说一下现在的一个版本的建容性所以可能很多人会踩过坑Crew Builder和Control Time大概是在18年末到19年初这样可以可能开始用的人会比较多当时的版本其实比较老的就是当时Crew Builder是1.差的版本然后Control Time是0.1的版本这两版本其实后来因为比较有了比较大的改动其实都被废弃了现在大家用的主流比较多了我理解其实是3.差但是也有一部分可能前几年大家见到Operator还在停留在2.差Crew Builder这两版本对项目的框架有一定的变动这里其实我理解整体OK它其实主要是说Control Time它后续的版本迭代它是符合一个规律性Control Time它的第二位比如说0.7第二位其实它加上12是对应的K8S版本大家可以理解K8S一个版本它对应了Control Time的一个版本它们两个版本之间大概是这样一个差12的关系现在是按这个方式再往前一叠带这里就是跟K8S的版本对应关系大家按这个方式去记就好但比较复杂的是涉及到KlanGO这一块就我底下理了一下从K8S1.4开始在1.4里边KlanGO版本还是1.4然后到K8S1.5的时候KlanGO当时我KlanGO参与不了当时我不知道什么背景反正就放飞自我了就变成2.0了然后直到后来的K8S1.13为止其实KlanGO已经从3.0一直升到了10.01.14对应的11.011.0KlanGO大家如果开发比较多的时候可能经常在代码里遇到的KlanGO11.0在勾募的人看到这个版本然后从1.15之后KlanGO又被拉回来了拉回来跟K8S保持了一致的版本就是说K8S1.16它对应了KlanGO的0.16然后它又对应了Ctrl Time的0.4大概是这样一个对应关系但是在勾勾模特里边它有一个坑的地方就是它识别Model版本的时候它是有一个按x.y.z这个规则去判定的也就是说如果你项目里边依赖了某一个裤带码它里边又间接性地依赖了KlanGO的11.0那么它会始终认为11.0的版本它是大于底下的比如说你即使你用最新的K8S1.28你引入了KlanGO 0.28但它会认为这个11.0其实是大于0.28它会强制把你版本再使用一些1.0大概有这么一个坑大家记住就行了遇到这种坑的话大概replace一下依赖可能能解决第一块我介绍一下就现在近期这个Model Console其实也不是近期了它其实这两年一直在有人跟社区在交流这个事就是说传统意义上manager它是all-in-one然后它是管理了一个class就K8S cluster里面的这个控制器它其实比如说它是以in-class的方式去运行集群力的它那个controller和集群队应该是1比1的然后就是一直在有人在跟社区聊就是说他们希望能做到一个operator去对接多个K8S cluster也就是说它可以一套operator可以管理多个K8S cluster但这种场景可能会我理解主要是面向一些比如说一些很密集的一些小集群的这种场景但现在社区就大概只做了一半的事就是说现在它从过去all-in-one manager去抽象出来的一个叫class这么一个抽象这class里面它维护了对于每一个K8S集群的不管是schema也好client也好cash也好这样的话就是说达到效果就是说你在一套在码里面或者你在一个进程里面你可以使用创建多个class来对应多个真正的K8S集群这是现在能做到的事但第二步就再往前走一步就如果需要一个manager去支持多个class对应到多个controller这个意思就是说你定义了一个controller但这controller它在你这个进程里面它要起两个副本去工作在两个class里面这是一种方式另一种方式如果你一个controller它里面要同时不管是reconcile还是q要维护多个class的对象不管是哪种方式现在这个M比N的硬射关系现在还是没有的然后这一块其实现在是一个比较搁置给状态因为大家可能对这块的意见不是很统一就是社区有的manager认为它认为这个不是一个特别合理的需求所以这块如果大家有需求欢迎去社区可以大家一起讨论然后第二块其实是做了一个优化叫disable deep copy然后这个事其实阿里在内部比较早的时候就已经在内部版本做了这个事然后后来我们是把这个功能推到社区然后为什么需要做这个事其实是通常话的就是说大家用原始的clanggo它的leaster它对接informal的时候它的查询就不管是getleast它其实返回来都是informal里面的index里面的对象指针对象一个引用就说它中间是没有任何消耗的但是你拿到对象的引用之后你不能直接修改对象里面的东西你修改之后其实它将来你把开启点东西篡改了然后control time它其实是为了一个异用性就包括降低一个使用的门槛它默认会给所有用户你在去informal查询的时候不管是getleast它全部会做stiff copy我们不会做stiff copy这样的话就是说你的developer你不需要关心这些底层的一些细节你拿到对象之后不管你怎么改其实你不会影响到你的cash但是这样的话就是说一个异用性带来的问题就是说我右边图里大概截了一部分在一些大规模的极权里边其实这个control time运行时尤其是它reconcept平凡的时候其实这块stiff copy它能带来非常大的一个一个是内存的消耗一个是它在stiff copy过程中dpu的消耗它的非常高这块怎么解呢其实在control time0.10里边其实加了一些cash层面的一些参数一个是说可以全局关闭disp copy全局关闭disp copy然后一个是说可以针对特定类型的对象其实就是特定类型比如说针对pod比如说针对node或者一些cr对象来选择性的关闭对象它所有查询和查询的dip copy这是两参数然后到0.14还有一个同学也是建议的是说全局关闭它的好处是很明显但是它的坏处其实就是说你没办法保证所有的operator的开发者它全部能知道这些知识它得知道说比如说我假设说pod对象它被关闭的dip copy那所有针对查询pod对象包括后续修改的时候你都要先做一遍dip copy这个就是说它是一个存在的潜在的风险因为这个风险一旦出发了它可能整个对把开启就已经它的数据就脏了所以在0.14里面我们又加了一个单独的一个list的一个option这个option可以针对单个list的查询去关闭dip copy这样打到效果就是说你可以在明确的你自己可以把控的这个地方你用这个参数查出来对象的话你只要不去做修改那就是没事了这个地方其实是在一些大规模场景其实能很大幅度提升就搞preto的一个性能这个cache的话其实现在我大概画的一张图就是因为我看一下就是网上面之前画的一些informer的一些结构势力包括informer和ctrln他們的结构势力其实都比较老然后我这个图大概重新画了一下大概是基于1.24版本的可能够应该是一个最新版本的一个比较完整的一个图就是它从informer内部的一些构造就是从它的ctrl它其实内部有个叫ctrl的一个抽象但它不是我们常规意义上的ctrl包括reflector做leastwatch然后到底下的delta file然后到process包括resync这条路然后它的process里面就是它的这个even它的出发器其实它通过就是可以看到中间的话可以通过add和next的两个对列来去做了一个类似一个缓存避免它这个even handler之间的一个block大概是这样一个结构到后面的ctrl timectrl time现在回来的这条路就是说底下列的几条其实是现在在做的一些包括已经实现的一些新的功能就包括transform之前大家可能有人也聊过比如说比如说在大规模机型或者说对象太大了cache怎么优化怎么精简其实现在不管cln go还是ctrl time都提供了transformer这个机制你可以去通过注册一个transformer来去使这个informer它在拿到这个比如说卧槍新对象的时候它可以执行你的transformer去把对象做一个收身做一个裁简但这个要注意的就是说比较常规的一些裁简比如说你可以把像manage bind就是说裁简掉但是如果你裁简更多对象的话更多自断的话就是说你后续再拿到这个对象再去做更新的时候就很可能就会把这自断去掉了这个很要注意的一个点另外就是说对event handler的一些remover这个现在社区上已经有了然后没有的是说Dynamic的一个watch和controller这其实也是我看是红帽还有一些公司在提的就是说他们希望是能做到一些动态的一些watch和controller就是说你不停controller你可以动态的根据一些机制比如说你一些出发的实际来去把一些capt watch或者一些controller这些动态就关闭或者是把这个watchformer能去销毁掉大概是这样一个事这个工作应该现在还在一个独映的阶段OK那最后其实是一些我们在做的一些探索性的事就是说不知道大家有没有想过就是说controller这个机制它是通过选组在集群里边起一个唯一的一个组的一个副本去做这个controller的管理在一些小规模场景或者一些非核心的场景还好在一些核心场景里边其实这controller的身体是一个非常大的一个风险为什么就是它因为它升级之后的新版本controller它默认是出于接管整个集群的一个对象自然的管理它在整个集群维度是没有一个挥度的一个过程你挥度你只能按照集群挥度比如说你可以按假设说有测试的集群有预发集群但是当你上生产的时候你生产集群其实是一个集群是一把升级的一个过程它们有一个挥度包括一些想做一些故障演练做一些隔离的事其实都比较复杂因为controller的机制它就做的是比较避缓的一个东西对然后其实我们现在在做的一个事就是现在启明叫controller mania其实是在做一个探索性的事包括这个事我跟controller mania其他几个每天也聊过这个事可能我们先放在我这边先放在open course底下一个一个指向我们在做然后后续我们看进度因为这块其实确实一个是我们尽量做的是跟controller mania不是一个偶和的关系就是说另一块是说它是一个探索性的事它目前还没有一个严格的一个标准这个事怎么实现的呢其实它很简单它就是通过在大家的operator的pod里面去注入了一个叫controller mania的一个proxy这个proxy它接受中心端的比如说mania它下发的一些规则通过这些规则proxy能帮助controller去做一些不管是路由也好做一些过滤做一些管理大概是这样一个形态比如说我们两个controller一个v1 一个v2 两个版本那这两个proxy能帮助这两个不同版本的controller能让他们同时运行并且他们能把他们两边的资源能隔离大概是这样一个过程就是说这个operator它跟APS server的所有交互就包括controller它对APS server的比如说listwatchcreateupdatedelete 这些操作然后包括大家注册的webhook其实是APS server调用了webhook这两条路都会被本地注入了iptablesNAT规则拦截掉它是透明的一个代理然后它会代理到本地的proxy塞特卡里面塞特卡会为所有请求去做一些路由过滤包括做一些比如说容断的一些工作这个就不细讲了大概就是这样一个实际图比如说集群里面假设说有3个name space但是它可以根据特径的一个规则路由规则去选择说比如说只有canary一个金斯确的name space能够被我们要挥度的新版本的operator去处理大概是这样一个形态webhook也是类似的一个形态对然后这里就简单一个压薄的实例大家可以看到里面能配什么东西左边其实就是简单的一些对operator自身一些meta设计的一些定义这个就不细说了其实是当前能支持的一些挥度的一些规则比如说按照name space的一个select比如说大家在name space上可以打标比如说哪些name space它是比如说金斯确name space你可以在name space上打标打标之后可以根据select去选择说哪些name space能够被挥度到新版本的operator去处理这是name space select然后包括name space的一个政则匹配然后也包括object的一个select这里可以根据object的label select去选择挥度这是各种各样的一个挥度策略通过这些挥度策略就是能比较灵活地控制说哪些非核心的name space或者非核心的资源能够挥度到新版本的operator去做一个挥度的验证然后除了除了这个挥度之外其实它能做一些其他事比如说traffic流量的一些策略流量策略之前大家可能比如说在一些安全性上可能会比如说给APS server配一些线流的策略那APS的线流策略它的限制比较多一个是说它要么是配全局的它要么是根据比如说user agent去配但user agent之中说白了其实是一个防君子不防小人的一个做法因为user agent它完全是可按定的它可以告诉你说比如说我user agent用的哪个然后你在APS server配好了就策略但它会都换了一个或者说你用的是社区的一些组建社区的控制器其实你很难去控制说你版本身体或者说一些变化它一定会使用一个你已经配置的user agent种种这样的问题那在可按端去做线流的一些配置其实它是会更加靈活更加可控一点它可以配置比如说请求总量包括请求的一个统的一些配置包括当发生错误的时候能怎么样去拉长这个错误的一个间隔就因为比如说有一些情况下你的耳朵写出了故障写出了一些bug不断的无限的在非常频繁的在操作一些对象比如说在大量的做List或者说在大量的做一些创建更新通过这种策略它能去强制你在客户端你必须符合我定义的这些线流的流量的规则才能去准入然后除此之外其实它还可以实现更多的事但这些事其实现在还没有但是比方说故障注入之前我们对operator其实想做一些比如说故障演练想做一些注入测试其实它很困难因为它直接连的是API Server你一样在API Server测去做这个故障注入比如说你强制比如说给哪个UZ agent就返回一些特定的信息在proxy测其实它能非常轻量的在proxy去拦截到这个请求并且它根据你定义的故障注入的一些规则去给控制器去返回特定的这种response你想去moke一些数据你想让它返回什么样的比如说一个查询到的对象或者说它更新那个结果创建的结果其实都是可以实现的包括一些这种可观色性的事就是说你可以在旁路的比如说你在使用一些社区的operator或者说你在使用一些非自己管控的operator其实你很难去改它的代码对吧但是你可以通过这个旁路proxy来去做一些trace请求包括它的延迟这样也好它的一些错误的一些那种统计其实能做到很多可观色性的一些事然后大家看有什么问题今天分享大概是这么多因为前面耽误点时间现在时间比较紧了这同学这是个好问题其实我们在很多企业内部的一些control里面都有类似的可能少量这种做法就是因为它的对列里面可能有一些情况下我们会把一些额外的信息塞到namespace塞到内容来拼装起来对吧对是这样的但其实从两个方面来看一个是说有多机群这个可能得另说因为多机群的话我前面说到了它涉及一个NBN的一个关系它不一定是说把多个机群塞到一个控制器你可能会给控制器会给每个机群去建立一个副本但是具体什么方式可能现在还没有定然后第二个问题就是说不排除多机群之外就是说其他一些场景下你资源的关联想通过这个对列放到对列这个atom联去实现这个其实它不一定是一个很好的方式它可能会简化你写的代码但是它不一定是一个正确的方式就是说你一定会有办法避开这种使用方式来去实现你的能力但这种情况下可能会对你代码带来一定的复杂度这其实是一个权衡但是从社区上来看的话就是说它希望的是说这个从KBS本身面向这个中态的一个机制上来讲它希望的是单纯的面向的一个对象它其实是说你拿到这个对象之后你根据你的reconcil你面向中态的一个逻辑你来去选择说你要处理什么样的一个一个事带来什么样的状态机去处理所有这种想在namespace和names里面带来一些额外信息的要么就是说比如说你不想写多空日期你一空日期没想把所有的事报掉这时候你要把多个信息处理对比方说deployment和pod或者说是因为deployment它不是就管pod的吗它其实比如说我们举个其他例子比如说rebacksetrebackset它跟pod的关系其实说它controller在处理两对象的时候其实它都会去把rebackset的其实是online资源的soxname就塞到对列里面当你对列取到rebackset的时候它再去反查它管理的pod比如说每一空日期在k8s或者说原生的它这个机制看来你的空日期只应该本身只关注一个对象类型拿到这个对象之后你再去处理跟这个对象它所有相关的其他对象这是它本身的一些这种设计上理念是这样的对它可能在一些场景下确实会增加你的复杂度但是当你break了这个规则你去加一些东西之后你需要把控的其实是你的代码你不能因为break了这个机制来给它比如说买下一些潜在的一些坑这个其实我之前其实都是看到过的大家看其他还有什么问题有我可以告诉你有但是就是社区上我们还没有去比如说卓力去推这个东西说白了也是因为我们希望这东西它能变得更加完善之后因为它现在其实它的核心能力是具备了但是它很多周边的一些比如说一些对它的一些管理怎么样比如说跟发布的平台去结合因为其实它是一道operator发布比如说你通过hairm或通过一些方式不同的平台去发布怎么样能跟它去结合就很多这种周边的一些管理的一些工具一些流程可能现在还没有完善但是它核心能力其实现在是已经在生产已经在使用的对它肯定没办法管理它自己的升级这个是很明确的一个问题它没有法自依赖所以说manager本身它虽然解决不了升级的问题但是它能解决你其他operator升级的问题我只能这么说对就是它是这样的它其实就任何事情它都是一个全衡的过程就是说你直接管理一个或者多个operator肯定是更简单的比如说你只需要比如说你升级的话比如说你通过Helm Upgrade或者通过一些命令或者通过一些平台你去一把把它下班下去OK 那这个就是升级就完成了那如果你没有这个需求的时候可能你完全不需要去care就可去卖起这个东西然后只有对这个生产的这种风险稳定性尤其是这种故障所带来的不可怎么说就是说包括你要去给用户或者说你给上面的继续的用户或者说你给你的业务方去提供这种SLA保障的时候只有这个时候你才会真正去考虑你的operator升级会不会带来一些影响这个其实尤其是大家在使用比如说自己很多团队在开发很多operator然后这个其实我们在不管是阿里云还是阿里机场其实都有很多这样的经验其实现在继续整体不管是从规模上还是从这种Ad-on就operator组建这种来看都是非常复杂的这种场景下其实不管你是作为机群的管控管理者还是作为比如说类似于SI一种角色其实你很难去把控你整个平面所有组建它的稳定性它的可靠性它的升级的一个稳定性那怎么办你只能通过一些这种机制这种手段来去使得他们的升级能够可控能够做挥度能够做控制能够影响或者说能够去收敛整个爆炸的一个半径这个时候你才会考虑说我这个对挥度升级包括对后续的一些这种故障演练的一些场景然后有一些需求就是当你没有这个场景没有这些需求的时候可能你确实是不需要控制Mesh的大概是这样的对那个我像前面说的它现在社区大概是做了一半的一个状态它从里面Cluster的一些抽象上来看它是能支持你通过就在一个代码里或者在一个进程里面通过多个Cluster对象来去对接到多个不同的K8机群就这层是能做到的但再往前一步就是说你需要把你比如说你这个进程里面的多个控制器能够跟多个机群之间能够做协调能够去支持这种N比N的一个关系就这层现在是还没有的对但这块具体怎么去实现其实社区还没有一个定论其实需要比如说大家有需求同样的社区可以一起讨论你说你说对就你很点问题两个问题就是第一个实际上第一块其实是它不是Control Time能解决的它其实是要Control自身解决就是这个怎么说呢就是说你想着你刚才问题就是说比如说你一个机群之间比如说它的自然规模非常大然后它每一次控制器比如说它选为主轴或者它启动之后默认其实是会通过List Watch把所有对象拿过来然后去默认去因为它做List Watch它需要把所有对象去触发一遍它的Event Handle它的Event Handle会把这些对象全部放对这里面OK那这时候你会看到非常大量的一个Reconcell每次启动之后非常大量的对象做Reconcell那怎么优化呢其实这个是需要控制器层面就是说因为控制器本身它的设计它也是一个面向中态的一个设计你在Event Handle的时候其实你可以提前做一层Event Handle的时候你在处理这个Event的时候你可以先提前碰到一下比如说你这个对象它是不是已经符合你的状态机的状态了如果在Event Handle的时候就是你受到对象事件的时候你发现这个对象它已经符合你的面向中态一个结果其实你就不需要把它入队那不入队它就自然就不会做Reconcell这个其实是在控制的就是它的设计层面或者说它这个事件处理的时候其实是能做一层优化的这个包括这个优化它不只是对运行时不包括它不只是对启动的时候它对后续的运行时你受到对象的时候它都能很有效地去收敛或者说减少你的Reconcell的一个数量然后第二个问题其实是你说的是其实说比如说当它一个Operator里面Controller数量比较多的时候你要避免它比如说全部就并发的在一起做Reconcell对吧就这可能是不确定可能比如说是对Controller需要做一些这种Priority有一些这种前后制的一些关系的定义但这个定义现在显然是没有的但是就是就是如果比如说明确有这些事我觉得可以跟社区聊一聊就是说这块从本身对这个多个Controller它的Priority定义去能不能去往前推但是我理解很难做就是它不是因为每一个Controller它不是一个一个面向过程的一个东西它明确告诉你说这Controller它处理完了下Controller在处理对吧Controller其实上它没有一个比如说处理完了一个概念它其实是持续的在做Reconcell对吧除非说你能定义说你这个Controller它其中说它要比如说要谍累一段时间或者要怎么样但这个策略其实它不是一个明确的一个一个比如说自洽的一个策略所以说具体这个问题怎么解可能我们得再看一下不它问的不是说不同Controller它直接在Complete的冲突了它其实说当有大量的Controller包括每一个Controller在处理大量资源的时候这个控制器刚拉起的时候可能所有Controller它都在并发做Reconcell它对这个控制器比如说它的这个压力或者说它的这个比如说出发OM的概率可能会更高一点如果你只是说对 这也是一种方式比如说你在受到那个事件的时候你比如说你入队的时候你可以加个比如说Delay的时间对吧这都是一些策略对这个分两块就是说一个是说它每个版本升级的时候现在是会在Release里面说明比如说这个版本它变化哪些东西包括变化的这些点它会分出来比如说哪些是Breaking Change哪些是一些优化哪些是Bugfix大概是这样分这么分出来但是呢现在就没有一个明确的文档你可能要去看比如说它列出来比如说10条Breaking Change你再进去看说这10条它分别是有什么变化对一个是这样一个是说它代码里面就是它的功能上就是说可能有的功能它只比如说要么是可能没有说明要么只是代码上那些comments可能简单描述了一下这个东西说白了还是一个社区人力的问题对吧就是所有问题落到这时候可能都是变成一个人力的问题就是社区现在现在就我然后包括几个北美的主要是红帽的麦坦那对吧我们几个麦坦那其实说白了都比较忙然后其实文档这块其实我们希望是社区更多的这种抗击标准能进来贡献对对当你扒完代码看到有功能的时候就顺便给上游提一个文档OK然后它是无感的就是它是在你定义好压抹之后你在提交operator pod的时候它会在APS server通过webbook去自动给operator pod注入一个proxy.com对它其实这样它的实现原理其实跟APS server很类似它其实在里面就起了一个非常简化的APS server的server那一层APS server的server那一层它本来就是可以去支持你注册各种各样的类似Progging的一个future的东西在future里面我们可以做各种各样的一些事情OK今天时间也不早了要不就这样回头大家有什么问题可以在下面交流谢谢大家