大中台的黄粱一梦和复用性设计的繁荣盛世


【编者的话】自从阿里巴巴现任CEO逍遥子在2015年提出“大中台,小前台”战略以来,关于“什么是中台”,可谓是一石激起千层浪,大量文章在描述什么是中台。而不懂的人看完后依旧是云里雾里,我们经常听到一些词:“业务中台”,“技术中台”,“系统中台”等,我相信很多同学都会懵逼。本文为作者眼中对中台的理解,中台可广义可狭义,理解到其本质含义更为重要。不同于其他由非技术人员编写的中台释义,本文会严格考虑系统实现的可操作性,时刻带着这种落地感来诠释中台。也希望通过此文指引更多的企业走向正确的中台之路,而不要被那些花里胡哨的概念误导,最后落到舍本逐末、烂尾收场的尴尬境地。

中台的本质理解

大中台小前台战略的由来

最广为流传的故事应当是2015年年中马云参观SuperCell后感慨这家公司单个员工的创造价值为何如此之大——这家创造了年税前利润15亿美元的公司,却只有不到200名员工。SuperCell这家公司可能大家可能没听说过,但它出品的游戏比如《部落冲突》、《卡通农场》、《海岛奇兵》、《皇室战争》和《荒野乱斗》等相信大家多少有所耳闻。这家公司的组织结构也是另类的,传统公司中越是上层,权利也越大,需求、产品定义都是由上至下的,如下图所示:
1.jpeg

而在SuperCell,CEO权力很小,CEO自称是“世界上权利最小的 CEO“,其实这正是一种睿智,自己反而轻松了,类似老子提出的“无为之治”,老祖宗的很多道理真的是放之天下皆可。先看下SuperCell的组织结构:
2.jpeg

他们的工作模式是这样的:谁都可以发起新的游戏创意,然后给组织几个人去实施,做出来看看,行不行,火了就进一步推广,风靡一把;火不起来,玩家不活跃,那这个创意立即终止,再来一个新的继续搞。

这个想法其实他们不是第一个,很多公司都内部竞争,都有多产品实施。它们的牛逼之处还是在于上线一个游戏竟然只要若干人的小组就可以完成,笔者了解到的大公司中很多互相竞争的项目团队各自都是百人规模,还频繁在招人。

SuperCell的快速业务试错模式固然是值得学习的,但支撑这些快速变化的却是背后的那套游戏构建系统。相信很多人,尤其是男生,都会偶尔有个想法:“要是能开发出这样那样玩法的游戏就好了”。现在若是有一个平台,你只需要配置各种事件对应的反馈、游戏的一些设定、建筑的风格等,再配备几个美工,对游戏中的物体进行按需美化,这些操作之后,平台就会给你生成一款全新的符合你设计的游戏,这是多么高效、轻松、低成本的一件事。

相信只要熟悉这套系统,谁都可以在极短的时间内,完成一个新游戏的创建。事实证明,SuperCell的这套新游戏研发系统已经炉火纯青了,《皇室战争》和《海岛奇兵》这两个游戏,如果您都玩过,你会发现它们的游戏画风极为相似,本人曾一度以为它们是一款游戏,只是做了APP升级。

就是这么一个逻辑,对前去参观的马老师一行人来说,犹如醍醐灌顶,豁然开朗。做管理做企业的领导们在看到“新”的高效的模式的时候,总是会想着我们公司是不是也可以这么搞?网上流言中台是马老师提出的无从考证,本人所知的情况是逍遥子内发的邮件最先提到了这个概念。根据广泛的理解,前台一般对应着一个具体的商业模式以及配套的用户应用(App、小程序等),对应阿里的中台架构图(后面会提到),前台就是一个个BU业务线。注意,这张图里压根就没有后台。

还有一种推理帝们的说法是,后台对应了面向内部人员的运营配置、前台对应了面向用户的客户端,所以中台就是衔接它两的。笔者想提醒下,这是压根不是技术人员提出来的,当年张建锋接到马老师的中台作业,也纳闷了半天,百思不得其解。高层管理们不会这么理性的技术化的看待前中后台的关系,个人猜测他们的逻辑是,用户看得到的这些叫前台,这之后看不见的所有的支撑平台叫后台,由于考虑到需要直接支撑前台,所以搞了一个前无古人,后无来者的叫法——中台,连专业代码二十年的阿里各大技术元老们都涨了见识。

笔者看来,在管理层眼中的中台和后台(这里的后台跟技术理解的后台管理系统也不是同一件事)并无差异,只是强调这跟之前看不见的后台是有差异的,他们希望中台这部分能打造成为一个公共后台,而不是竖烟囱式的后台。

说了这么多,总结下本文通用的中台定义:前台的支撑系统,基础设施层之上的通用业务层,具体由通用的业务领域能力和与其对应的后台系统共同组成。画成图的话大概是这样:
3.png

其中前台特有领域和中台领域之间的比例是按前台业务差异性不同而变化的,有些场景下,中台领域可以做的非常厚,厚到前台就剩一个前端应用(APP、小程序、PC站等);有些场景下,中台可能只能做有限的抽象。笔者的另外一个观点是——中台是一个相对的概念,除了整个集团能谈中台,在各个前台领域中,前台研发团队仍然可以做自己的“小中台”,用于服务自身商业模式下的多变的一类业务产品。这种关系是多级的。本质都是在做复用设计。

“新”打了引号,是想表明,这种软件通用性的设计其实很早就有了。

超级细胞公司的“中台”本质

个人非常欣赏埃隆·马斯克经常提及的“第一性原理”,从本质来思考,SuperCell公司并不是一开始就有一个“大中台、小前台”的战略在指引自己,而是任何一家游戏公司,要想做得好,不完全是追求短期利益,都会走向这条路。事实上,超级细胞自身从来没有公开提出什么“中台”的概念。只从游戏工厂这种产品模式来说,SuperCell也不是第一家这样做的公司,所有玩过暴雪的WarCraft(魔兽争霸)的同学都知道,它不仅仅是一款即时战略游戏,它还是一个游戏制造器,通过创建一个新的地图,配置剧情,任何人都可以很快的上手并创建一个自己的玩法。游久网就是这么一个专门提供不同魔兽争霸地图的网站。虽然看不到超级细胞的游戏创造后台系统,我们可以看看魔兽争霸的游戏编辑器是啥样的:
4.jpg

通过任务系统和事件系统,我们还可以定制出各种剧情。为了展示下魔兽地图编辑器(WE)有多变态,以下几幅游戏截图,都是来自于自定义的地图
5.jpg

6.jpg

7.jpg

单说游戏工厂这种产品或游戏创作模式,暴雪的游戏团队绝对是全球顶尖的。在超级细胞的官网介绍中也曾提到,他们的很多员工都是魔兽世界的铁粉。然而人们关注的往往是成功的对象,暴雪最近几年在手游领域除了炉石传说这种卡牌类的,几乎没出啥游戏。PC游戏做的再好,知名度也很难与全民参与度更高的手游相比。与这些先驱游戏公司类似的,超级细胞的“中台”系统本质也是一个游戏工厂,是游戏行业里的一种高复用性、高度可自定义、高度开放式设计的软件系统。当然了,这个工厂生产的东西可能只是一套虚拟的游戏逻辑,具体的用户端APP还是需要依靠研发团队进一步加工和研发的。

个人猜想,马老师一行人回去之后,对标超级细胞一想,这么大一个公司,每天有那么多想法和创意,每个创意、产品都搞一个五脏俱全的团队去实施那得浪费多少人力成本?要是有一个强大的系统,可以让各种想法和创意快速试错,推向市场、反馈、迭代,行就推广,不行就终止,那该多高效。所以才有了后来的“大中台、小前台”战略,为的是给业务打造快速试错的平台,他们理解的中台实质就是一个业务产品工厂,可以通过“配置大于研发的约定”快速构建业务前台,这对应了超级细胞的各种游戏。

中台本质总结

为了更好的阐述和帮助读者理解下文笔者的意图,先总结下对中台的一些理解:
  • 中台的意图:让业务更好的进行创新、试错,同时大大降低新业务研发成本。
  • 中台的理论基础:前台只是一层皮(这层皮也不仅仅是前端,还可以包括后面的前台领域系统),基础设施只是一套没血肉的骨架,位于中间的看不见的血肉才是软件系统的核心,如果这些血肉每次都要重建,那么将严重阻碍新业务创新、试错的速度。
  • 中台的方法论:和平台方法论并无差异——抽象通用能力+开放设计,这两者比例多大,不好说,这里也不想耍流氓那样用个二八定律去糊弄大家,相信不同的业务场景这个比例多少会有些不同。
  • 中台的本质:四个字——系统复用。复用也分层次,也有复用程度之分,通过抽象出各种配置来支撑定制化这件事的本质也是复用——复用配置系统。
  • 中台的实施原则:专注领域复用能力建设、配置大于研发。这个点看似很简单,但是极具艺术性,配置如何做到化繁为简很关键,如果发现配置复杂度比研发还大,那就瞎了。


阿里“大中台、小前台”战略的成与败

阿里中台建设之路

2016 ATF阿里技术论坛于4月15日在清华大学举办,主旨是阐述阿里对世界创新做出的贡献。会上阿里业务平台事业部&淘宝基础平台技术部负责人玄难阐释了淘宝经历13年的发展中,业务平台从零到有,同时又逐步演进为业务中台。下面是个人梳理的可能与阿里中台战略提出有关的一个时间线:

2003年淘宝事业部成立,推进以淘宝为中心的电商系统。

2008年,从淘宝事业部中抽出了一拨人,成立了天猫(最初期也叫淘宝商城)。天猫瞬间变火,业务话语权飙升,于是晋升成了天猫事业部,与淘宝事业部并驾齐驱。但是由于主要的技术团队都还是淘宝的,所以你懂的,很多公司毛病之一——屁股意识太强,所以天猫的需求优先级总是比不过淘宝自身的。天猫业务团队自然就不爽了。另外,到这个时候,天猫和淘宝的大部分业务系统都是各自建设的,但都是由淘系研发团队负责。

2009年,共享业务事业部应运而生。领导层发现上述的问题后,决定成立一个与淘宝事业部、天猫事业部平级的事业部,用来处理他们的公共业务。这么看起来似乎很棒,但却带来了另一个问题,共享业务事业部自身没有前台业务,自然话语权比较小,所以逐渐演变成一个两头受气、吃力不讨好的角色。纵使研发天天加班,也填满不了铺天盖地的需求。

2010年,基于共享业务搭建的聚划算前台取得了喜人的成绩,从此说话腰杆子都直了。当时集团就要求1688、淘宝、天猫要想上聚划算,必须通过共享业务事业部。目前,阿里集团超过25个业务单元(如淘宝、天猫、聚划算、去啊等)都是基于这个共享业务事业部上构建的。整体架构如下图所示:
8.jpg

2015年年底,集团“大中台,小前台”战略正式启用,逍遥子张勇在邮件里写道:“构建符合DT时代的更创新灵活的‘大中台、小前台’组织机制和业务机制:作为前台的一线业务会更敏捷,更快速适应瞬息万变的市场;中台将集合整个集团的运营数据能力、产品技术能力,对各前台业务形成强力支撑”。尝到了共享业务事业部的甜头后,加上前往超级细胞获得的灵感,集团大胆的走出了激进的一步——构建集团中台,纳入更多的BU。此时的整个中台的大致结构如下:
9.png

其中玄难负责业务中台事业群,致力于构建和推行整个集团的业务中台。

2019年,玄难离职创业,方向为电商中台。坊间一个比较靠谱的说法是:2015年阿里制订了一个15~18的三年中台战略,但到19年还没有任何建树,所以中台大将玄难不得不引咎辞职。

2019年阿里组织架构又进行了调整,如下图所示,中台的影子已悄然不见,取而代之的是出现了很多能力型BU和基础基建,这标志着中台回归本质化——复用,既然是复用,自然是被复用的能力型BU躺在下面,面客业务性BU在上面各自发展。
10.png

至今,官方和小道消息都没有具体中台有没有做成的消息,说没有做成吧,淘系电商业务平台(也可以叫中台)确实支撑了好多BU。但是支撑归支撑,要是中台做不大,前台做不小,可能还是达不到管理层的目标。笔者猜测,由于管理层过度的理想化,导致技术实施时困难重重,毕竟复用性并不是想做多大就可以做多大的,支撑的业务模式越多,抽象出来的通用复用性就越底层。这就达不到小前台的效果,前台还是需要一定规模的研发团队,事实证明,目前阿里的各个BU仍然各自都有着大量的研发团队。

阿里中台战略败点分析

该部分没有什么参考文献,全部为个人的观点。笔者做软件设计和研发已有12年,作为一名架构师和码农,个人最怕的就是自己因为害怕走出舒适区而陷入“极端陷阱”。这是一个笔者自己发现和定义的现象:很多时候,绝大多数人会认定一个死理,难以自拔,而究其本质是一旦大脑好不容易发现了某种理解可行时,不想再接受更多的反例,不愿意再去用第一性原则慢慢推导,个人认为这也是一种不想走出舒适区的表现。陷入极端陷阱后引发的问题是,当时你以一个高层领导的身份急着去拍了一个方案,实际上还有很多细节没想明白,这样大概率的结果就是项目烂尾。以下是按个人理解总结的阿里“全局大中台、小前台”战略的两个致命问题。

注:本节仅代表个人思考,不能作为事实依据。

(1) 中台应当分门别类,因地制宜,全局中台并不适合大集团

阿里集团业务繁杂度远高于超级细胞,中台范围应当细化,不适全局中台。治理小区和治理国家固然有一些类似的点和方法论,但是问题规模变大后,很多小规模下的方法也会变得不再适用,这是一个广泛被认可的观点。超级细胞的业务范围很专一,就是手游,所以它可以很容易就做成游戏工厂。放到阿里这样的大集团,业务种类繁杂,性质大相径庭,何必强融?

像淘宝、一淘、天猫,这些其实换汤不换药,那么即便没有中台战略,架构师也知道很多业务逻辑可以复用,要说阿里架构师没有超级细胞的架构师懂?怎么可能。文献中提到的第三阶段其实已经在考虑通过搭建业务平台来建设通用业务能力。而管理层想通过打造一个统一的万能中台来支撑所有集团业务前台,是未经深度思考的表现,从超级细胞小公司到阿里大集团,业务复杂度规模急剧增大,怎么能照搬模式呢。正如没有一个架构师可以在新问题上做出百分之一百与实际匹配的架构一样,也不会有一个统一的万能中台能在保证开闭原则的基础上适配所有业务。

总结来说,阿里集团业务繁杂,不能把BU当做前台来构建大中台,每个BU就是一个独立的公司,有着自己独立的业务,根本“小”不了。而为各个BU做的那些通用的东西也是具有局限性的,只能帮助上层BU节省部分研发成本。过度贪求高度复用,会陷入“强求陷进”——把不该抽象的东西硬是抽象到了一起,结果就是系统的复杂度并没有降低,而是从多个地方搬到了一个地方。因此,管理层想要的“全集团大中台、小前台”,是一种理想主义,注定难以实现。

(2) 全局中台带来的新问题——依赖单点和热点

按上文的理解,中台战略的实际意义更大的是在于提醒所有BU,要尽量的增强能力复用,为BU业务创新营造一个高效低成本的环境。而如果我们把一家大集团的所有主要业务系统都放到一个事业部去管理,就会产生一个新的问题——单点甚至是热点现象。每个BU甚至业务线都各自有KPI,如果某个BU发现中台无法支撑自己的场景(因为总会有没考虑的情况),那么势必要求中台团队做支撑,需求一多,还得排队,这和BU寻求自身的生存和发展势必是矛盾的。所以,复用能力涉及的业务范围越大,单点问题就越是严重,单点变热点的概率也就越大。即便中台事业部做的再大,哪怕为每个BU都搞一个小团队去支持,由于所背的KPI和汇报关系并不在所支撑的BU,实践起来总是会存在信息断层。

合理的复用是不会产生热点的,因为正确的抽象聚焦是的领域内的业务,设计思路会无差别的对待所有用户,要么一个用户都没法用,要么所有用户都可以用(无故障的情况下)。就好比数据库一样,任何一款数据库都不会关注数据的业务属性,电商的数据能存,金融的数据必然也能存。引入数据库就是一种数据存取能力复用——数据库属于基础设施,复用性是必要的。

阿里中台战略的成功之处

时至今日,中台的理念已经深入所有互联网人的心,阿里集团各个BU也在打着自己的中台算盘。全局大中台虽未建成,单各个事业部都开始在研发中试着使用中台思维去思考自己的研发体系。中台的理念一定是没错的,只是要因地制宜,切忌一刀切。早期,大家只会思考基础设施的复用性,产品如各种中间件等,现在大家开始关心另外一个问题了——这个业务能不能做成一个通用能力;又或者,会先问问其他同学——集团是不是有这样的业务能力可以复用过来?这就是一种良性的影响。

中台,未必要大。前台,未必就小。能避免低水平重复性劳动的研发体系,就是可以被称为优秀的研发模式。

企业如何建设适合自己的中台

中台建设的通用步骤

(1) 定义需要快速变化、试错的前台业务(业务线、产品线)

如果您都无法清晰的定义自己的业务线,那么可以先内部脑暴一下。先基于现有的业务线讨论,再继续讨论未来可能发展的业务线。

(2) 领域分析和模块划分

架构师在充分了解了每个业务线后,梳理出每个业务线所需要的业务领域块。这对架构师的要求很高,纯粹的业务架构师可能无法胜任,但是可以参与讨论,因为业务架构师可能对研发细节欠缺考虑,从而做出形而上无法落地的复用设计。

(3) 识别业务线共性并归类

架构师进行前台业务线归类。通过上文的讨论我们知道中台的本质是复用性设计,那么业务线分类就是把可以大程度进行复用业务逻辑的业务线放到一起。这部分需要资深架构师参与,毕竟这很大程度上是一个经验活。有些不该放到一类的业务线应当分开,比如金融业务和电商业务大相径庭,硬是搞一个团队同时维护两套系统,甚至揉在一个系统里,结果是不会太好的。

(4) 画出领域模块(能力)对齐图

由2、3步骤可以画出一个各业务线所需的领域能力图。把名字相同(或者类似)的领域能力对齐,如下图所示大致的内容为:
11.png

先申明下,该图只是提供一种参考,着重去说明复用设计的通用步骤,不具备实际的参考意义,各企业应当结合自身的具体现状具体分析。图中每一列相同的颜色代表它们可以做成一套系统,给各个前台复用。从图中我们可以看出以下关键信息:
  • 一般来说相同业务类别相同的他们的领域划分也比较类似,但也存在反例,比如本地生活中的外卖和到店O2O,可能在商品、营销上有着很大的差异。
  • 用户中心一般不带有具体的业务信息,这部分是可以做成全局统一的,也方便统计用户画像。当然了,各个业务线除了对接这个统一的用户中心外,还是要各自记录一些跟自身业务相关的用户信息,比如金融用户的征信信息等,这种信息可能还需要由另外的系统来承载——比如征信中心。
  • 同样的商家结算,一般都是B2B之间的资金往来,业务不同仅仅影响的是交易凭证的描述不同,其他的结算方式等完全可以复用。
  • 商品中心,看起来各个业务都有商品中心,但是各个业务线的商品结构可能存在差异,比如金融和传统电商的商品中心,其实现逻辑应当是不一样的。当然,硬要把金融产品标上价格,打上SKU去传统电商前台去卖,也是可以的,只是这种方式带来的问题需要事先想好怎么克服,例如,谁来配置这些SKU,谁来进行商品售后等等。
  • 一般涉及货物差异性的业务,都会用到评价中心,这是对商户货物品质的一种用户反馈。而在金融行业的贷款业务看来一般不会对不同的资金提供方去做评价,不排除其他业务会有,比如基金业务等。
  • 而有些领域是业务特有的,比如电商经常需要用到竞价中心,它负责对手商品价格的抓取和匹配等。


(5) 严格遵循开闭原则,从底至上的去实施

针对我们上文找出的存在复用可能性的领域(每一列里颜色相同的领域块),架构师需要识别出其边界和专注解决的问题,最后安排不同的产研团队去实施。各个领域块的研发团队在实施时应当尽可能的抽象公共业务逻辑,并且将无法通用的环节做成开放式的。只要按照这个思想创建的系统,即便没有配置后台,上层业务系统对接也是极其轻松的。这里推荐另一篇笔者的文章《浅谈微服务体系中的分层设计和领域划分》,它讲述的就是一种搭建通用大后端的系统架构,按照柔性的定义,这也是中台——它可以支撑新业务应用快速研发。在完成了通用能力的搭建后,我们还可以为每个通用能力去构建配置后台,这样可以更快的给前台应用研发提速,配置优于研发带来的好处就是不需要走研发流程就可以完成一定的定制逻辑。

需要注意,图中的每个域不代表只有一个服务,服务数量可以是多个。

从底而上是要求我们优先实现那些被广泛依赖和公用的通用领域能力,然后再去实现被依赖较少的那些通用领域能力,最后基于这些能力可能还会继续抽象出一些更具有具体业务含义的领域能力。比如资源库存中心搭建好之后,还可以基于它去搭建商品库存中心。这样不仅可以实现效能最优化,也可以避免由于上层抽象不合理带来的重构成本。想象一下,如果我们先竖烟囱,再去抽象他们的公共部分,是不是会带来巨大的重构成本和重构风险。

万能工厂要不得

“一个强大的集中的流程定制配置后台”是不是企业中台必须要有的部分?个人理解不是必须的,因为互联网业务复杂度规模很大,涉及各种细节,花大代价去整合一个这样的流程配置中台对中小型公司来说是不可取的。前两年阿里内部很火的NBF、TMF框架,可以快速的通过配置和少量研发帮助阿里集团内的其他BU搭建业务项目,说的神乎其神,除了一两个用来打广告的案例之外,真实用的BU并不多,文献对应的知乎回答中也有表达类似看法的。为什么?笔者的答案是“极端陷阱”,只要路子够极端,必定会遇到新的问题,在这一点上,苍天饶过谁?

本以为只要把“开闭原则”用到极致,提供通用配置之外,允许需求方编写很多插件接口实现定制化业务,就可以解决任何问题,其实不然。由于要保证灵活和个性化,配置会呈爆炸式增长,多到理解它学习它使用它的成本也到了一个不小的量级,这时候大部分研发会想——还不如我写代码了。而且一旦遇到某些功能不满足业务需要,业务也不想迁就,那么还得依赖这样一个框架去发起新的迭代,这是业务方不想看到的。代码是一种逻辑语言,本质上和配置一样,只是为了保证代码的正确性,需要经过合理的研发环节,比如研发、自测、测试、灰度、上线验证等,这才是让我们抵触研发的根本原因,而一旦配置复杂了,笔者认为一样一套配置实例仍然需要经过一定的验证流程才能上线,而为这样的一套大型配置系统去编写在线测试机制,又是一大坨工作量。

所以笔者建议,中台的建设应当围绕单一职责的领域能力去构建,单一能力又可以提供一些简单配置来实现定制化使用(就像一款款的中间件那样),比如我们只需要申请好支付账号和密钥,就可以在系统里集成支付宝了。在这些可以复用的系统能力至上,我们再去定制化构建自己的前台业务系统。如果前台产品明确的话,我们甚至可以搭建自己的产品工厂,专门生产某一商业模式下的产品。

这些产品也代表了小前台中的更小前台,也可以反应框定范围内业务模式的不同,业务们也是可以基于这个工厂去玩不同的花样的,只是这样的工厂不能用来生产其他商业模式的产品。反过来说,本来就没啥关系,为啥要管别的商业模式呢?管的越多,工厂本身越复杂,越耽误事,折射到现实中,一般一个工厂只会生产某一种类的产品,但是产品系列可以有多个。折射到超级细胞,它的那套游戏工厂,生产游戏自然没问题,非得让它生产贷款产品,这得多无聊。

所以号称自己可以快速搭建某行业任何业务系统的“万能工厂”,多半是陷入了“极端陷阱”,最后只能是庸人自扰,舍本逐末。记得《最强大脑第七季》的某一场比赛,娄云皓对宋佳昌,单位时间内根据解开的“异形谜盘”数量来得分,娄云皓选择了低阶的盘面,而宋佳昌选择的是高阶的盘面,最后娄云皓大获全胜。这个例子告诉我们,过于追求更大复杂度的成功,很可能陷入自己跟自己过不去的尴尬境地。

笔者不否认理论上是存在一套全能的系统,仅通过配置就可以完成各类电商的业务系统定制,但也别忘了,当配置足够复杂时,也许写写代码更容易解决问题,毕竟底层通用能力有的话,已经可以极大的提高研发效率了。

中台建设本质是复用能力的建设,能力系统的建设应当聚焦某一领域,切实的去解决众多前台业务的某一类复杂性子问题,并封装出简洁的接口提供给前台业务开发使用。万能工厂的做法不可取,这种方法的本质是简单问题复杂化,分布式前台业务的集中式抽象,若是前台业务逻辑本身就相似,那么不用系统工厂也能做的很通用;若是差异很大的前台业务,用了系统工厂可能更难如期交付。

举个例子,一个稍经通用设计的商品中心,从日用百货,到飞机大炮,再到房产基金都可以卖!何必去搞一个万能电商工厂,根据所卖的货物不同而生成一套新的电商系统呢?如果担心很多定制化个性化的逻辑无处表达,那就做好基础能力建设,然后一个小团队就可以基于这些通用能力去快速构建出新的电商系统了。笔者有信心,这种方式比搞一个万能电商工厂来的更加现实和经济,以下是笔者眼中的合理中台架构:
12.png

不同的前台可以有自己的产品工厂,比如金融业务可以有自己的贷款产品工厂、电商业务可以有自己的商品中心等。在写该部分的时候,由于内容很抽象,笔者在极力寻找生活中的例子来帮助读者理解笔者的意图。关于这个部分,可以这样来比拟:如果您某天特别想吃川菜,可以选择自己买菜来做;如果你想能定时吃到按照自己口味做的菜又不想自己做,你可以开个该菜系的小饭馆,请个川菜厨师;如果你还想吃湖南菜,那么你可以尝试招聘一个又会川菜又会湖南菜的厨师(类似业务线是存在抽象复用的可能性的);如果你心血来潮,想着自己还喜欢看书,就想着开一个超级工厂,可以生产你想要的任何东西(食物、书和其他),很可能您会落到一个舍本逐末、烂尾收场的境地。因为本来成立这个工厂就是为了节省成本,而建设它的投入已经远大于分别去搭建按现有需求所需的小生产线了。即便万幸你的超级工厂建成了,你也会发现它的内部很可能也是一条条小生产线组成的,写书和炒菜毕竟差的太远了。这个例子告诉我们以下几点:
  • 尽早识别出截然不同的业务线,不要企图去构建同时支撑他们的中台。
  • 保守的做法是,优先为很容易就被识别的同类业务线去搭建复用中台。
  • 不要激进的去框定一个万能中台的目标,落到实处,为前台老百姓们切切实实的解决一些实在的问题。
  • 中台的设计讨论可以从上至下的去分析,但是实施路径一定要从底至上,先从最基础的通用能力开始,慢慢往上建设,不用强求高度复用性,因为很可能那是业务差异决定的。即便是有解的,高度复用性设计也是在从底至上的建设过程中逐渐形成的。


各大互联网中台实施现状

具体内容参考文献。笔者看完的感受是:广观各大互联网中台建设,都是打着中台的幌子在进行复用性设计战略实施,而且他们的战略实施都有个规律,都是从稳固底部做起,从下至上。似乎只有大阿厂是锚定了一个理想化终态从上至下的大搞特搞的。从腾讯中台定义来看就知道阿厂中台大而泛了,腾讯都是建设了具体的内容中台、用户中台等,而阿厂上来就是业务中台、数据中台和技术中台。不过随着2019年组织结构调整,“大中台、小前台”战略已经无人提及了,提出中台的阿里正在像行业理解的中台前进!这就好比老师跟学生说了某个知识,结果学生理解到了精髓,而老师却曲解了知识本意。

互联网业务参差不齐、细节差异大,很难像超级细胞那样搞个超级中台工厂,业务随便来配置一下就可以生成一个新的业务前台了。不如从基础能力复用性做起,建设好通用基础业务领域能力,其他的个性化前台业务还是需要各自的研发团队负责。从本质上看,全局中台没有意义,但能想的很清楚的领域能力一定要提供出来,比如用户、物流、支付、营销、数据管理等,能减轻多少上层的负担是多少,不必逞强。另外,前台业务的研发团队是需要保留的,他们需要基于全局的通用基础能力去构建属于自己业务的“小”中台。

中台由中台能力组成,具体表现为一个个领域系统,叫不叫中台不重要,重要的是这个领域的服务能力是复用的。

总结

火极一时的阿里“大中台、小前台”战略折射出的是高层管理者在初尝复用技术的甜头后引发的一系列创造性思考,表明企业的管理者正开始思考自身研发体系的科学性和可持续性。中台的提出是粗犷研发转向精益研发的重要里程碑,就像冷兵器时代早期打仗靠堆人,后面慢慢的演化出高效用兵的兵法。

很难想象如果没有中台思想的提出,还有多少公司要陷入研发滚雪球、竖烟囱的状态并且管理层还认为就应该是这样,业务催着要交付产品,研发毫无机会去思考复用性,大家都为着短期的利益做着极端的取舍:前台业务需求第一,不管合不合理,先怼上去,烟囱先竖起来。中台战略,就像是一场革命,革掉了“唯短期利益主义”,当然我们也要避免走入另外一个极端——唯远期利益,这种情况下可能死的更快,对应了过度设计。适合企业的优秀研发架构的实现没有一条黄金定律,架构师和技术TL需要担起这个识别复用点的责任。最后引用一段超级细胞一位开发同学在受采访时说的话:

I feel like when you’re chasing short-term goals, you can end up stepping on your own toes —— Seth Allison。

翻译为:我认为当你追寻短期利益时,你最终会踩到自己的脚趾。文中寓意为超级细胞认为每一款游戏都会运营个20-30年,每次更新变更的内容都会经过充分的讨论。笔者相信,这样的团队在打造自己的游戏研发平台时,注定也会去追求了一个中长期的目标,围绕这个目标小步快跑。

原文链接:https://tbwork.org/2020/08/02/ ... form/,作者:汤波/甘盘
继续阅读 »

【编者的话】自从阿里巴巴现任CEO逍遥子在2015年提出“大中台,小前台”战略以来,关于“什么是中台”,可谓是一石激起千层浪,大量文章在描述什么是中台。而不懂的人看完后依旧是云里雾里,我们经常听到一些词:“业务中台”,“技术中台”,“系统中台”等,我相信很多同学都会懵逼。本文为作者眼中对中台的理解,中台可广义可狭义,理解到其本质含义更为重要。不同于其他由非技术人员编写的中台释义,本文会严格考虑系统实现的可操作性,时刻带着这种落地感来诠释中台。也希望通过此文指引更多的企业走向正确的中台之路,而不要被那些花里胡哨的概念误导,最后落到舍本逐末、烂尾收场的尴尬境地。

中台的本质理解

大中台小前台战略的由来

最广为流传的故事应当是2015年年中马云参观SuperCell后感慨这家公司单个员工的创造价值为何如此之大——这家创造了年税前利润15亿美元的公司,却只有不到200名员工。SuperCell这家公司可能大家可能没听说过,但它出品的游戏比如《部落冲突》、《卡通农场》、《海岛奇兵》、《皇室战争》和《荒野乱斗》等相信大家多少有所耳闻。这家公司的组织结构也是另类的,传统公司中越是上层,权利也越大,需求、产品定义都是由上至下的,如下图所示:
1.jpeg

而在SuperCell,CEO权力很小,CEO自称是“世界上权利最小的 CEO“,其实这正是一种睿智,自己反而轻松了,类似老子提出的“无为之治”,老祖宗的很多道理真的是放之天下皆可。先看下SuperCell的组织结构:
2.jpeg

他们的工作模式是这样的:谁都可以发起新的游戏创意,然后给组织几个人去实施,做出来看看,行不行,火了就进一步推广,风靡一把;火不起来,玩家不活跃,那这个创意立即终止,再来一个新的继续搞。

这个想法其实他们不是第一个,很多公司都内部竞争,都有多产品实施。它们的牛逼之处还是在于上线一个游戏竟然只要若干人的小组就可以完成,笔者了解到的大公司中很多互相竞争的项目团队各自都是百人规模,还频繁在招人。

SuperCell的快速业务试错模式固然是值得学习的,但支撑这些快速变化的却是背后的那套游戏构建系统。相信很多人,尤其是男生,都会偶尔有个想法:“要是能开发出这样那样玩法的游戏就好了”。现在若是有一个平台,你只需要配置各种事件对应的反馈、游戏的一些设定、建筑的风格等,再配备几个美工,对游戏中的物体进行按需美化,这些操作之后,平台就会给你生成一款全新的符合你设计的游戏,这是多么高效、轻松、低成本的一件事。

相信只要熟悉这套系统,谁都可以在极短的时间内,完成一个新游戏的创建。事实证明,SuperCell的这套新游戏研发系统已经炉火纯青了,《皇室战争》和《海岛奇兵》这两个游戏,如果您都玩过,你会发现它们的游戏画风极为相似,本人曾一度以为它们是一款游戏,只是做了APP升级。

就是这么一个逻辑,对前去参观的马老师一行人来说,犹如醍醐灌顶,豁然开朗。做管理做企业的领导们在看到“新”的高效的模式的时候,总是会想着我们公司是不是也可以这么搞?网上流言中台是马老师提出的无从考证,本人所知的情况是逍遥子内发的邮件最先提到了这个概念。根据广泛的理解,前台一般对应着一个具体的商业模式以及配套的用户应用(App、小程序等),对应阿里的中台架构图(后面会提到),前台就是一个个BU业务线。注意,这张图里压根就没有后台。

还有一种推理帝们的说法是,后台对应了面向内部人员的运营配置、前台对应了面向用户的客户端,所以中台就是衔接它两的。笔者想提醒下,这是压根不是技术人员提出来的,当年张建锋接到马老师的中台作业,也纳闷了半天,百思不得其解。高层管理们不会这么理性的技术化的看待前中后台的关系,个人猜测他们的逻辑是,用户看得到的这些叫前台,这之后看不见的所有的支撑平台叫后台,由于考虑到需要直接支撑前台,所以搞了一个前无古人,后无来者的叫法——中台,连专业代码二十年的阿里各大技术元老们都涨了见识。

笔者看来,在管理层眼中的中台和后台(这里的后台跟技术理解的后台管理系统也不是同一件事)并无差异,只是强调这跟之前看不见的后台是有差异的,他们希望中台这部分能打造成为一个公共后台,而不是竖烟囱式的后台。

说了这么多,总结下本文通用的中台定义:前台的支撑系统,基础设施层之上的通用业务层,具体由通用的业务领域能力和与其对应的后台系统共同组成。画成图的话大概是这样:
3.png

其中前台特有领域和中台领域之间的比例是按前台业务差异性不同而变化的,有些场景下,中台领域可以做的非常厚,厚到前台就剩一个前端应用(APP、小程序、PC站等);有些场景下,中台可能只能做有限的抽象。笔者的另外一个观点是——中台是一个相对的概念,除了整个集团能谈中台,在各个前台领域中,前台研发团队仍然可以做自己的“小中台”,用于服务自身商业模式下的多变的一类业务产品。这种关系是多级的。本质都是在做复用设计。

“新”打了引号,是想表明,这种软件通用性的设计其实很早就有了。

超级细胞公司的“中台”本质

个人非常欣赏埃隆·马斯克经常提及的“第一性原理”,从本质来思考,SuperCell公司并不是一开始就有一个“大中台、小前台”的战略在指引自己,而是任何一家游戏公司,要想做得好,不完全是追求短期利益,都会走向这条路。事实上,超级细胞自身从来没有公开提出什么“中台”的概念。只从游戏工厂这种产品模式来说,SuperCell也不是第一家这样做的公司,所有玩过暴雪的WarCraft(魔兽争霸)的同学都知道,它不仅仅是一款即时战略游戏,它还是一个游戏制造器,通过创建一个新的地图,配置剧情,任何人都可以很快的上手并创建一个自己的玩法。游久网就是这么一个专门提供不同魔兽争霸地图的网站。虽然看不到超级细胞的游戏创造后台系统,我们可以看看魔兽争霸的游戏编辑器是啥样的:
4.jpg

通过任务系统和事件系统,我们还可以定制出各种剧情。为了展示下魔兽地图编辑器(WE)有多变态,以下几幅游戏截图,都是来自于自定义的地图
5.jpg

6.jpg

7.jpg

单说游戏工厂这种产品或游戏创作模式,暴雪的游戏团队绝对是全球顶尖的。在超级细胞的官网介绍中也曾提到,他们的很多员工都是魔兽世界的铁粉。然而人们关注的往往是成功的对象,暴雪最近几年在手游领域除了炉石传说这种卡牌类的,几乎没出啥游戏。PC游戏做的再好,知名度也很难与全民参与度更高的手游相比。与这些先驱游戏公司类似的,超级细胞的“中台”系统本质也是一个游戏工厂,是游戏行业里的一种高复用性、高度可自定义、高度开放式设计的软件系统。当然了,这个工厂生产的东西可能只是一套虚拟的游戏逻辑,具体的用户端APP还是需要依靠研发团队进一步加工和研发的。

个人猜想,马老师一行人回去之后,对标超级细胞一想,这么大一个公司,每天有那么多想法和创意,每个创意、产品都搞一个五脏俱全的团队去实施那得浪费多少人力成本?要是有一个强大的系统,可以让各种想法和创意快速试错,推向市场、反馈、迭代,行就推广,不行就终止,那该多高效。所以才有了后来的“大中台、小前台”战略,为的是给业务打造快速试错的平台,他们理解的中台实质就是一个业务产品工厂,可以通过“配置大于研发的约定”快速构建业务前台,这对应了超级细胞的各种游戏。

中台本质总结

为了更好的阐述和帮助读者理解下文笔者的意图,先总结下对中台的一些理解:
  • 中台的意图:让业务更好的进行创新、试错,同时大大降低新业务研发成本。
  • 中台的理论基础:前台只是一层皮(这层皮也不仅仅是前端,还可以包括后面的前台领域系统),基础设施只是一套没血肉的骨架,位于中间的看不见的血肉才是软件系统的核心,如果这些血肉每次都要重建,那么将严重阻碍新业务创新、试错的速度。
  • 中台的方法论:和平台方法论并无差异——抽象通用能力+开放设计,这两者比例多大,不好说,这里也不想耍流氓那样用个二八定律去糊弄大家,相信不同的业务场景这个比例多少会有些不同。
  • 中台的本质:四个字——系统复用。复用也分层次,也有复用程度之分,通过抽象出各种配置来支撑定制化这件事的本质也是复用——复用配置系统。
  • 中台的实施原则:专注领域复用能力建设、配置大于研发。这个点看似很简单,但是极具艺术性,配置如何做到化繁为简很关键,如果发现配置复杂度比研发还大,那就瞎了。


阿里“大中台、小前台”战略的成与败

阿里中台建设之路

2016 ATF阿里技术论坛于4月15日在清华大学举办,主旨是阐述阿里对世界创新做出的贡献。会上阿里业务平台事业部&淘宝基础平台技术部负责人玄难阐释了淘宝经历13年的发展中,业务平台从零到有,同时又逐步演进为业务中台。下面是个人梳理的可能与阿里中台战略提出有关的一个时间线:

2003年淘宝事业部成立,推进以淘宝为中心的电商系统。

2008年,从淘宝事业部中抽出了一拨人,成立了天猫(最初期也叫淘宝商城)。天猫瞬间变火,业务话语权飙升,于是晋升成了天猫事业部,与淘宝事业部并驾齐驱。但是由于主要的技术团队都还是淘宝的,所以你懂的,很多公司毛病之一——屁股意识太强,所以天猫的需求优先级总是比不过淘宝自身的。天猫业务团队自然就不爽了。另外,到这个时候,天猫和淘宝的大部分业务系统都是各自建设的,但都是由淘系研发团队负责。

2009年,共享业务事业部应运而生。领导层发现上述的问题后,决定成立一个与淘宝事业部、天猫事业部平级的事业部,用来处理他们的公共业务。这么看起来似乎很棒,但却带来了另一个问题,共享业务事业部自身没有前台业务,自然话语权比较小,所以逐渐演变成一个两头受气、吃力不讨好的角色。纵使研发天天加班,也填满不了铺天盖地的需求。

2010年,基于共享业务搭建的聚划算前台取得了喜人的成绩,从此说话腰杆子都直了。当时集团就要求1688、淘宝、天猫要想上聚划算,必须通过共享业务事业部。目前,阿里集团超过25个业务单元(如淘宝、天猫、聚划算、去啊等)都是基于这个共享业务事业部上构建的。整体架构如下图所示:
8.jpg

2015年年底,集团“大中台,小前台”战略正式启用,逍遥子张勇在邮件里写道:“构建符合DT时代的更创新灵活的‘大中台、小前台’组织机制和业务机制:作为前台的一线业务会更敏捷,更快速适应瞬息万变的市场;中台将集合整个集团的运营数据能力、产品技术能力,对各前台业务形成强力支撑”。尝到了共享业务事业部的甜头后,加上前往超级细胞获得的灵感,集团大胆的走出了激进的一步——构建集团中台,纳入更多的BU。此时的整个中台的大致结构如下:
9.png

其中玄难负责业务中台事业群,致力于构建和推行整个集团的业务中台。

2019年,玄难离职创业,方向为电商中台。坊间一个比较靠谱的说法是:2015年阿里制订了一个15~18的三年中台战略,但到19年还没有任何建树,所以中台大将玄难不得不引咎辞职。

2019年阿里组织架构又进行了调整,如下图所示,中台的影子已悄然不见,取而代之的是出现了很多能力型BU和基础基建,这标志着中台回归本质化——复用,既然是复用,自然是被复用的能力型BU躺在下面,面客业务性BU在上面各自发展。
10.png

至今,官方和小道消息都没有具体中台有没有做成的消息,说没有做成吧,淘系电商业务平台(也可以叫中台)确实支撑了好多BU。但是支撑归支撑,要是中台做不大,前台做不小,可能还是达不到管理层的目标。笔者猜测,由于管理层过度的理想化,导致技术实施时困难重重,毕竟复用性并不是想做多大就可以做多大的,支撑的业务模式越多,抽象出来的通用复用性就越底层。这就达不到小前台的效果,前台还是需要一定规模的研发团队,事实证明,目前阿里的各个BU仍然各自都有着大量的研发团队。

阿里中台战略败点分析

该部分没有什么参考文献,全部为个人的观点。笔者做软件设计和研发已有12年,作为一名架构师和码农,个人最怕的就是自己因为害怕走出舒适区而陷入“极端陷阱”。这是一个笔者自己发现和定义的现象:很多时候,绝大多数人会认定一个死理,难以自拔,而究其本质是一旦大脑好不容易发现了某种理解可行时,不想再接受更多的反例,不愿意再去用第一性原则慢慢推导,个人认为这也是一种不想走出舒适区的表现。陷入极端陷阱后引发的问题是,当时你以一个高层领导的身份急着去拍了一个方案,实际上还有很多细节没想明白,这样大概率的结果就是项目烂尾。以下是按个人理解总结的阿里“全局大中台、小前台”战略的两个致命问题。

注:本节仅代表个人思考,不能作为事实依据。

(1) 中台应当分门别类,因地制宜,全局中台并不适合大集团

阿里集团业务繁杂度远高于超级细胞,中台范围应当细化,不适全局中台。治理小区和治理国家固然有一些类似的点和方法论,但是问题规模变大后,很多小规模下的方法也会变得不再适用,这是一个广泛被认可的观点。超级细胞的业务范围很专一,就是手游,所以它可以很容易就做成游戏工厂。放到阿里这样的大集团,业务种类繁杂,性质大相径庭,何必强融?

像淘宝、一淘、天猫,这些其实换汤不换药,那么即便没有中台战略,架构师也知道很多业务逻辑可以复用,要说阿里架构师没有超级细胞的架构师懂?怎么可能。文献中提到的第三阶段其实已经在考虑通过搭建业务平台来建设通用业务能力。而管理层想通过打造一个统一的万能中台来支撑所有集团业务前台,是未经深度思考的表现,从超级细胞小公司到阿里大集团,业务复杂度规模急剧增大,怎么能照搬模式呢。正如没有一个架构师可以在新问题上做出百分之一百与实际匹配的架构一样,也不会有一个统一的万能中台能在保证开闭原则的基础上适配所有业务。

总结来说,阿里集团业务繁杂,不能把BU当做前台来构建大中台,每个BU就是一个独立的公司,有着自己独立的业务,根本“小”不了。而为各个BU做的那些通用的东西也是具有局限性的,只能帮助上层BU节省部分研发成本。过度贪求高度复用,会陷入“强求陷进”——把不该抽象的东西硬是抽象到了一起,结果就是系统的复杂度并没有降低,而是从多个地方搬到了一个地方。因此,管理层想要的“全集团大中台、小前台”,是一种理想主义,注定难以实现。

(2) 全局中台带来的新问题——依赖单点和热点

按上文的理解,中台战略的实际意义更大的是在于提醒所有BU,要尽量的增强能力复用,为BU业务创新营造一个高效低成本的环境。而如果我们把一家大集团的所有主要业务系统都放到一个事业部去管理,就会产生一个新的问题——单点甚至是热点现象。每个BU甚至业务线都各自有KPI,如果某个BU发现中台无法支撑自己的场景(因为总会有没考虑的情况),那么势必要求中台团队做支撑,需求一多,还得排队,这和BU寻求自身的生存和发展势必是矛盾的。所以,复用能力涉及的业务范围越大,单点问题就越是严重,单点变热点的概率也就越大。即便中台事业部做的再大,哪怕为每个BU都搞一个小团队去支持,由于所背的KPI和汇报关系并不在所支撑的BU,实践起来总是会存在信息断层。

合理的复用是不会产生热点的,因为正确的抽象聚焦是的领域内的业务,设计思路会无差别的对待所有用户,要么一个用户都没法用,要么所有用户都可以用(无故障的情况下)。就好比数据库一样,任何一款数据库都不会关注数据的业务属性,电商的数据能存,金融的数据必然也能存。引入数据库就是一种数据存取能力复用——数据库属于基础设施,复用性是必要的。

阿里中台战略的成功之处

时至今日,中台的理念已经深入所有互联网人的心,阿里集团各个BU也在打着自己的中台算盘。全局大中台虽未建成,单各个事业部都开始在研发中试着使用中台思维去思考自己的研发体系。中台的理念一定是没错的,只是要因地制宜,切忌一刀切。早期,大家只会思考基础设施的复用性,产品如各种中间件等,现在大家开始关心另外一个问题了——这个业务能不能做成一个通用能力;又或者,会先问问其他同学——集团是不是有这样的业务能力可以复用过来?这就是一种良性的影响。

中台,未必要大。前台,未必就小。能避免低水平重复性劳动的研发体系,就是可以被称为优秀的研发模式。

企业如何建设适合自己的中台

中台建设的通用步骤

(1) 定义需要快速变化、试错的前台业务(业务线、产品线)

如果您都无法清晰的定义自己的业务线,那么可以先内部脑暴一下。先基于现有的业务线讨论,再继续讨论未来可能发展的业务线。

(2) 领域分析和模块划分

架构师在充分了解了每个业务线后,梳理出每个业务线所需要的业务领域块。这对架构师的要求很高,纯粹的业务架构师可能无法胜任,但是可以参与讨论,因为业务架构师可能对研发细节欠缺考虑,从而做出形而上无法落地的复用设计。

(3) 识别业务线共性并归类

架构师进行前台业务线归类。通过上文的讨论我们知道中台的本质是复用性设计,那么业务线分类就是把可以大程度进行复用业务逻辑的业务线放到一起。这部分需要资深架构师参与,毕竟这很大程度上是一个经验活。有些不该放到一类的业务线应当分开,比如金融业务和电商业务大相径庭,硬是搞一个团队同时维护两套系统,甚至揉在一个系统里,结果是不会太好的。

(4) 画出领域模块(能力)对齐图

由2、3步骤可以画出一个各业务线所需的领域能力图。把名字相同(或者类似)的领域能力对齐,如下图所示大致的内容为:
11.png

先申明下,该图只是提供一种参考,着重去说明复用设计的通用步骤,不具备实际的参考意义,各企业应当结合自身的具体现状具体分析。图中每一列相同的颜色代表它们可以做成一套系统,给各个前台复用。从图中我们可以看出以下关键信息:
  • 一般来说相同业务类别相同的他们的领域划分也比较类似,但也存在反例,比如本地生活中的外卖和到店O2O,可能在商品、营销上有着很大的差异。
  • 用户中心一般不带有具体的业务信息,这部分是可以做成全局统一的,也方便统计用户画像。当然了,各个业务线除了对接这个统一的用户中心外,还是要各自记录一些跟自身业务相关的用户信息,比如金融用户的征信信息等,这种信息可能还需要由另外的系统来承载——比如征信中心。
  • 同样的商家结算,一般都是B2B之间的资金往来,业务不同仅仅影响的是交易凭证的描述不同,其他的结算方式等完全可以复用。
  • 商品中心,看起来各个业务都有商品中心,但是各个业务线的商品结构可能存在差异,比如金融和传统电商的商品中心,其实现逻辑应当是不一样的。当然,硬要把金融产品标上价格,打上SKU去传统电商前台去卖,也是可以的,只是这种方式带来的问题需要事先想好怎么克服,例如,谁来配置这些SKU,谁来进行商品售后等等。
  • 一般涉及货物差异性的业务,都会用到评价中心,这是对商户货物品质的一种用户反馈。而在金融行业的贷款业务看来一般不会对不同的资金提供方去做评价,不排除其他业务会有,比如基金业务等。
  • 而有些领域是业务特有的,比如电商经常需要用到竞价中心,它负责对手商品价格的抓取和匹配等。


(5) 严格遵循开闭原则,从底至上的去实施

针对我们上文找出的存在复用可能性的领域(每一列里颜色相同的领域块),架构师需要识别出其边界和专注解决的问题,最后安排不同的产研团队去实施。各个领域块的研发团队在实施时应当尽可能的抽象公共业务逻辑,并且将无法通用的环节做成开放式的。只要按照这个思想创建的系统,即便没有配置后台,上层业务系统对接也是极其轻松的。这里推荐另一篇笔者的文章《浅谈微服务体系中的分层设计和领域划分》,它讲述的就是一种搭建通用大后端的系统架构,按照柔性的定义,这也是中台——它可以支撑新业务应用快速研发。在完成了通用能力的搭建后,我们还可以为每个通用能力去构建配置后台,这样可以更快的给前台应用研发提速,配置优于研发带来的好处就是不需要走研发流程就可以完成一定的定制逻辑。

需要注意,图中的每个域不代表只有一个服务,服务数量可以是多个。

从底而上是要求我们优先实现那些被广泛依赖和公用的通用领域能力,然后再去实现被依赖较少的那些通用领域能力,最后基于这些能力可能还会继续抽象出一些更具有具体业务含义的领域能力。比如资源库存中心搭建好之后,还可以基于它去搭建商品库存中心。这样不仅可以实现效能最优化,也可以避免由于上层抽象不合理带来的重构成本。想象一下,如果我们先竖烟囱,再去抽象他们的公共部分,是不是会带来巨大的重构成本和重构风险。

万能工厂要不得

“一个强大的集中的流程定制配置后台”是不是企业中台必须要有的部分?个人理解不是必须的,因为互联网业务复杂度规模很大,涉及各种细节,花大代价去整合一个这样的流程配置中台对中小型公司来说是不可取的。前两年阿里内部很火的NBF、TMF框架,可以快速的通过配置和少量研发帮助阿里集团内的其他BU搭建业务项目,说的神乎其神,除了一两个用来打广告的案例之外,真实用的BU并不多,文献对应的知乎回答中也有表达类似看法的。为什么?笔者的答案是“极端陷阱”,只要路子够极端,必定会遇到新的问题,在这一点上,苍天饶过谁?

本以为只要把“开闭原则”用到极致,提供通用配置之外,允许需求方编写很多插件接口实现定制化业务,就可以解决任何问题,其实不然。由于要保证灵活和个性化,配置会呈爆炸式增长,多到理解它学习它使用它的成本也到了一个不小的量级,这时候大部分研发会想——还不如我写代码了。而且一旦遇到某些功能不满足业务需要,业务也不想迁就,那么还得依赖这样一个框架去发起新的迭代,这是业务方不想看到的。代码是一种逻辑语言,本质上和配置一样,只是为了保证代码的正确性,需要经过合理的研发环节,比如研发、自测、测试、灰度、上线验证等,这才是让我们抵触研发的根本原因,而一旦配置复杂了,笔者认为一样一套配置实例仍然需要经过一定的验证流程才能上线,而为这样的一套大型配置系统去编写在线测试机制,又是一大坨工作量。

所以笔者建议,中台的建设应当围绕单一职责的领域能力去构建,单一能力又可以提供一些简单配置来实现定制化使用(就像一款款的中间件那样),比如我们只需要申请好支付账号和密钥,就可以在系统里集成支付宝了。在这些可以复用的系统能力至上,我们再去定制化构建自己的前台业务系统。如果前台产品明确的话,我们甚至可以搭建自己的产品工厂,专门生产某一商业模式下的产品。

这些产品也代表了小前台中的更小前台,也可以反应框定范围内业务模式的不同,业务们也是可以基于这个工厂去玩不同的花样的,只是这样的工厂不能用来生产其他商业模式的产品。反过来说,本来就没啥关系,为啥要管别的商业模式呢?管的越多,工厂本身越复杂,越耽误事,折射到现实中,一般一个工厂只会生产某一种类的产品,但是产品系列可以有多个。折射到超级细胞,它的那套游戏工厂,生产游戏自然没问题,非得让它生产贷款产品,这得多无聊。

所以号称自己可以快速搭建某行业任何业务系统的“万能工厂”,多半是陷入了“极端陷阱”,最后只能是庸人自扰,舍本逐末。记得《最强大脑第七季》的某一场比赛,娄云皓对宋佳昌,单位时间内根据解开的“异形谜盘”数量来得分,娄云皓选择了低阶的盘面,而宋佳昌选择的是高阶的盘面,最后娄云皓大获全胜。这个例子告诉我们,过于追求更大复杂度的成功,很可能陷入自己跟自己过不去的尴尬境地。

笔者不否认理论上是存在一套全能的系统,仅通过配置就可以完成各类电商的业务系统定制,但也别忘了,当配置足够复杂时,也许写写代码更容易解决问题,毕竟底层通用能力有的话,已经可以极大的提高研发效率了。

中台建设本质是复用能力的建设,能力系统的建设应当聚焦某一领域,切实的去解决众多前台业务的某一类复杂性子问题,并封装出简洁的接口提供给前台业务开发使用。万能工厂的做法不可取,这种方法的本质是简单问题复杂化,分布式前台业务的集中式抽象,若是前台业务逻辑本身就相似,那么不用系统工厂也能做的很通用;若是差异很大的前台业务,用了系统工厂可能更难如期交付。

举个例子,一个稍经通用设计的商品中心,从日用百货,到飞机大炮,再到房产基金都可以卖!何必去搞一个万能电商工厂,根据所卖的货物不同而生成一套新的电商系统呢?如果担心很多定制化个性化的逻辑无处表达,那就做好基础能力建设,然后一个小团队就可以基于这些通用能力去快速构建出新的电商系统了。笔者有信心,这种方式比搞一个万能电商工厂来的更加现实和经济,以下是笔者眼中的合理中台架构:
12.png

不同的前台可以有自己的产品工厂,比如金融业务可以有自己的贷款产品工厂、电商业务可以有自己的商品中心等。在写该部分的时候,由于内容很抽象,笔者在极力寻找生活中的例子来帮助读者理解笔者的意图。关于这个部分,可以这样来比拟:如果您某天特别想吃川菜,可以选择自己买菜来做;如果你想能定时吃到按照自己口味做的菜又不想自己做,你可以开个该菜系的小饭馆,请个川菜厨师;如果你还想吃湖南菜,那么你可以尝试招聘一个又会川菜又会湖南菜的厨师(类似业务线是存在抽象复用的可能性的);如果你心血来潮,想着自己还喜欢看书,就想着开一个超级工厂,可以生产你想要的任何东西(食物、书和其他),很可能您会落到一个舍本逐末、烂尾收场的境地。因为本来成立这个工厂就是为了节省成本,而建设它的投入已经远大于分别去搭建按现有需求所需的小生产线了。即便万幸你的超级工厂建成了,你也会发现它的内部很可能也是一条条小生产线组成的,写书和炒菜毕竟差的太远了。这个例子告诉我们以下几点:
  • 尽早识别出截然不同的业务线,不要企图去构建同时支撑他们的中台。
  • 保守的做法是,优先为很容易就被识别的同类业务线去搭建复用中台。
  • 不要激进的去框定一个万能中台的目标,落到实处,为前台老百姓们切切实实的解决一些实在的问题。
  • 中台的设计讨论可以从上至下的去分析,但是实施路径一定要从底至上,先从最基础的通用能力开始,慢慢往上建设,不用强求高度复用性,因为很可能那是业务差异决定的。即便是有解的,高度复用性设计也是在从底至上的建设过程中逐渐形成的。


各大互联网中台实施现状

具体内容参考文献。笔者看完的感受是:广观各大互联网中台建设,都是打着中台的幌子在进行复用性设计战略实施,而且他们的战略实施都有个规律,都是从稳固底部做起,从下至上。似乎只有大阿厂是锚定了一个理想化终态从上至下的大搞特搞的。从腾讯中台定义来看就知道阿厂中台大而泛了,腾讯都是建设了具体的内容中台、用户中台等,而阿厂上来就是业务中台、数据中台和技术中台。不过随着2019年组织结构调整,“大中台、小前台”战略已经无人提及了,提出中台的阿里正在像行业理解的中台前进!这就好比老师跟学生说了某个知识,结果学生理解到了精髓,而老师却曲解了知识本意。

互联网业务参差不齐、细节差异大,很难像超级细胞那样搞个超级中台工厂,业务随便来配置一下就可以生成一个新的业务前台了。不如从基础能力复用性做起,建设好通用基础业务领域能力,其他的个性化前台业务还是需要各自的研发团队负责。从本质上看,全局中台没有意义,但能想的很清楚的领域能力一定要提供出来,比如用户、物流、支付、营销、数据管理等,能减轻多少上层的负担是多少,不必逞强。另外,前台业务的研发团队是需要保留的,他们需要基于全局的通用基础能力去构建属于自己业务的“小”中台。

中台由中台能力组成,具体表现为一个个领域系统,叫不叫中台不重要,重要的是这个领域的服务能力是复用的。

总结

火极一时的阿里“大中台、小前台”战略折射出的是高层管理者在初尝复用技术的甜头后引发的一系列创造性思考,表明企业的管理者正开始思考自身研发体系的科学性和可持续性。中台的提出是粗犷研发转向精益研发的重要里程碑,就像冷兵器时代早期打仗靠堆人,后面慢慢的演化出高效用兵的兵法。

很难想象如果没有中台思想的提出,还有多少公司要陷入研发滚雪球、竖烟囱的状态并且管理层还认为就应该是这样,业务催着要交付产品,研发毫无机会去思考复用性,大家都为着短期的利益做着极端的取舍:前台业务需求第一,不管合不合理,先怼上去,烟囱先竖起来。中台战略,就像是一场革命,革掉了“唯短期利益主义”,当然我们也要避免走入另外一个极端——唯远期利益,这种情况下可能死的更快,对应了过度设计。适合企业的优秀研发架构的实现没有一条黄金定律,架构师和技术TL需要担起这个识别复用点的责任。最后引用一段超级细胞一位开发同学在受采访时说的话:

I feel like when you’re chasing short-term goals, you can end up stepping on your own toes —— Seth Allison。

翻译为:我认为当你追寻短期利益时,你最终会踩到自己的脚趾。文中寓意为超级细胞认为每一款游戏都会运营个20-30年,每次更新变更的内容都会经过充分的讨论。笔者相信,这样的团队在打造自己的游戏研发平台时,注定也会去追求了一个中长期的目标,围绕这个目标小步快跑。

原文链接:https://tbwork.org/2020/08/02/ ... form/,作者:汤波/甘盘 收起阅读 »

平安证券Kubernetes落地实践


2020年7月18日,由信也科技集团(NYSE:FINV)旗下科技布道师FTE(FINV technology evangelist)在上海举办了第二届技术沙龙。本次沙龙的主题为《Kubernetes在大型互联网公司落地》,在本次沙龙上,本人分享了《平安证券Kubernetes落地实践》的技术主题。


在本次沙龙中,其它几位技术大神的技术分享,让我受益良多。eBay的技术专家潘野的《eBay大规模化Kubernetes集群管理实践》中,自研扩展Kubernetes API的功能,让超大超多节点的Kubernetes集群管理不再麻烦。美国电商iHerb公司中国研发部DevOps团队负责人李洋的《多Kubernetes集群生产环境中的服务部署与监控实践》,借助于国际云提供商的资源和自研的CI/CD平台,完成了一套高效的基于Kubernetes的DevOps流程体系。信也科技集团架构师、布道师张轶丛的《Kubernetes在信也科技落地分享》,深耕细作于Kubernetes集群各组件的高效运行,并且开源了自家研发的CI/CD交付源代码,让人起敬!
这篇文章,即基于这次的讲演PPT写成(有少量增删)。在此文中,主要讲述了我公司在进行Kubernetes的落地实践中,涉及到的几点小小的经验分享:
  • 镜像制作过程中让JAVA应用感知容器资源;
  • 制作支持GPU的AI项目镜像;
  • 使用Operator部署有状态应用;
  • Kubernetes应用指标的收集和监控;


一、Java应用中的容器配置感知

Kubernetes部署中,我们一般会定义一个容器使用CPU,内存资源的上下限。如下一个yaml文件片断:
1.png

这表示tomcat-demo:v8.55这个容器运行在Kubernetes集群中时,最低能拥有0.5核CPU,512M内存,最高不超过2核CPU,2G内存。

假想当我们把这个yaml资源声明应用到Kubernetes集群时,Kubernetes将它调度一个拥有64核CPU,128G内存的宿主机节点上。Docker容器本质是是宿主机上的一个进程,它与宿主机共享一个/proc目录,也就是说我们在容器内看到的/proc/meminfo,/proc/cpuinfo与直接在宿主机上看到的一致。也即,此容器认为自己的系统资源同样是64核CPU,128G内存。

此处,就出现了运行的容器感知的资源,与Kubernetes分配给它的资源的偏差。在早期的Java版本(JDK 8u131之前)中,这种偏差可能会导致Java应用不断的重启。

那么,为什么Pod会不断重启呢?

以刚才这个配置为例,Java应用以为这自身拥有128G内存,默认情况下,JVM的Max Heap Size是系统内存的1/4,也就是32G作为最大JVM堆内存。但是,当应用运行的总内存,超过Kubernetes的声明限制的2G时,应用就会触发Kubernetes集群定义的资源超配额限制,自动重启此应用POD。于是,我们看到的现象,就是这个应用有越来越多的restart。

如果用户运行的JDK8版本低于131,解决这个问题的办法,是需要在容器启动JAVA程序时,自行定义好与资源配额一致的-Xmx等参数。后来,随着JDK版本的升级,容器感知的功能就内置于Java应用中了,如果JDK8的版本高于191,我们就可以使用MaxRAMPercentage这种更智能化的参数来解决这个问题了。

下图是我综合网上的文档,制作的容器内的JVM参数进化史。
2.png

二、AI项目镜像对GPU的支持

随着现在AI人工智能的高速发布,深度学习,神经网络的热门,公司越来越多的项目,开始使用PyTorch、TensorFlow作为项目开发的支持库。

众所周知,深度学习库,在CPU和GPU上运行效率有巨大差异。为了更快的运行速度,我们也从去年开始了这部份的实践。本节,主要讲述的就是将一个GPU机器加入Kubernetes集群的过程。

因为我公司用的是Nvidia的Tesla系列GPU,所以我们的方案,主要是参照Nvidia的构架思路。在Docker中调用Nvidia的GPU,可以通过nvidia-docker调用,nvidia-docker是一个可以使用GPU的Docker。
3.png

这里且放过Nvidia驱动,cuda-toolkit这些不表,整个安装过程分两大步:

替换docker-runtime

1、安装nvidia-docker(CentOS)
yum install nvidia-docker2-2.0.3-3.docker18.09.6.ce.noarch.rpm

2、修改/etc/docker/daemon.json
4.png

如果这时我们使用docker info命令,会发现docker runtime已替换成了Nvidia。
5.png

将此节点加入Kubernetes集群之后,在集群内安装Nvidia Device Plugin

1、Nvidia Device Plugin项目地址:https://github.com/NVIDIA/k8s-device-plugin

Nvidia Device Plugin的工作机制如下图(图片来自于网络):
6.png

2、在Kubernetes集群中安装好GPU之后,我们就可以在Yaml文件中,为应用分配GPU资源了。其yaml文件中的resource定义,和Kubernetes调度机制如下图(图片来自于网络):
7.png

3、经过我实测试,同样的代码,使用GPU和CPU运算的差距,起码在10位以上。
8.png

9.png

三、使用Operator部署ECK(Elastic Cloud Kubernetes)

在Kubernetes中,对于有状态的应用,有原生的StatefulSet部署支持。StatefulSet原理和ReplicaSet 和 Deployment 资源一样,StatefulSet也使用控制器的方式实现,它主要由StatefulSetController、StatefulSetControl和StatefulPodControl 三个组件协作来完成StatefulSet 的管理,StatefulSetController会同时从PodInformer和ReplicaSetInformer中接受增删改事件并将事件推送到队列中。

但StatefulSet无法解决有状态应用的所有问题,它只能做到创建集群、删除集群、扩缩容等基础操作,但比如备份、恢复等数据库常用操作,则无法实现。

基于此,CoreOS团队提出了Kubernetes Operator概念。Operator是一个自动化的软件管理程序,负责处理部署在Kubernetes有状态应用的安装和生命周期管理。它包含一个Controller和CRD(Custom Resource Definition),CRD扩展了Kubernetes API,可以将一些运维能力,作为代码封装于镜像中。其实现如下图所示(图片来自于网络):
10.png

我们公司遇到一个项目,需要使用Kubernetes集群内的Elasticsearch服务。于是,我们就使用operator部署ECK,后端使用NFS作为数据存储。这里就简要介绍一下其实现思路。

ECK官网:https://www.elastic.co/guide/en/cloud-on-k8s/,本节不讲关于ECK的一些部署,因为官网都提供了详细的说明。这里主要讲解一下,如果通过NFS 动态PVC为ECK提供网络存储,这部分内容,我在部署ECK时,并没有在网络上搜索到完全合用的文档。所以在这里作为落地实践的内容,分享给大家。

使用NFS提供动态PVC功能

GitHub项目地址:https://github.com/kubernetes- ... lient

yaml文件地址:https://github.com/kubernetes- ... .yaml

这份配置文件的注意要点,是要将StorageClass定义中的Provisioner与Deployment中的PROVISIONER_NAME这个环境变量一致。

NFS Provisioner是一个自动配置卷程序,它使用现有的和已配置的NFS服务器来支持通过持久卷声明动态配置Kubernetes持久卷。
11.png

Kubernetes集群有PVC存储之后,就可以将这个StorageClass就用于ECK要求的存储中了

12.png

使用kube-prometheus收集JVM和Node.js的Metric

在Kubernetes集群里,一般是使用Prometheus作指标的收集,监控和报警。我们在早期,也是使用原生的Prometheus,配合一些Exporter来作Metric的收集。在作过几次集群的迁移和新建之后,发现每一次的部署,都很繁琐,叫苦不迭。

到后来,我们引入了Prometheus Operator项目,再过渡到Kube-prometheus项目,部署监控的流程,才变得规范和轻松起来。

kube-promehteus项目地址:https://github.com/coreos/kube-prometheus

由于时间关系,这里也不展开这个项目的具体细节,只和大家分享一下我们是如何使用Kube-prometheus的ServiceMonitor来监控Node.js应用的。

ServiceMonitor就是一种由Prometheus Operator定义的CRD,Operator会通过监听ServiceMonitor的变化来动态生成Prometheus的配置文件中的Scrape targets,并让这些配置实时生效。Operator通过将生成的Job更新到上面的prometheus-k8s这个Secret的Data的prometheus.yaml字段里,然后Prometheus这个Pod里的Sidecar容器prometheus-config-reloader。当检测到挂载路径的文件发生改变后,自动去执行HTTP Post请求到/api/-reload-路径去reload配置。该自定义资源(CRD)通过labels选取对应的Service,并让Prometheus Server通过选取的Service拉取对应的监控信息(Metric)。
13.png

在上图中,我们先定义好ServiceMonitor的Endpoint和Selector。然后,在已有的应用Service中,labels和selector对应,port的name和endpoint的port对应,如果此Node.js应用提供了path作为metric的话,Prometheus就能将这些指标定时入库了,极其方便!

JVM的监控也可以类似的方式实现。
14.png

15.png

当一切部署妥当之后,该应用的Metric就会自动的纳入Promemetheus体系中了。
16.png


作者:陈刚,平安证券运维研发工程师。
继续阅读 »

2020年7月18日,由信也科技集团(NYSE:FINV)旗下科技布道师FTE(FINV technology evangelist)在上海举办了第二届技术沙龙。本次沙龙的主题为《Kubernetes在大型互联网公司落地》,在本次沙龙上,本人分享了《平安证券Kubernetes落地实践》的技术主题。


在本次沙龙中,其它几位技术大神的技术分享,让我受益良多。eBay的技术专家潘野的《eBay大规模化Kubernetes集群管理实践》中,自研扩展Kubernetes API的功能,让超大超多节点的Kubernetes集群管理不再麻烦。美国电商iHerb公司中国研发部DevOps团队负责人李洋的《多Kubernetes集群生产环境中的服务部署与监控实践》,借助于国际云提供商的资源和自研的CI/CD平台,完成了一套高效的基于Kubernetes的DevOps流程体系。信也科技集团架构师、布道师张轶丛的《Kubernetes在信也科技落地分享》,深耕细作于Kubernetes集群各组件的高效运行,并且开源了自家研发的CI/CD交付源代码,让人起敬!
这篇文章,即基于这次的讲演PPT写成(有少量增删)。在此文中,主要讲述了我公司在进行Kubernetes的落地实践中,涉及到的几点小小的经验分享:
  • 镜像制作过程中让JAVA应用感知容器资源;
  • 制作支持GPU的AI项目镜像;
  • 使用Operator部署有状态应用;
  • Kubernetes应用指标的收集和监控;


一、Java应用中的容器配置感知

Kubernetes部署中,我们一般会定义一个容器使用CPU,内存资源的上下限。如下一个yaml文件片断:
1.png

这表示tomcat-demo:v8.55这个容器运行在Kubernetes集群中时,最低能拥有0.5核CPU,512M内存,最高不超过2核CPU,2G内存。

假想当我们把这个yaml资源声明应用到Kubernetes集群时,Kubernetes将它调度一个拥有64核CPU,128G内存的宿主机节点上。Docker容器本质是是宿主机上的一个进程,它与宿主机共享一个/proc目录,也就是说我们在容器内看到的/proc/meminfo,/proc/cpuinfo与直接在宿主机上看到的一致。也即,此容器认为自己的系统资源同样是64核CPU,128G内存。

此处,就出现了运行的容器感知的资源,与Kubernetes分配给它的资源的偏差。在早期的Java版本(JDK 8u131之前)中,这种偏差可能会导致Java应用不断的重启。

那么,为什么Pod会不断重启呢?

以刚才这个配置为例,Java应用以为这自身拥有128G内存,默认情况下,JVM的Max Heap Size是系统内存的1/4,也就是32G作为最大JVM堆内存。但是,当应用运行的总内存,超过Kubernetes的声明限制的2G时,应用就会触发Kubernetes集群定义的资源超配额限制,自动重启此应用POD。于是,我们看到的现象,就是这个应用有越来越多的restart。

如果用户运行的JDK8版本低于131,解决这个问题的办法,是需要在容器启动JAVA程序时,自行定义好与资源配额一致的-Xmx等参数。后来,随着JDK版本的升级,容器感知的功能就内置于Java应用中了,如果JDK8的版本高于191,我们就可以使用MaxRAMPercentage这种更智能化的参数来解决这个问题了。

下图是我综合网上的文档,制作的容器内的JVM参数进化史。
2.png

二、AI项目镜像对GPU的支持

随着现在AI人工智能的高速发布,深度学习,神经网络的热门,公司越来越多的项目,开始使用PyTorch、TensorFlow作为项目开发的支持库。

众所周知,深度学习库,在CPU和GPU上运行效率有巨大差异。为了更快的运行速度,我们也从去年开始了这部份的实践。本节,主要讲述的就是将一个GPU机器加入Kubernetes集群的过程。

因为我公司用的是Nvidia的Tesla系列GPU,所以我们的方案,主要是参照Nvidia的构架思路。在Docker中调用Nvidia的GPU,可以通过nvidia-docker调用,nvidia-docker是一个可以使用GPU的Docker。
3.png

这里且放过Nvidia驱动,cuda-toolkit这些不表,整个安装过程分两大步:

替换docker-runtime

1、安装nvidia-docker(CentOS)
yum install nvidia-docker2-2.0.3-3.docker18.09.6.ce.noarch.rpm

2、修改/etc/docker/daemon.json
4.png

如果这时我们使用docker info命令,会发现docker runtime已替换成了Nvidia。
5.png

将此节点加入Kubernetes集群之后,在集群内安装Nvidia Device Plugin

1、Nvidia Device Plugin项目地址:https://github.com/NVIDIA/k8s-device-plugin

Nvidia Device Plugin的工作机制如下图(图片来自于网络):
6.png

2、在Kubernetes集群中安装好GPU之后,我们就可以在Yaml文件中,为应用分配GPU资源了。其yaml文件中的resource定义,和Kubernetes调度机制如下图(图片来自于网络):
7.png

3、经过我实测试,同样的代码,使用GPU和CPU运算的差距,起码在10位以上。
8.png

9.png

三、使用Operator部署ECK(Elastic Cloud Kubernetes)

在Kubernetes中,对于有状态的应用,有原生的StatefulSet部署支持。StatefulSet原理和ReplicaSet 和 Deployment 资源一样,StatefulSet也使用控制器的方式实现,它主要由StatefulSetController、StatefulSetControl和StatefulPodControl 三个组件协作来完成StatefulSet 的管理,StatefulSetController会同时从PodInformer和ReplicaSetInformer中接受增删改事件并将事件推送到队列中。

但StatefulSet无法解决有状态应用的所有问题,它只能做到创建集群、删除集群、扩缩容等基础操作,但比如备份、恢复等数据库常用操作,则无法实现。

基于此,CoreOS团队提出了Kubernetes Operator概念。Operator是一个自动化的软件管理程序,负责处理部署在Kubernetes有状态应用的安装和生命周期管理。它包含一个Controller和CRD(Custom Resource Definition),CRD扩展了Kubernetes API,可以将一些运维能力,作为代码封装于镜像中。其实现如下图所示(图片来自于网络):
10.png

我们公司遇到一个项目,需要使用Kubernetes集群内的Elasticsearch服务。于是,我们就使用operator部署ECK,后端使用NFS作为数据存储。这里就简要介绍一下其实现思路。

ECK官网:https://www.elastic.co/guide/en/cloud-on-k8s/,本节不讲关于ECK的一些部署,因为官网都提供了详细的说明。这里主要讲解一下,如果通过NFS 动态PVC为ECK提供网络存储,这部分内容,我在部署ECK时,并没有在网络上搜索到完全合用的文档。所以在这里作为落地实践的内容,分享给大家。

使用NFS提供动态PVC功能

GitHub项目地址:https://github.com/kubernetes- ... lient

yaml文件地址:https://github.com/kubernetes- ... .yaml

这份配置文件的注意要点,是要将StorageClass定义中的Provisioner与Deployment中的PROVISIONER_NAME这个环境变量一致。

NFS Provisioner是一个自动配置卷程序,它使用现有的和已配置的NFS服务器来支持通过持久卷声明动态配置Kubernetes持久卷。
11.png

Kubernetes集群有PVC存储之后,就可以将这个StorageClass就用于ECK要求的存储中了

12.png

使用kube-prometheus收集JVM和Node.js的Metric

在Kubernetes集群里,一般是使用Prometheus作指标的收集,监控和报警。我们在早期,也是使用原生的Prometheus,配合一些Exporter来作Metric的收集。在作过几次集群的迁移和新建之后,发现每一次的部署,都很繁琐,叫苦不迭。

到后来,我们引入了Prometheus Operator项目,再过渡到Kube-prometheus项目,部署监控的流程,才变得规范和轻松起来。

kube-promehteus项目地址:https://github.com/coreos/kube-prometheus

由于时间关系,这里也不展开这个项目的具体细节,只和大家分享一下我们是如何使用Kube-prometheus的ServiceMonitor来监控Node.js应用的。

ServiceMonitor就是一种由Prometheus Operator定义的CRD,Operator会通过监听ServiceMonitor的变化来动态生成Prometheus的配置文件中的Scrape targets,并让这些配置实时生效。Operator通过将生成的Job更新到上面的prometheus-k8s这个Secret的Data的prometheus.yaml字段里,然后Prometheus这个Pod里的Sidecar容器prometheus-config-reloader。当检测到挂载路径的文件发生改变后,自动去执行HTTP Post请求到/api/-reload-路径去reload配置。该自定义资源(CRD)通过labels选取对应的Service,并让Prometheus Server通过选取的Service拉取对应的监控信息(Metric)。
13.png

在上图中,我们先定义好ServiceMonitor的Endpoint和Selector。然后,在已有的应用Service中,labels和selector对应,port的name和endpoint的port对应,如果此Node.js应用提供了path作为metric的话,Prometheus就能将这些指标定时入库了,极其方便!

JVM的监控也可以类似的方式实现。
14.png

15.png

当一切部署妥当之后,该应用的Metric就会自动的纳入Promemetheus体系中了。
16.png


作者:陈刚,平安证券运维研发工程师。 收起阅读 »

博云成为容器云代表性厂商,入选Gartner《2020年中国ICT技术成熟度曲线报告》


近日,全球权威的信息技术研究和分析公司 Gartner 发布了《Hype Cycle for ICT in China, 2020》报告即“2020中国 ICT 技术成熟度曲线报告”,其中容器即服务( CaaS )为新兴技术热点,取得了飞速成长,且市场对容器技术的关注与兴趣仍在急剧上升中。BoCloud博云作为国内容器云领域( CaaS )的领军企业入选该报告,被评为 CaaS 容器云“代表性厂商”( Sample Vendor )。

技术成熟度曲线是 Gartner 为企业提供的评估新技术成熟度的典型工具。新兴技术是支持企业数字化转型的关键创新引擎,中国 ICT 技术成熟度曲线是企业用户和技术厂商提供评估新技术成熟度的典型工具,也是评估新兴数字化技术趋势、技术潜力和商业潜力提供重要依据。

Gartner

容器平台是中国ICT市场热点

Gartner 指出,对于企业而言,2020年数字化转型仍然是高度优先事项。企业正在经历从技术导向向服务导向的转变,其中以容器、DevOps、多云平台为代表的现代化基础设施平台是这些企业需要重点关注的三大方向之一。报告中显示,CaaS(容器即服务)作为新兴技术热点,取得了飞速成长,由于人们对容器运行时的采用越来越多,市场对容器技术的关注与兴趣仍在急剧上升中。

115701596511881_.pic_hd_.jpg


Gartner 指出,云原生应用程序需要高度的基础设施自动化、专业化的操作能力,但这对于企业 IT 并不容易实现。而 CaaS 容器云可以让企业 IT 更便捷地使用容器功能,为企业 IT 在生产力和敏捷性带来了显而易见的优势,包括加速和简化应用程序生命周期能力、实现不同环境间的工作负载可移植性、提高资源利用率等。

在中国本土 CaaS 容器云市场上,当前容器技术收益合理,市场潜力覆盖了5%-20%的目标受众,技术成熟度凸显。Gartner 指出,以 BoCloud 博云为代表的国内容器服务提供商是强有力的本土竞争者。

博云

深耕容器领域,掌握底层核心能力

近年来,容器技术凭借轻量化和标准化的显著特性,逐渐成为云计算领域基础设施云化的变革技术。作为云原生( cloud native )生态的基石,容器技术已然成为云原生时代的标准基础设施。

作为国内最早瞄准容器领域为企业级用户提供容器云服务的提供商之一,博云基于 kubernetes 自主研发的 BeyondContainer 容器云平台,一直坚持聚焦平台底层能力的提升,根据用户实际需求,对容器网络、负载均衡能力、胖容器等容器底层核心技术进行了改进与增强,确保能满足用户 IT 敏捷化的需求。

自研容器网络

网络对于容器云平台的稳定性、扩展性影响非常大。随着容器云平台在企业的大量落地,企业亟需缓解在落地私有容器云平台时遇到的网络阻力。博云 BeyondFabric 容器网络是基于OpenVswitch (OVS) 自研的 Kubernetes CNI 插件,可以实现内外网互通、管理业务网络分离、灵活的网络隔离机制、易于运维管理和调试等功能。

同时支持 underlay 和 overlay 网络,重点解决微服务上云过程中,集群内外互相直接通信的问题,大大降级企业落地容器云平台的复杂度,使业务迁移到容器云后,几乎感知不到基础设施从虚拟化到容器化变更带来的变化。(为什么我们要自主开发一个稳定可靠的容器网络)

增强负载均衡

在对社区版 Nginx Ingress Controller 进行了全面调研和深入理解之后,博云针对社区版 Nginx IngresController 做了进一步模型改进和功能扩充,自研 Ingress 控制器 BeyondELB。支持租户级负载、热更新、多版本灰度发布等特性,大大增强了 Nginx Ingress Controller 的功能特性和扩展能力。(原生Ingress灰度发布能力不够?我们是这么干的)

自研胖容器

目前在企业的应用生态中,云原生系统仍然仅占很小一部分,大量传统应用无法享受容器技术来带的好处。随着容器技术在企业生态中占比逐渐增加,传统应用上云的需求将逐步释放,胖容器技术将在其中发挥重要作用。

博云 BeyondVM 是一种基于container-based 实现的胖容器技术,兼容 OCI 标准,可以灵活的与 Kubernetes 集群进行集成。胖容器解决方案在传统应用(非微服务架构)迁移到容器云平台中,针对传统应用需要安装各种 agent、满足业务灵活性和弹性、发挥强大服务器硬件的能力、满足运维人员手动调整需求、应对性能敏感等问题上,比虚拟机和容器更具优势。(兼容传统应用,蓄力边缘云——博云胖容器解决方案)

其中,博云 BeyondFabric 容器网络 与 BeyondVM 胖容器解决方案入选了由中国信息通信研究院布的国内首个云原生技术生态图景 (博云产品入选国内首个云原生技术生态图景 | 行业观察)

布局PaaS产品体系

实现应用管理敏捷化

博云在这些容器底层技术领域的持续深耕与自主创新,使博云成为了为数不多的掌握容器云底层核心技术的提供商之一。目前,博云容器云已在银行、证券、保险、电力、能源、高端制造等多个行业中实现生产系统落地,平台能力经过了长期生产级有效验证,帮助客户实现 IT 应用全生命周期管理的敏捷性,释放 IT 基础架构生产力。

115711596511885_.pic_hd_.jpg


目前,基于容器这一云原生技术基石,博云形成了以敏捷化应用管理为核心的 PaaS 产品体系布局,将容器、微服务和 DevOps 等产品深度整合与集成,实现应用一站式全生命周期管理。并且已帮助超 200 家大型企业从传统 IT 架构向云原生架构转型,从业务架构、技术架构、研发流程、组织架构等多方面帮助企业进行云原生体系建设。

此次入选 Gartner “ 2020中国 ICT 技术成熟度曲线报告 ”是对博云产品能力、客户覆盖、市场竞争力的权威认可。未来,博云也将继续积极参与云原生技术开源社区贡献,把自身积累的技术经验回馈社区,不断提升产品的自主创新与研发能力,以丰富成熟的云原生技术落地服务能力,赋能更多的客户实现数字化转型。
继续阅读 »

近日,全球权威的信息技术研究和分析公司 Gartner 发布了《Hype Cycle for ICT in China, 2020》报告即“2020中国 ICT 技术成熟度曲线报告”,其中容器即服务( CaaS )为新兴技术热点,取得了飞速成长,且市场对容器技术的关注与兴趣仍在急剧上升中。BoCloud博云作为国内容器云领域( CaaS )的领军企业入选该报告,被评为 CaaS 容器云“代表性厂商”( Sample Vendor )。

技术成熟度曲线是 Gartner 为企业提供的评估新技术成熟度的典型工具。新兴技术是支持企业数字化转型的关键创新引擎,中国 ICT 技术成熟度曲线是企业用户和技术厂商提供评估新技术成熟度的典型工具,也是评估新兴数字化技术趋势、技术潜力和商业潜力提供重要依据。

Gartner

容器平台是中国ICT市场热点

Gartner 指出,对于企业而言,2020年数字化转型仍然是高度优先事项。企业正在经历从技术导向向服务导向的转变,其中以容器、DevOps、多云平台为代表的现代化基础设施平台是这些企业需要重点关注的三大方向之一。报告中显示,CaaS(容器即服务)作为新兴技术热点,取得了飞速成长,由于人们对容器运行时的采用越来越多,市场对容器技术的关注与兴趣仍在急剧上升中。

115701596511881_.pic_hd_.jpg


Gartner 指出,云原生应用程序需要高度的基础设施自动化、专业化的操作能力,但这对于企业 IT 并不容易实现。而 CaaS 容器云可以让企业 IT 更便捷地使用容器功能,为企业 IT 在生产力和敏捷性带来了显而易见的优势,包括加速和简化应用程序生命周期能力、实现不同环境间的工作负载可移植性、提高资源利用率等。

在中国本土 CaaS 容器云市场上,当前容器技术收益合理,市场潜力覆盖了5%-20%的目标受众,技术成熟度凸显。Gartner 指出,以 BoCloud 博云为代表的国内容器服务提供商是强有力的本土竞争者。

博云

深耕容器领域,掌握底层核心能力

近年来,容器技术凭借轻量化和标准化的显著特性,逐渐成为云计算领域基础设施云化的变革技术。作为云原生( cloud native )生态的基石,容器技术已然成为云原生时代的标准基础设施。

作为国内最早瞄准容器领域为企业级用户提供容器云服务的提供商之一,博云基于 kubernetes 自主研发的 BeyondContainer 容器云平台,一直坚持聚焦平台底层能力的提升,根据用户实际需求,对容器网络、负载均衡能力、胖容器等容器底层核心技术进行了改进与增强,确保能满足用户 IT 敏捷化的需求。

自研容器网络

网络对于容器云平台的稳定性、扩展性影响非常大。随着容器云平台在企业的大量落地,企业亟需缓解在落地私有容器云平台时遇到的网络阻力。博云 BeyondFabric 容器网络是基于OpenVswitch (OVS) 自研的 Kubernetes CNI 插件,可以实现内外网互通、管理业务网络分离、灵活的网络隔离机制、易于运维管理和调试等功能。

同时支持 underlay 和 overlay 网络,重点解决微服务上云过程中,集群内外互相直接通信的问题,大大降级企业落地容器云平台的复杂度,使业务迁移到容器云后,几乎感知不到基础设施从虚拟化到容器化变更带来的变化。(为什么我们要自主开发一个稳定可靠的容器网络)

增强负载均衡

在对社区版 Nginx Ingress Controller 进行了全面调研和深入理解之后,博云针对社区版 Nginx IngresController 做了进一步模型改进和功能扩充,自研 Ingress 控制器 BeyondELB。支持租户级负载、热更新、多版本灰度发布等特性,大大增强了 Nginx Ingress Controller 的功能特性和扩展能力。(原生Ingress灰度发布能力不够?我们是这么干的)

自研胖容器

目前在企业的应用生态中,云原生系统仍然仅占很小一部分,大量传统应用无法享受容器技术来带的好处。随着容器技术在企业生态中占比逐渐增加,传统应用上云的需求将逐步释放,胖容器技术将在其中发挥重要作用。

博云 BeyondVM 是一种基于container-based 实现的胖容器技术,兼容 OCI 标准,可以灵活的与 Kubernetes 集群进行集成。胖容器解决方案在传统应用(非微服务架构)迁移到容器云平台中,针对传统应用需要安装各种 agent、满足业务灵活性和弹性、发挥强大服务器硬件的能力、满足运维人员手动调整需求、应对性能敏感等问题上,比虚拟机和容器更具优势。(兼容传统应用,蓄力边缘云——博云胖容器解决方案)

其中,博云 BeyondFabric 容器网络 与 BeyondVM 胖容器解决方案入选了由中国信息通信研究院布的国内首个云原生技术生态图景 (博云产品入选国内首个云原生技术生态图景 | 行业观察)

布局PaaS产品体系

实现应用管理敏捷化

博云在这些容器底层技术领域的持续深耕与自主创新,使博云成为了为数不多的掌握容器云底层核心技术的提供商之一。目前,博云容器云已在银行、证券、保险、电力、能源、高端制造等多个行业中实现生产系统落地,平台能力经过了长期生产级有效验证,帮助客户实现 IT 应用全生命周期管理的敏捷性,释放 IT 基础架构生产力。

115711596511885_.pic_hd_.jpg


目前,基于容器这一云原生技术基石,博云形成了以敏捷化应用管理为核心的 PaaS 产品体系布局,将容器、微服务和 DevOps 等产品深度整合与集成,实现应用一站式全生命周期管理。并且已帮助超 200 家大型企业从传统 IT 架构向云原生架构转型,从业务架构、技术架构、研发流程、组织架构等多方面帮助企业进行云原生体系建设。

此次入选 Gartner “ 2020中国 ICT 技术成熟度曲线报告 ”是对博云产品能力、客户覆盖、市场竞争力的权威认可。未来,博云也将继续积极参与云原生技术开源社区贡献,把自身积累的技术经验回馈社区,不断提升产品的自主创新与研发能力,以丰富成熟的云原生技术落地服务能力,赋能更多的客户实现数字化转型。 收起阅读 »

掌门教育微服务体系 Solar | 阿里巴巴 Nacos 企业级落地中篇


联席作者:吴毅挺 任浩军 童子龙
郑重鸣谢:Nacos - 彦林,Spring Cloud Alibaba - 小马哥、洛夜,Nacos 社区 - 张龙(pader)、春少(chuntaojun)

相关文章推荐:


前言

> 在高速发展的时候,公司规模越来越大,老师人数越来越多,这时候公司不能铺太多人去做运营与服务,必须提高每个人效,这就需要技术驱动。因此掌门教育转变成一家技术驱动型的公司,如果被迫成为一家靠资金驱动的公司就活不下去了。

-- 张翼(掌门教育创始人兼 CEO)

掌门教育自 2014 年正式转型在线教育以来,秉承“让教育共享智能,让学习高效快乐”的宗旨和愿景,经历云计算、大数据、人工智能、 AR / VR / MR 以及现今最火的 5G ,一直坚持用科技赋能教育。掌门教育的业务近几年得到了快速发展,特别是今年的疫情,使在线教育成为了新的风口,也给掌门教育新的机遇。

随着业务规模进一步扩大,流量进一步暴增,微服务数目进一步增长,使老的微服务体系所采用的注册中心 Eureka 不堪重负,同时 Spring Cloud 体系已经演进到第二代,第一代的 Eureka 注册中心已经不大适合现在的业务逻辑和规模,同时它目前被 Spring Cloud 官方置于维护模式,将不再向前发展。如何选择一个更为优秀和适用的注册中心,这个课题就摆在了掌门人的面前。经过对 Alibaba NacosHashiCorp Consul等开源注册中心做了深入的调研和比较,最终选定 Alibaba Nacos 做微服务体系 Solar 中的新注册中心。

背景故事

两次 Eureka 引起业务服务大面积崩溃后,虽然通过升级硬件和优化配置参数的方式得以解决,Eureka 服务器目前运行平稳,但我们依旧担心此类事故在未来会再次发生,最终选择落地 Alibaba Nacos 作为掌门教育的新注册中心。

Nacos 开发篇

Nacos Eureka Sync 方案演进

① Sync 官方方案

经过研究,我们采取了官方的 Nacos Eureka Sync 方案,在小范围试用了一下,效果良好,但一部署到 FAT 环境后,发现根本不行,一台同步服务器无法抗住将近 660 个服务(非实例数)的频繁心跳,同时该方案不具备高可用特点。

② Sync 高可用一致性 Hash + Zookeeper 方案

既然一台不行,那么就多几台,但如何做高可用呢?

我们率先想到的是一致性 Hash 方式。当一台或者几台同步服务器挂掉后,采用 Zookeeper 临时节点的 Watch 机制监听同步服务器挂掉情况,通知剩余同步服务器执行 reHash ,挂掉服务的工作由剩余的同步服务器来承担。通过一致性 Hash 实现被同步的业务服务列表的平均分配,基于对业务服务名的二进制转换作为 HashKey 实现一致性 Hash 的算法。我们自研了这套算法,发现平均分配的很不理想,第一时间怀疑是否算法有问题,于是找来 Kafka 自带的算法(见 Utils.murmur2 ),发现效果依旧不理想,原因还是业务服务名的本身分布就是不平均的,于是又回到自研算法上进行了优化,基本达到预期,下文会具体讲到。但说实话,直到现在依旧无法做到非常良好的绝对平均。

③ Sync 高可用主备 + Zookeeper 方案

这个方案是个小插曲,当一台同步服务器挂掉后,由它的“备”顶上,当然主备切换也是基于 Zookeeper 临时节点的 Watch 机制来实现的。后面讨论下来,主备方案,机器的成本很高,实现也不如一致性 Hash 优雅,最后没采用。

④ Sync 高可用一致性 Hash + Etcd 方案

折腾了这么几次后,发现同步业务服务列表是持久化在数据库,同步服务器挂掉后 reHash 通知机制是由 Zookeeper 来负责,两者能否可以合并到一个中间件上以降低成本?于是我们想到了 Etcd 方案,即通过它实现同步业务服务列表持久化 + 业务服务列表增减的通知 + 同步服务器挂掉后 reHash 通知。至此方案最终确定,即两个注册中心( EurekaNacos )的双向同步方案,通过第三个注册中心( Etcd )来做桥梁。

⑤ Sync 业务服务名列表定时更新优化方案

解决了一致性 Hash 的问题后,还有一个潜在风险,即官方方案每次定时同步业务服务的时候,都会去读取全量业务服务名列表,对于业务服务数较少的场景应该没问题,但对于我们这种场景下,这么频繁的全量去拉业务服务列表,会不会对 Nacos 服务器的性能有所冲击呢?接下去我们对此做了优化,取消全量定时读取业务服务名列表,通过 DevOps 的发布系统平台实施判断,如果是迁移过来的业务服务或者新上 Nacos 的业务服务,由发布平台统一调用 Nacos 接口来增加新的待同步业务服务 Job,当该业务服务全部迁移完毕后,在官方同步界面上删除该同步业务服务 Job 即可。

⑥ Sync 服务器两次扩容

方案实现后,上了 FAT 环境上后没发现问题(此环境,很多业务服务只部署一个实例),而在 PROD 环境上发现存在双向同步丢心跳的问题,原因是同步服务器来不及执行排队的心跳线程,导致 Nacos 服务器无法及时收到心跳而把业务服务踢下来。我们从 8 台 4C8G 同步服务器扩容到 12 台,情况好了很多,但观察下来,还是存在一天内存在一些业务服务丢失心跳的情况,于是我们再次从 12 台 4C8G 同步服务器扩容到 20 台,情况得到了大幅改善,但依旧存在某个同步服务器上个位数丢失心跳的情况,观察下来,那台同步服务器承受的某几个业务服务的实例数特别多的情况,我们在那台同步服务器调整了最大同步线程数,该问题得到了修复。我们将继续观察,如果该问题仍旧复现,不排除升级机器配置到 8C16G 来确保 PROD 环境的绝对安全。

至此,经过 2 个月左右的努力付出,EurekaNacos 同步运行稳定, PROD 环境上同步将近 660 个服务(非实例数),情况良好。


非常重要的提醒:一致性 Hash 的虚拟节点数,在所有的 Nacos Sync Server 上必须保持一致,否则会导致一部分业务服务同步的时候会被遗漏。

Nacos Eureka Sync 落地实践

① Nacos Eureka Sync 目标原则


  • 注册中心迁移目标
    • 过程并非一蹴而就的,业务服务逐步迁移的过程要保证线上调用不受影响,例如, A 业务服务注册到 Eureka 上, B 业务服务迁移到 NacosA 业务服务和 B 业务服务的互相调用必须正常;
    • 过程必须保证双注册中心都存在这两个业务服务,并且目标注册中心的业务服务实例必须与源注册中心的业务服务实例数目和状态保持实时严格一致。

  • 注册中心迁移原则
    • 一个业务服务只能往一个注册中心注册,不能同时双向注册;
    • 一个业务服务无论注册到 Eureka 或者 Nacos,最终结果都是等效的;
    • 一个业务服务在绝大多数情况下,一般只存在一个同步任务,如果是注册到 Eureka 的业务服务需要同步到 Nacos ,那就有一个 Eureka -> Nacos 的同步任务,反之亦然。在平滑迁移中,一个业务服务一部分实例在 Eureka 上,另一部分实例在 Nacos 上,那么会产生两个双向同步的任务;
    • 一个业务服务的同步方向,是根据业务服务实例元数据( Metadata )的标记 syncSource 来决定。


② Nacos Eureka Sync 问题痛点

  • Nacos Eureka Sync 同步节点需要代理业务服务实例和 Nacos Server 间的心跳上报。Nacos Eureka Sync 将心跳上报请求放入队列,以固定线程消费,一个同步业务服务节点处理的服务实例数超过一定的阈值会造成业务服务实例的心跳发送不及时,从而造成业务服务实例的意外丢失。
  • Nacos Eureka Sync 节点宕机,上面处理的心跳任务会全部丢失,会造成线上调用大面积失败,后果不堪设想。
  • Nacos Eureka Sync 已经开始工作的时候,从 Eureka 或者 Nacos 上,新上线或者下线一个业务服务(非实例),都需要让 Nacos Eureka Sync 实时感知。


③ Nacos Eureka Sync 架构思想

1.png

  • 从各个注册中心获取业务服务列表,初始化业务服务同步任务列表,并持久化到 Etcd 集群中;
  • 后续迁移过程增量业务服务通过 API 接口持久化到 Etcd 集群中,业务服务迁移过程整合 DevOps 发布平台。整个迁移过程全自动化,规避人为操作造成的遗漏;
  • 同步服务订阅 Etcd 集群获取任务列表,并监听同步集群的节点状态;
  • 同步服务根据存活节点的一致性 Hash 算法,找到处理任务节点,后端接口通过 SLB 负载均衡,删除任务指令轮询到的节点。如果是自己处理任务则移除心跳,否则找到处理节点,代理出去;
  • 同步服务监听源注册中心每个业务服务实例状态,将正常的业务服务实例同步到目标注册中心,保证双方注册中心的业务服务实例状态实时同步;
  • 业务服务所有实例从 EurekaNacos 后,需要业务部门通知基础架构部手动从 Nacos Eureka Sync 同步界面摘除该同步任务。


④ Nacos Eureka Sync 方案实现

2.png


基于官方的 Nacos Sync 做任务分片和集群高可用,目标是为了支持大规模的注册集群迁移,并保障在节点宕机时,其它节点能快速响应,转移故障。技术点如下,文中只列出部分源码或者以伪代码表示:


详细代码,请参考:https://github.com/zhangmen-tech/nacos

服务一致性 Hash 分片路由

  • 根据如图 1 多集群部署,为每个节点设置可配置的虚拟节点数,使其在 Hash 环上能均匀分布;


```java
// 虚拟节点配置
sync.consistent.hash.replicas = 1000;

// 存储虚拟节点
SortedMap<Integer, T> circle = new TreeMap<Integer, T>();
// 循环添加所有节点到容器,构建Hash环
replicas for loop {
// 为每个物理节点设置虚拟节点
String nodeStr = node.toString().concat("##").concat(Integer.toString(replica));
// 根据算法计算出虚拟节点的Hash值
int hashcode = getHash(nodeStr);
// 将虚拟节点放入Hash环中
circle.put(hashcode, node);


// 异步监听节点存活状态
etcdManager.watchEtcdKeyAsync(REGISTER_WORKER_PATH, true, response -> {
for (WatchEvent event : response.getEvents()) {
// 删除事件,从内存中剔除此节点及Hash中虚拟节点
if (event.getEventType().equals(WatchEvent.EventType.DELETE)) {
String key = Optional.ofNullable(event.getKeyValue().getKey()).map(bs -> bs.toString(Charsets.UTF_8)).orElse(StringUtils.EMPTY);
//获取Etcd中心跳丢失的节点
String[] ks = key.split(SLASH);
log.info("{} lost heart beat", ks[3]);
// 自身节点不做判断
if (!IPUtils.getIpAddress().equalsIgnoreCase(ks[3])) {
// 监听心跳丢失,更显存货节点缓存,删除Hash环上节点
nodeCaches.remove(ks[3]);
try {
// 心跳丢失,清除etcd上该节点的处理任务
manager.deleteEtcdValueByKey(PER_WORKER_PROCESS_SERVICE.concat(SLASH).concat(ks[3]), true);
} catch (InterruptedException e) {
log.error("clear {} process service failed,{}", ks[3], e);
} catch (ExecutionException e) {
log.error("clear {} process service failed,{}", ks[3], e);
}
}
}
}
```
  • 根据业务服务名的 FNV1_32_HASH 算法计算每个业务服务的哈希值,计算该 Hash 值顺时针最近的节点,将任务代理到该节点。


```java
// 计算任务的Hash值
int hash = getHash(key.toString());
if (!circle.containsKey(hash)) {
SortedMap<Integer, T> tailMap = circle.tailMap(hash);
// 找到顺势针最近节点
hash = tailMap.isEmpty() ? circle.firstKey() : tailMap.firstKey();
}

// 得到Hash环中的节点位置
circle.get(hash);

// 判断任务是否自己的处理节点
if (syncShardingProxy.isProcessNode(taskDO.getServiceName())) {
//如果任务属于该节点,则进行心跳同步处理
processTask(Task);
}

// 删除心跳同步任务
if (TaskStatusEnum.DELETE.getCode().equals(taskUpdateRequest.getTaskStatus())) {
// 通过Etcd存活节点的一致性Hash算法,获取此任务所在的处理节点
Node processNode = syncShardingProxy.fetchProcessNode(Task);
if (processNode.isMyself()) {
// 如果是自己的同步任务,发布删除心跳事件
eventBus.post(new DeleteTaskEvent(taskDO));
} else {
// 如果是其他节点,则通过Http代理到此节点处理
httpClientProxy.deleteTask(targetUrl,task);
}
}
```

同步节点宕机故障转移

  • 节点监听:监听其它节点存活状态,配置 Etcd 集群租约 TTLTTL 内至少发送 5 个续约心跳以保证一旦出现网络波动避免造成节点丢失;


```java
// 心跳TTL配置
sync.etcd.register.ttl = 30;

// 获取租约TTL配置
String ttls = environment.getProperty(ETCD_BEAT_TTL);
long ttl = NumberUtils.toLong(ttls);

// 获取租约ID
long leaseId = client.getLeaseClient().grant(ttl).get().getID();
PutOption option = PutOption.newBuilder().withLeaseId(leaseId).withPrevKV().build();
client.getKVClient().put(ByteSequence.from(key, UTF_8), ByteSequence.from(value, UTF_8), option).get();
long delay = ttl / 6;

// 定时续约
scheduledExecutorService.schedule(new BeatTask(leaseId, delay), delay, TimeUnit.SECONDS);

// 续约任务
private class BeatTask implements Runnable {
long leaseId;
long delay;

public BeatTask(long leaseId, long delay) {
this.leaseId = leaseId;
this.delay = delay;
}

public void run() {
client.getLeaseClient().keepAliveOnce(leaseId);
scheduledExecutorService.schedule(new BeatTask(this.leaseId, this.delay), delay, TimeUnit.SECONDS);
}
}
```

  • 节点宕机:其中某个节点宕机,其任务转移到其它节点,因为有虚拟节点的缘故,所以此节点的任务会均衡 ReSharding 到其它节点,那么,集群在任何时候,任务处理都是分片均衡的,如图 2 中, B 节点宕机, ##1##2 虚拟节点的任务会分别转移到 CA 节点,这样避免一个节点承担宕机节点的所有任务造成剩余节点连续雪崩;

  • 节点恢复:如图 3,节点的虚拟节点重新添加到 Hash 环中, Sharding 规则变更,恢复的节点会根据新的 Hash 环规则承担其它节点的一部分任务。心跳任务一旦在节点产生都不会自动消失,这时需要清理其它节点的多余任务(即重新分配给复苏节点的任务),给其它节点减负(这一步非常关键,不然也可能会引发集群的连续雪崩),保障集群恢复到最初正常任务同步状态;


```java
// 找到此节点处理的心跳同步任务
Map<String, FinishedTask> finishedTaskMap = skyWalkerCacheServices.getFinishedTaskMap();

// 存储非此节点处理任务
Map<String, FinishedTask> unBelongTaskMap = Maps.newHashMap();

// 找到集群复苏后,Rehash后不是此节点处理的任务
if (!shardingEtcdProxy.isProcessNode(taskDO.getServiceName()) && TaskStatusEnum.SYNC.getCode().equals(taskDO.getTaskStatus())) {
unBelongTaskMap.put(operationId, entry.getValue());
}

unBelongTaskMap for loop {
// 删除多余的节点同步
specialSyncEventBus.unsubscribe(taskDO);

// 删除多余的节点处理任务数
proxy.deleteEtcdValueByKey(PER_WORKER_PROCESS_SERVICE.concat(SLASH).concat(IPUtils.getIpAddress()).concat(SLASH).concat(taskDO.getServiceName()), false);

// 根据不同的同步类型,删除多余的节点心跳
if (ClusterTypeEnum.EUREKA.getCode().equalsIgnoreCase(clusterDO.getClusterType())) {
syncToNacosService.deleteHeartBeat(taskDO);
}

if (ClusterTypeEnum.NACOS.getCode().equalsIgnoreCase(clusterDO.getClusterType())) {
syncToEurekaService.deleteHeartBeat(taskDO);
}

// 删除多余的finish任务
finishedTaskMap.remove(val.getKey());
}
```
  • 节点容灾:如果 Etcd 集群连接不上,则存活节点从配置文件中获取,集群正常运作,但是会失去容灾能力。


```java
// 配置所有处理节点的机器IP,用于构建Hash环
sync.worker.address = ip1, ip2, ip3;

// 从配置文件获取所有处理任务节点IP
List<String> ips = getWorkerIps();
ConsistentHash<String> consistentHash = new ConsistentHash(replicas, ips);

// 如果从Etcd中获取不到当前处理节点,则构建Hash环用配置文件中的IP列表,且列表不会动态变化
if (CollectionUtils.isNotEmpty(nodeCaches)) {
consistentHash = new ConsistentHash(replicas, nodeCaches);
}

return consistentHash;
```

Nacos Eureka Sync 保障手段

① Nacos Eureka Sync 同步界面

从如下界面可以保证,从 Eureka 或者 Nacos 上,新上线或者下线一个业务服务(非实例),都能让 Nacos Eureka Sync 实时感知。但我们做了更进一层的智能化和自动化:
  • 新增同步:结合 DevOps 发布平台,当一个业务服务(非实例)新上线的时候,智能判断它是从哪个注册中心上线的,然后回调 Nacos Eureka Sync 接口,自动添加同步接口,例如,A 业务服务注册到 Eureka 上,DevOps 发布平台会自动添加它的 Eureka -> Nacos 的同步任务,反之亦然。当然从如下界面的操作也可实现该功能;
  • 删除同步:由于 DevOps 发布平台无法判断一个业务服务(非实例)下线,或者已经迁移到另一个注册中心,已经全部完毕(有同学会反问,可以判断的,即查看那个业务服务的实例数是否是零为标准,但我们应该考虑,实例数为零在网络故障的时候也会发生,即心跳全部丢失,所以这个判断依据是不严谨的),交由业务人员来判断,同时配合钉钉机器人告警提醒,由基础架构部同学从如下界面的操作实现该功能;


3.png


② Nacos Eureka Sync Etcd 监控

从如下界面可以监控到,业务服务列表是否在同步服务的集群上呈现一致性 Hash 均衡分布。

4.png


③ Nacos Eureka Sync 告警

5.jpg

  • 业务服务同步完毕告警


6.png


Nacos Eureka Sync 升级演练

  • 7 月某天晚上 10 点开始, FAT 环境进行演练,通过自动化运维工具 Ansible 两次执行一键升级和回滚均没问题;
  • 晚上 11 点 30 开始,执行灾难性操作,观察智能恢复状况, 9 台 Nacos Eureka Sync 挂掉 3 台的操作,只丢失一个实例,但 5 分钟后恢复(经调查,问题定位在 Eureka 上某个业务服务实例状态异常);
  • 晚上 11 点 45 开始,继续挂掉 2 台,只剩 4 台,故障转移,同步正常;
  • 晚上 11 点 52 开始,恢复 2 台,Nacos Eureka Sync 集群重新均衡 ReHash ,同步正常;
  • 晚上 11 点 55 开始,全部恢复,Nacos Eureka Sync 集群重新均衡 ReHash ,同步正常;
  • 12 点 14 分,极限灾难演练, 9 台挂掉 8 台,剩 1 台也能抗住,故障转移,同步正常;
  • 凌晨 12 点 22 分,升级 UAT 环境顺利;
  • 凌晨 1 点 22,升级 PROD 环境顺利;
  • 容灾恢复中的 ReHash 时间小于 1 分钟,即 Nacos Eureka Sync 服务大面积故障发生时,恢复时间小于 1 分钟。


作者介绍

  • 吴毅挺,掌门技术副总裁,负责技术中台和少儿技术团队。曾就职于百度、eBay 、携程,曾任携程高级研发总监,负责从零打造携程私有云、容器云、桌面云和 PaaS 平台。
  • 任浩军,掌门基础架构部负责人。曾就职于平安银行、万达、惠普,曾负责平安银行平台架构部 PaaS 平台 Halo 基础服务框架研发。10 多年开源经历,Github ID:@HaojunRen,Nepxion 开源社区创始人,Nacos Group Member,Spring Cloud Alibaba & Nacos & Sentinel & OpenTracing Committer。


参与 Nacos 落地的基础架构部成员,包括:
  • 童子龙,张彬彬,廖梦鸽,张金星,胡振建,谢璐,谢庆芳,伊安娜


阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”
继续阅读 »

联席作者:吴毅挺 任浩军 童子龙
郑重鸣谢:Nacos - 彦林,Spring Cloud Alibaba - 小马哥、洛夜,Nacos 社区 - 张龙(pader)、春少(chuntaojun)

相关文章推荐:


前言

> 在高速发展的时候,公司规模越来越大,老师人数越来越多,这时候公司不能铺太多人去做运营与服务,必须提高每个人效,这就需要技术驱动。因此掌门教育转变成一家技术驱动型的公司,如果被迫成为一家靠资金驱动的公司就活不下去了。

-- 张翼(掌门教育创始人兼 CEO)

掌门教育自 2014 年正式转型在线教育以来,秉承“让教育共享智能,让学习高效快乐”的宗旨和愿景,经历云计算、大数据、人工智能、 AR / VR / MR 以及现今最火的 5G ,一直坚持用科技赋能教育。掌门教育的业务近几年得到了快速发展,特别是今年的疫情,使在线教育成为了新的风口,也给掌门教育新的机遇。

随着业务规模进一步扩大,流量进一步暴增,微服务数目进一步增长,使老的微服务体系所采用的注册中心 Eureka 不堪重负,同时 Spring Cloud 体系已经演进到第二代,第一代的 Eureka 注册中心已经不大适合现在的业务逻辑和规模,同时它目前被 Spring Cloud 官方置于维护模式,将不再向前发展。如何选择一个更为优秀和适用的注册中心,这个课题就摆在了掌门人的面前。经过对 Alibaba NacosHashiCorp Consul等开源注册中心做了深入的调研和比较,最终选定 Alibaba Nacos 做微服务体系 Solar 中的新注册中心。

背景故事

两次 Eureka 引起业务服务大面积崩溃后,虽然通过升级硬件和优化配置参数的方式得以解决,Eureka 服务器目前运行平稳,但我们依旧担心此类事故在未来会再次发生,最终选择落地 Alibaba Nacos 作为掌门教育的新注册中心。

Nacos 开发篇

Nacos Eureka Sync 方案演进

① Sync 官方方案

经过研究,我们采取了官方的 Nacos Eureka Sync 方案,在小范围试用了一下,效果良好,但一部署到 FAT 环境后,发现根本不行,一台同步服务器无法抗住将近 660 个服务(非实例数)的频繁心跳,同时该方案不具备高可用特点。

② Sync 高可用一致性 Hash + Zookeeper 方案

既然一台不行,那么就多几台,但如何做高可用呢?

我们率先想到的是一致性 Hash 方式。当一台或者几台同步服务器挂掉后,采用 Zookeeper 临时节点的 Watch 机制监听同步服务器挂掉情况,通知剩余同步服务器执行 reHash ,挂掉服务的工作由剩余的同步服务器来承担。通过一致性 Hash 实现被同步的业务服务列表的平均分配,基于对业务服务名的二进制转换作为 HashKey 实现一致性 Hash 的算法。我们自研了这套算法,发现平均分配的很不理想,第一时间怀疑是否算法有问题,于是找来 Kafka 自带的算法(见 Utils.murmur2 ),发现效果依旧不理想,原因还是业务服务名的本身分布就是不平均的,于是又回到自研算法上进行了优化,基本达到预期,下文会具体讲到。但说实话,直到现在依旧无法做到非常良好的绝对平均。

③ Sync 高可用主备 + Zookeeper 方案

这个方案是个小插曲,当一台同步服务器挂掉后,由它的“备”顶上,当然主备切换也是基于 Zookeeper 临时节点的 Watch 机制来实现的。后面讨论下来,主备方案,机器的成本很高,实现也不如一致性 Hash 优雅,最后没采用。

④ Sync 高可用一致性 Hash + Etcd 方案

折腾了这么几次后,发现同步业务服务列表是持久化在数据库,同步服务器挂掉后 reHash 通知机制是由 Zookeeper 来负责,两者能否可以合并到一个中间件上以降低成本?于是我们想到了 Etcd 方案,即通过它实现同步业务服务列表持久化 + 业务服务列表增减的通知 + 同步服务器挂掉后 reHash 通知。至此方案最终确定,即两个注册中心( EurekaNacos )的双向同步方案,通过第三个注册中心( Etcd )来做桥梁。

⑤ Sync 业务服务名列表定时更新优化方案

解决了一致性 Hash 的问题后,还有一个潜在风险,即官方方案每次定时同步业务服务的时候,都会去读取全量业务服务名列表,对于业务服务数较少的场景应该没问题,但对于我们这种场景下,这么频繁的全量去拉业务服务列表,会不会对 Nacos 服务器的性能有所冲击呢?接下去我们对此做了优化,取消全量定时读取业务服务名列表,通过 DevOps 的发布系统平台实施判断,如果是迁移过来的业务服务或者新上 Nacos 的业务服务,由发布平台统一调用 Nacos 接口来增加新的待同步业务服务 Job,当该业务服务全部迁移完毕后,在官方同步界面上删除该同步业务服务 Job 即可。

⑥ Sync 服务器两次扩容

方案实现后,上了 FAT 环境上后没发现问题(此环境,很多业务服务只部署一个实例),而在 PROD 环境上发现存在双向同步丢心跳的问题,原因是同步服务器来不及执行排队的心跳线程,导致 Nacos 服务器无法及时收到心跳而把业务服务踢下来。我们从 8 台 4C8G 同步服务器扩容到 12 台,情况好了很多,但观察下来,还是存在一天内存在一些业务服务丢失心跳的情况,于是我们再次从 12 台 4C8G 同步服务器扩容到 20 台,情况得到了大幅改善,但依旧存在某个同步服务器上个位数丢失心跳的情况,观察下来,那台同步服务器承受的某几个业务服务的实例数特别多的情况,我们在那台同步服务器调整了最大同步线程数,该问题得到了修复。我们将继续观察,如果该问题仍旧复现,不排除升级机器配置到 8C16G 来确保 PROD 环境的绝对安全。

至此,经过 2 个月左右的努力付出,EurekaNacos 同步运行稳定, PROD 环境上同步将近 660 个服务(非实例数),情况良好。


非常重要的提醒:一致性 Hash 的虚拟节点数,在所有的 Nacos Sync Server 上必须保持一致,否则会导致一部分业务服务同步的时候会被遗漏。

Nacos Eureka Sync 落地实践

① Nacos Eureka Sync 目标原则


  • 注册中心迁移目标
    • 过程并非一蹴而就的,业务服务逐步迁移的过程要保证线上调用不受影响,例如, A 业务服务注册到 Eureka 上, B 业务服务迁移到 NacosA 业务服务和 B 业务服务的互相调用必须正常;
    • 过程必须保证双注册中心都存在这两个业务服务,并且目标注册中心的业务服务实例必须与源注册中心的业务服务实例数目和状态保持实时严格一致。

  • 注册中心迁移原则
    • 一个业务服务只能往一个注册中心注册,不能同时双向注册;
    • 一个业务服务无论注册到 Eureka 或者 Nacos,最终结果都是等效的;
    • 一个业务服务在绝大多数情况下,一般只存在一个同步任务,如果是注册到 Eureka 的业务服务需要同步到 Nacos ,那就有一个 Eureka -> Nacos 的同步任务,反之亦然。在平滑迁移中,一个业务服务一部分实例在 Eureka 上,另一部分实例在 Nacos 上,那么会产生两个双向同步的任务;
    • 一个业务服务的同步方向,是根据业务服务实例元数据( Metadata )的标记 syncSource 来决定。


② Nacos Eureka Sync 问题痛点

  • Nacos Eureka Sync 同步节点需要代理业务服务实例和 Nacos Server 间的心跳上报。Nacos Eureka Sync 将心跳上报请求放入队列,以固定线程消费,一个同步业务服务节点处理的服务实例数超过一定的阈值会造成业务服务实例的心跳发送不及时,从而造成业务服务实例的意外丢失。
  • Nacos Eureka Sync 节点宕机,上面处理的心跳任务会全部丢失,会造成线上调用大面积失败,后果不堪设想。
  • Nacos Eureka Sync 已经开始工作的时候,从 Eureka 或者 Nacos 上,新上线或者下线一个业务服务(非实例),都需要让 Nacos Eureka Sync 实时感知。


③ Nacos Eureka Sync 架构思想

1.png

  • 从各个注册中心获取业务服务列表,初始化业务服务同步任务列表,并持久化到 Etcd 集群中;
  • 后续迁移过程增量业务服务通过 API 接口持久化到 Etcd 集群中,业务服务迁移过程整合 DevOps 发布平台。整个迁移过程全自动化,规避人为操作造成的遗漏;
  • 同步服务订阅 Etcd 集群获取任务列表,并监听同步集群的节点状态;
  • 同步服务根据存活节点的一致性 Hash 算法,找到处理任务节点,后端接口通过 SLB 负载均衡,删除任务指令轮询到的节点。如果是自己处理任务则移除心跳,否则找到处理节点,代理出去;
  • 同步服务监听源注册中心每个业务服务实例状态,将正常的业务服务实例同步到目标注册中心,保证双方注册中心的业务服务实例状态实时同步;
  • 业务服务所有实例从 EurekaNacos 后,需要业务部门通知基础架构部手动从 Nacos Eureka Sync 同步界面摘除该同步任务。


④ Nacos Eureka Sync 方案实现

2.png


基于官方的 Nacos Sync 做任务分片和集群高可用,目标是为了支持大规模的注册集群迁移,并保障在节点宕机时,其它节点能快速响应,转移故障。技术点如下,文中只列出部分源码或者以伪代码表示:


详细代码,请参考:https://github.com/zhangmen-tech/nacos

服务一致性 Hash 分片路由

  • 根据如图 1 多集群部署,为每个节点设置可配置的虚拟节点数,使其在 Hash 环上能均匀分布;


```java
// 虚拟节点配置
sync.consistent.hash.replicas = 1000;

// 存储虚拟节点
SortedMap<Integer, T> circle = new TreeMap<Integer, T>();
// 循环添加所有节点到容器,构建Hash环
replicas for loop {
// 为每个物理节点设置虚拟节点
String nodeStr = node.toString().concat("##").concat(Integer.toString(replica));
// 根据算法计算出虚拟节点的Hash值
int hashcode = getHash(nodeStr);
// 将虚拟节点放入Hash环中
circle.put(hashcode, node);


// 异步监听节点存活状态
etcdManager.watchEtcdKeyAsync(REGISTER_WORKER_PATH, true, response -> {
for (WatchEvent event : response.getEvents()) {
// 删除事件,从内存中剔除此节点及Hash中虚拟节点
if (event.getEventType().equals(WatchEvent.EventType.DELETE)) {
String key = Optional.ofNullable(event.getKeyValue().getKey()).map(bs -> bs.toString(Charsets.UTF_8)).orElse(StringUtils.EMPTY);
//获取Etcd中心跳丢失的节点
String[] ks = key.split(SLASH);
log.info("{} lost heart beat", ks[3]);
// 自身节点不做判断
if (!IPUtils.getIpAddress().equalsIgnoreCase(ks[3])) {
// 监听心跳丢失,更显存货节点缓存,删除Hash环上节点
nodeCaches.remove(ks[3]);
try {
// 心跳丢失,清除etcd上该节点的处理任务
manager.deleteEtcdValueByKey(PER_WORKER_PROCESS_SERVICE.concat(SLASH).concat(ks[3]), true);
} catch (InterruptedException e) {
log.error("clear {} process service failed,{}", ks[3], e);
} catch (ExecutionException e) {
log.error("clear {} process service failed,{}", ks[3], e);
}
}
}
}
```
  • 根据业务服务名的 FNV1_32_HASH 算法计算每个业务服务的哈希值,计算该 Hash 值顺时针最近的节点,将任务代理到该节点。


```java
// 计算任务的Hash值
int hash = getHash(key.toString());
if (!circle.containsKey(hash)) {
SortedMap<Integer, T> tailMap = circle.tailMap(hash);
// 找到顺势针最近节点
hash = tailMap.isEmpty() ? circle.firstKey() : tailMap.firstKey();
}

// 得到Hash环中的节点位置
circle.get(hash);

// 判断任务是否自己的处理节点
if (syncShardingProxy.isProcessNode(taskDO.getServiceName())) {
//如果任务属于该节点,则进行心跳同步处理
processTask(Task);
}

// 删除心跳同步任务
if (TaskStatusEnum.DELETE.getCode().equals(taskUpdateRequest.getTaskStatus())) {
// 通过Etcd存活节点的一致性Hash算法,获取此任务所在的处理节点
Node processNode = syncShardingProxy.fetchProcessNode(Task);
if (processNode.isMyself()) {
// 如果是自己的同步任务,发布删除心跳事件
eventBus.post(new DeleteTaskEvent(taskDO));
} else {
// 如果是其他节点,则通过Http代理到此节点处理
httpClientProxy.deleteTask(targetUrl,task);
}
}
```

同步节点宕机故障转移

  • 节点监听:监听其它节点存活状态,配置 Etcd 集群租约 TTLTTL 内至少发送 5 个续约心跳以保证一旦出现网络波动避免造成节点丢失;


```java
// 心跳TTL配置
sync.etcd.register.ttl = 30;

// 获取租约TTL配置
String ttls = environment.getProperty(ETCD_BEAT_TTL);
long ttl = NumberUtils.toLong(ttls);

// 获取租约ID
long leaseId = client.getLeaseClient().grant(ttl).get().getID();
PutOption option = PutOption.newBuilder().withLeaseId(leaseId).withPrevKV().build();
client.getKVClient().put(ByteSequence.from(key, UTF_8), ByteSequence.from(value, UTF_8), option).get();
long delay = ttl / 6;

// 定时续约
scheduledExecutorService.schedule(new BeatTask(leaseId, delay), delay, TimeUnit.SECONDS);

// 续约任务
private class BeatTask implements Runnable {
long leaseId;
long delay;

public BeatTask(long leaseId, long delay) {
this.leaseId = leaseId;
this.delay = delay;
}

public void run() {
client.getLeaseClient().keepAliveOnce(leaseId);
scheduledExecutorService.schedule(new BeatTask(this.leaseId, this.delay), delay, TimeUnit.SECONDS);
}
}
```

  • 节点宕机:其中某个节点宕机,其任务转移到其它节点,因为有虚拟节点的缘故,所以此节点的任务会均衡 ReSharding 到其它节点,那么,集群在任何时候,任务处理都是分片均衡的,如图 2 中, B 节点宕机, ##1##2 虚拟节点的任务会分别转移到 CA 节点,这样避免一个节点承担宕机节点的所有任务造成剩余节点连续雪崩;

  • 节点恢复:如图 3,节点的虚拟节点重新添加到 Hash 环中, Sharding 规则变更,恢复的节点会根据新的 Hash 环规则承担其它节点的一部分任务。心跳任务一旦在节点产生都不会自动消失,这时需要清理其它节点的多余任务(即重新分配给复苏节点的任务),给其它节点减负(这一步非常关键,不然也可能会引发集群的连续雪崩),保障集群恢复到最初正常任务同步状态;


```java
// 找到此节点处理的心跳同步任务
Map<String, FinishedTask> finishedTaskMap = skyWalkerCacheServices.getFinishedTaskMap();

// 存储非此节点处理任务
Map<String, FinishedTask> unBelongTaskMap = Maps.newHashMap();

// 找到集群复苏后,Rehash后不是此节点处理的任务
if (!shardingEtcdProxy.isProcessNode(taskDO.getServiceName()) && TaskStatusEnum.SYNC.getCode().equals(taskDO.getTaskStatus())) {
unBelongTaskMap.put(operationId, entry.getValue());
}

unBelongTaskMap for loop {
// 删除多余的节点同步
specialSyncEventBus.unsubscribe(taskDO);

// 删除多余的节点处理任务数
proxy.deleteEtcdValueByKey(PER_WORKER_PROCESS_SERVICE.concat(SLASH).concat(IPUtils.getIpAddress()).concat(SLASH).concat(taskDO.getServiceName()), false);

// 根据不同的同步类型,删除多余的节点心跳
if (ClusterTypeEnum.EUREKA.getCode().equalsIgnoreCase(clusterDO.getClusterType())) {
syncToNacosService.deleteHeartBeat(taskDO);
}

if (ClusterTypeEnum.NACOS.getCode().equalsIgnoreCase(clusterDO.getClusterType())) {
syncToEurekaService.deleteHeartBeat(taskDO);
}

// 删除多余的finish任务
finishedTaskMap.remove(val.getKey());
}
```
  • 节点容灾:如果 Etcd 集群连接不上,则存活节点从配置文件中获取,集群正常运作,但是会失去容灾能力。


```java
// 配置所有处理节点的机器IP,用于构建Hash环
sync.worker.address = ip1, ip2, ip3;

// 从配置文件获取所有处理任务节点IP
List<String> ips = getWorkerIps();
ConsistentHash<String> consistentHash = new ConsistentHash(replicas, ips);

// 如果从Etcd中获取不到当前处理节点,则构建Hash环用配置文件中的IP列表,且列表不会动态变化
if (CollectionUtils.isNotEmpty(nodeCaches)) {
consistentHash = new ConsistentHash(replicas, nodeCaches);
}

return consistentHash;
```

Nacos Eureka Sync 保障手段

① Nacos Eureka Sync 同步界面

从如下界面可以保证,从 Eureka 或者 Nacos 上,新上线或者下线一个业务服务(非实例),都能让 Nacos Eureka Sync 实时感知。但我们做了更进一层的智能化和自动化:
  • 新增同步:结合 DevOps 发布平台,当一个业务服务(非实例)新上线的时候,智能判断它是从哪个注册中心上线的,然后回调 Nacos Eureka Sync 接口,自动添加同步接口,例如,A 业务服务注册到 Eureka 上,DevOps 发布平台会自动添加它的 Eureka -> Nacos 的同步任务,反之亦然。当然从如下界面的操作也可实现该功能;
  • 删除同步:由于 DevOps 发布平台无法判断一个业务服务(非实例)下线,或者已经迁移到另一个注册中心,已经全部完毕(有同学会反问,可以判断的,即查看那个业务服务的实例数是否是零为标准,但我们应该考虑,实例数为零在网络故障的时候也会发生,即心跳全部丢失,所以这个判断依据是不严谨的),交由业务人员来判断,同时配合钉钉机器人告警提醒,由基础架构部同学从如下界面的操作实现该功能;


3.png


② Nacos Eureka Sync Etcd 监控

从如下界面可以监控到,业务服务列表是否在同步服务的集群上呈现一致性 Hash 均衡分布。

4.png


③ Nacos Eureka Sync 告警

5.jpg

  • 业务服务同步完毕告警


6.png


Nacos Eureka Sync 升级演练

  • 7 月某天晚上 10 点开始, FAT 环境进行演练,通过自动化运维工具 Ansible 两次执行一键升级和回滚均没问题;
  • 晚上 11 点 30 开始,执行灾难性操作,观察智能恢复状况, 9 台 Nacos Eureka Sync 挂掉 3 台的操作,只丢失一个实例,但 5 分钟后恢复(经调查,问题定位在 Eureka 上某个业务服务实例状态异常);
  • 晚上 11 点 45 开始,继续挂掉 2 台,只剩 4 台,故障转移,同步正常;
  • 晚上 11 点 52 开始,恢复 2 台,Nacos Eureka Sync 集群重新均衡 ReHash ,同步正常;
  • 晚上 11 点 55 开始,全部恢复,Nacos Eureka Sync 集群重新均衡 ReHash ,同步正常;
  • 12 点 14 分,极限灾难演练, 9 台挂掉 8 台,剩 1 台也能抗住,故障转移,同步正常;
  • 凌晨 12 点 22 分,升级 UAT 环境顺利;
  • 凌晨 1 点 22,升级 PROD 环境顺利;
  • 容灾恢复中的 ReHash 时间小于 1 分钟,即 Nacos Eureka Sync 服务大面积故障发生时,恢复时间小于 1 分钟。


作者介绍

  • 吴毅挺,掌门技术副总裁,负责技术中台和少儿技术团队。曾就职于百度、eBay 、携程,曾任携程高级研发总监,负责从零打造携程私有云、容器云、桌面云和 PaaS 平台。
  • 任浩军,掌门基础架构部负责人。曾就职于平安银行、万达、惠普,曾负责平安银行平台架构部 PaaS 平台 Halo 基础服务框架研发。10 多年开源经历,Github ID:@HaojunRen,Nepxion 开源社区创始人,Nacos Group Member,Spring Cloud Alibaba & Nacos & Sentinel & OpenTracing Committer。


参与 Nacos 落地的基础架构部成员,包括:
  • 童子龙,张彬彬,廖梦鸽,张金星,胡振建,谢璐,谢庆芳,伊安娜


阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”
收起阅读 »

KubeCon 2020 阿里云推出四大企业级容器新品 ,详解云原生操作系统进化



导读:云原生操作系统进化,详解阿里云 ACK Pro、ASM、ACR EE、ACK@Edge 等四款企业级容器新品。
KubeCon 2020 中国站,阿里云容器服务负责人易立会在《云原生,数字经济技术创新基石》的演讲中,分享阿里云原生如何助力数字技术抗‘疫’,阐述阿里云对云原生操作系统的思考,同时详解阿里云 ACK Pro、ASM、ACR EE、ACK@Edge 四款企业级容器新品。

容器服务 ACK Pro,为企业级大规模生产环境提供增强的可靠性安全性,以及与可赔付标准 SLA,现已开启公测。同时还有三款产品商业化:服务网格 ASM,统一精准管控容器化微服务应用流量;容器镜像服务企业版 ACR EE,公共云首个独享实例形态的容器镜像仓库产品,是支撑阿里巴巴经济体的双十一同款利器,具备如下能力:多维度安全保障、全球镜像分发加速、DevSecOps 交付提效特点,保障企业客户云原生制品的安全托管及高效分发;边缘容器 ACK@Edge 采用非侵入方式增强,提供边缘自治、边缘单元、边缘流量管理、原生运维 API 支持等能力,以原生方式支持边缘计算场景下的应用统一生命周期管理和统一资源调度。

1.png


疫情期间,争分夺秒的云原生

云计算是数字时代新基建,而 2020 疫情也为数字化生活按下了快进键。“上班用钉钉,上学云课堂,出门健康码,订菜送到家”成为了日常生活一部分,这背后是一系列云计算、云原生技术支撑的业务创新。

2 小时内支撑了钉钉业务 1 万台云主机的扩容需求,基于阿里云服务器和容器化的应用部署方案,钉钉应用发布扩容效率大大提升,顺利扛住有史以来最大的流量洪峰,为全国用户提供线上工作的流畅体验。

停课不停学,希沃课堂整体业务性能提升 30%、运维成本降低 50%,洋葱学院系统资源利用率提升 60%。

健康码基于云原生大数据平台具备弹性、韧性和安全的特点,平稳支撑每日亿次调用。

盒马通过阿里云边缘容器服务 ACK@Edge,快速构建人、货、场数字化全链路融合,云、边、端一体化协同的天眼 AI 系统。结合了云原生技术体系良好的资源调度和应用管理能力,与边缘计算就近访问,实时处理的优势,轻松实现全方位的『降本提效』,门店计算资源成本节省 50%,新店开服效率提升 70%。

云原生操作系统的诞生与进化

容器技术的发展揭开了云原生计算的序幕,在易立看来, Kubernetes 为基础的云原生计算也已经成为新的操作系统,云原生操作系统的雏形被越来越多的行业和企业采纳并因此受益:容器应用化、容器编排系统和 Istio 服务网格等技术依次解耦了应用与运行环境、资源编排调度与底层基础设施、服务实现与服务治理等传统架构的依赖关系。

2.png


阿里云为用户提供了怎样的云原生操作系统?这个云原生操作系统又有哪些突出特点呢?

首先基础设施层是强大的 IaaS 资源,基于第三代神龙架构的计算资源可以更弹性的扩展,以更加优化的成本提供更高的性能;云原生的分布式文件系统,为容器持久化数据而生;云原生网络加速应用交付能力,提供应用型负载均衡与容器网络基础设施。

3.png


其次在容器编排层,阿里云容器服务自 2015 年上线来,伴随数千家企业客户,共同实践过各行各业大量生产级场景。越来越多的客户以云原生的方式架构其大部分甚至全量应用,随着业务深入发展,为了满足大中型企业对可靠性、安全性的强烈需求,阿里云推出新品可供赔付 SLA 的容器服务企业版 ACK Pro。

容器服务企业版 ACK Pro 横空出世:全面安全、高性能,支持新一代神龙架构,SLA 可赔付

容器服务企业版 ACK Pro,是在原容器服务 ACK 托管版集群的基础上发展而来,其继承了原托管版集群的所有优势,例如 Master 节点托管和高可用等。同时,相比原托管版进一步提升了集群的可靠性、安全性和调度性能,并且支持赔付标准的 SLA,高达 99.95%,单集群可支持 5000 节点。ACK Pro 非常适合生产环境下有着大规模业务、对稳定性和安全性有高要求的企业客户。

ACK Pro 支持神龙架构,凭借软硬一体的优化设计,可为企业应用提供卓越的性能;支持无损 Terway 容器网络,相比路由网络延迟下降 30%;为企业提供全面安全防护,支持阿里云安全沙箱容器,满足企业客户对应用的安全、隔离需求,性能相比
继续阅读 »


导读:云原生操作系统进化,详解阿里云 ACK Pro、ASM、ACR EE、ACK@Edge 等四款企业级容器新品。
KubeCon 2020 中国站,阿里云容器服务负责人易立会在《云原生,数字经济技术创新基石》的演讲中,分享阿里云原生如何助力数字技术抗‘疫’,阐述阿里云对云原生操作系统的思考,同时详解阿里云 ACK Pro、ASM、ACR EE、ACK@Edge 四款企业级容器新品。

容器服务 ACK Pro,为企业级大规模生产环境提供增强的可靠性安全性,以及与可赔付标准 SLA,现已开启公测。同时还有三款产品商业化:服务网格 ASM,统一精准管控容器化微服务应用流量;容器镜像服务企业版 ACR EE,公共云首个独享实例形态的容器镜像仓库产品,是支撑阿里巴巴经济体的双十一同款利器,具备如下能力:多维度安全保障、全球镜像分发加速、DevSecOps 交付提效特点,保障企业客户云原生制品的安全托管及高效分发;边缘容器 ACK@Edge 采用非侵入方式增强,提供边缘自治、边缘单元、边缘流量管理、原生运维 API 支持等能力,以原生方式支持边缘计算场景下的应用统一生命周期管理和统一资源调度。

1.png


疫情期间,争分夺秒的云原生

云计算是数字时代新基建,而 2020 疫情也为数字化生活按下了快进键。“上班用钉钉,上学云课堂,出门健康码,订菜送到家”成为了日常生活一部分,这背后是一系列云计算、云原生技术支撑的业务创新。

2 小时内支撑了钉钉业务 1 万台云主机的扩容需求,基于阿里云服务器和容器化的应用部署方案,钉钉应用发布扩容效率大大提升,顺利扛住有史以来最大的流量洪峰,为全国用户提供线上工作的流畅体验。

停课不停学,希沃课堂整体业务性能提升 30%、运维成本降低 50%,洋葱学院系统资源利用率提升 60%。

健康码基于云原生大数据平台具备弹性、韧性和安全的特点,平稳支撑每日亿次调用。

盒马通过阿里云边缘容器服务 ACK@Edge,快速构建人、货、场数字化全链路融合,云、边、端一体化协同的天眼 AI 系统。结合了云原生技术体系良好的资源调度和应用管理能力,与边缘计算就近访问,实时处理的优势,轻松实现全方位的『降本提效』,门店计算资源成本节省 50%,新店开服效率提升 70%。

云原生操作系统的诞生与进化

容器技术的发展揭开了云原生计算的序幕,在易立看来, Kubernetes 为基础的云原生计算也已经成为新的操作系统,云原生操作系统的雏形被越来越多的行业和企业采纳并因此受益:容器应用化、容器编排系统和 Istio 服务网格等技术依次解耦了应用与运行环境、资源编排调度与底层基础设施、服务实现与服务治理等传统架构的依赖关系。

2.png


阿里云为用户提供了怎样的云原生操作系统?这个云原生操作系统又有哪些突出特点呢?

首先基础设施层是强大的 IaaS 资源,基于第三代神龙架构的计算资源可以更弹性的扩展,以更加优化的成本提供更高的性能;云原生的分布式文件系统,为容器持久化数据而生;云原生网络加速应用交付能力,提供应用型负载均衡与容器网络基础设施。

3.png


其次在容器编排层,阿里云容器服务自 2015 年上线来,伴随数千家企业客户,共同实践过各行各业大量生产级场景。越来越多的客户以云原生的方式架构其大部分甚至全量应用,随着业务深入发展,为了满足大中型企业对可靠性、安全性的强烈需求,阿里云推出新品可供赔付 SLA 的容器服务企业版 ACK Pro。

容器服务企业版 ACK Pro 横空出世:全面安全、高性能,支持新一代神龙架构,SLA 可赔付

容器服务企业版 ACK Pro,是在原容器服务 ACK 托管版集群的基础上发展而来,其继承了原托管版集群的所有优势,例如 Master 节点托管和高可用等。同时,相比原托管版进一步提升了集群的可靠性、安全性和调度性能,并且支持赔付标准的 SLA,高达 99.95%,单集群可支持 5000 节点。ACK Pro 非常适合生产环境下有着大规模业务、对稳定性和安全性有高要求的企业客户。

ACK Pro 支持神龙架构,凭借软硬一体的优化设计,可为企业应用提供卓越的性能;支持无损 Terway 容器网络,相比路由网络延迟下降 30%;为企业提供全面安全防护,支持阿里云安全沙箱容器,满足企业客户对应用的安全、隔离需求,性能相比 收起阅读 »

你问我答:微服务治理应该如何去做?


【你问我答】是 BoCloud 博云最新上线的互动类栏目,每周我们将收集和整理有关容器、微服务、DevOps、多云管理等方面的 企业 IT 建设问题,由博云产品团队进行详细解答。如果你有任何感兴趣的相关问题,欢迎留言提问。

以下是本周 “ 微服务 ” 相关问题精选:

网友1:微服务治理应该如何去做?

微服务化应该是从企业的单个系统考虑,还是从整体IT架构去考虑?微服务治理应该如何去做?

博云产品团队:微服务的治理分很多方面,简单的来谈至少三个层面:

  1. 微服务底层管理,微服务之所以需要治理,是因为其逻辑复杂,运维困难,所以需要提供注册中心,配置中心,网关,监控等多种组件做为帮助,所以这个层面是对这些组件的治理。

  2. 微服务外层治理,主要关注于用户的使用,这就涉及到 DevOps ,需要对服务的全生命周期做治理,从想法到实现,再到更新升级。当然这里很重要的一块就是用户权限等问题,部门角色也不可忽略的。


3.从微服务的业务层治理,算是微服务的上层治理,这一层主要关注于服务的业务实现,跟踪业务的调用链,发现调用过程中的逻辑问题,效率问题,冗余问题等等。

网友2:微服务框架,容器云,ServiceMesh、传统API Gateway产品都提供注册发现,它们各适合什么场景?如何选型?

服务化架构中,服务注册和发现是重要的组件,微服务框架中有注册发现,比如Eureka, consul等,容器云也提供服务注册和发现,ServiceMesh、传统API Gateway产品也有注册发现,它们各适合什么场景?如何选型?

博云产品团队:服务注册是指服务提供者将自身信息上报至平台,服务发现是服务消费者到平台查找自己需要的服务。

  1. 微服务框架中,服务是由自身启动,并将信息注册到注册中心,如果不加服务注册信息,那么平台将不知道也不能控制该服务。而且微服务框架下,平台是被动的,不能实现服务资源的主动调度。

  2. 容器云,现在一般都是使用 kubernetes 做为容器的调度,服务的启动都是以 pod 的形式,以 service 向外提供服务。从平台的角度来说无需服务注册与发现。kubernetes 具有强大的服务资源调度能力,所以服务的启停平台占据主动权。与微服务框架相比,服务原生的负载均衡、访问控制将被废除,而由 kubernetes 提供,但功能较弱。

  3. ServiceMesh 可以说是微服务框架的一个升级版,让服务只专注于服务自身的功能,将其内部的服务注册、负载均衡、网络等功能,全部拆出来,以依赖服务的形式存在。其实这里的服务注册与发现,与微服务框架的理念没有太大差别。


4.传统 API Gateway,在微服务框架中也是经常使用的组件,主要是用来控制服务访问的,不管是内部服务间,还是向外部提供业务,主要是用来做安全控制的,当然其他功能还有很多。

网友3:我们处在微服务+容器的转型探索时期,微服务框架:Dubbo、Spring Cloud、Service Mesh等发展趋势探讨?

博云产品团队:纯粹微服务开发,不考虑服务线上运维的要求,spring cloud 是首选,组件多,生态好。

基于通信延迟要求较小的情况下,采用 rpc 协议比 http 协议通信要好一些,dubbo 占优势 service mesh 是解决服务通信的基础设施,本身与微服务无关。

如果考虑容器化的方式部署,spring boot+kubernetes+spring cloud部分组件会更好一些,可以有效的减少组件依赖以及链路调用关系。

网友4:微服务拆分的原则?

按分享的经验来看,是需要将无关的功能都进行拆分,我理解就是原子化拆分。但现实业务场景中对于传统的应用系统,已经存在了大量的业务逻辑处理。这种迁移是一个比较长期且痛苦的事情,如何解决?

博云产品团队:服务拆分大的前提可以参考 DDD 领域驱动设计。进一步讲,业务需要考虑三方面问题:1.服务边界切分;2.服务依赖梳理;3.服务交互规范标准。

服务边界切分需要依赖“低耦合,高内聚”的原则,明确业务单元的边界,尽可能减少同一个业务的不同服务单元的调用依赖。

服务依赖,需要明确一个业务构成过程中的服务依赖关系,避免出现回环依赖,双向依赖的场景。最好的方式是实现链式依赖调用。

服务交互规范,从协议以及数据传输规范层面说明服务与服务之间的交互方式,包括采用的通信协议,数据传递格式等;

服务迁移的过程中,首先要考虑接口变化情况,对于前后端分离的架构,可以采用restful 的方式进行,尽可能避免接口的频繁变更。同时复用原有的业务代码实现。线上迁移过程中,可以利用负载路由的控制实现逐步发布。

网友5:微服务架构下底层数据存储的实现方式?

从分享的材料来看,使用了分布式的多个数据库存储,从而达到高并发支持。在这种架构下,数据一致性的要求就很高,能否详细说明一下底层数据的同步方式?

博云产品团队:无论是否采用微服务架构,针对高并发的支持的情况,数据存储可以分为两个阶段:第一持久化存储;第二缓存。

针对持久化存储,首先微服务架构的各个服务是分库存储,针对不同的数据类型,可以采用不同的数据持久化引擎。例如关系型数据可以采用 mysql 做数据持久化引擎,时序数据可以采用influxdb,以及其他擅长存储不同数据类型的持久化引擎。但是需要注意集群化部署时的数据同步,数据备份以及故障切换等问题。针对缓存的,是对数据库的补充,能够有效的避免平凡操作数据库,导致请求延迟增大的效果。

针对数据同步以来 CAP 原理,首先需要考虑业务需求,需要满足强一致性,还是最终一致性来保证。根据不同的特性,可以选择其他的存储引擎,例如 etcd,zookeeper,consul 等。

网友6:微服务的高可用主要用什么方法保证高可用呢?硬负载均衡设备,还是软负载方式保证?

博云产品团队:高可用有两种不同的方式:主从,双活。与具体采用的服务架构关系相对没有那么紧密。软负载,或者硬负载在项目的实施过程中都会遇到。从适用场景而言,软负载更多适用在内网环境,内部服务与服务的交互接口处;硬负载更多呈现在整个应用的入口处,除了负载以外同时包含部分网关的功能。

下周预告:

关于 “ DevOps ” ,任何你感兴趣或者想了解,欢迎留言,下周我们将为大家解答有关 DevOps 建设的相关问题。
继续阅读 »

【你问我答】是 BoCloud 博云最新上线的互动类栏目,每周我们将收集和整理有关容器、微服务、DevOps、多云管理等方面的 企业 IT 建设问题,由博云产品团队进行详细解答。如果你有任何感兴趣的相关问题,欢迎留言提问。

以下是本周 “ 微服务 ” 相关问题精选:

网友1:微服务治理应该如何去做?

微服务化应该是从企业的单个系统考虑,还是从整体IT架构去考虑?微服务治理应该如何去做?

博云产品团队:微服务的治理分很多方面,简单的来谈至少三个层面:

  1. 微服务底层管理,微服务之所以需要治理,是因为其逻辑复杂,运维困难,所以需要提供注册中心,配置中心,网关,监控等多种组件做为帮助,所以这个层面是对这些组件的治理。

  2. 微服务外层治理,主要关注于用户的使用,这就涉及到 DevOps ,需要对服务的全生命周期做治理,从想法到实现,再到更新升级。当然这里很重要的一块就是用户权限等问题,部门角色也不可忽略的。


3.从微服务的业务层治理,算是微服务的上层治理,这一层主要关注于服务的业务实现,跟踪业务的调用链,发现调用过程中的逻辑问题,效率问题,冗余问题等等。

网友2:微服务框架,容器云,ServiceMesh、传统API Gateway产品都提供注册发现,它们各适合什么场景?如何选型?

服务化架构中,服务注册和发现是重要的组件,微服务框架中有注册发现,比如Eureka, consul等,容器云也提供服务注册和发现,ServiceMesh、传统API Gateway产品也有注册发现,它们各适合什么场景?如何选型?

博云产品团队:服务注册是指服务提供者将自身信息上报至平台,服务发现是服务消费者到平台查找自己需要的服务。

  1. 微服务框架中,服务是由自身启动,并将信息注册到注册中心,如果不加服务注册信息,那么平台将不知道也不能控制该服务。而且微服务框架下,平台是被动的,不能实现服务资源的主动调度。

  2. 容器云,现在一般都是使用 kubernetes 做为容器的调度,服务的启动都是以 pod 的形式,以 service 向外提供服务。从平台的角度来说无需服务注册与发现。kubernetes 具有强大的服务资源调度能力,所以服务的启停平台占据主动权。与微服务框架相比,服务原生的负载均衡、访问控制将被废除,而由 kubernetes 提供,但功能较弱。

  3. ServiceMesh 可以说是微服务框架的一个升级版,让服务只专注于服务自身的功能,将其内部的服务注册、负载均衡、网络等功能,全部拆出来,以依赖服务的形式存在。其实这里的服务注册与发现,与微服务框架的理念没有太大差别。


4.传统 API Gateway,在微服务框架中也是经常使用的组件,主要是用来控制服务访问的,不管是内部服务间,还是向外部提供业务,主要是用来做安全控制的,当然其他功能还有很多。

网友3:我们处在微服务+容器的转型探索时期,微服务框架:Dubbo、Spring Cloud、Service Mesh等发展趋势探讨?

博云产品团队:纯粹微服务开发,不考虑服务线上运维的要求,spring cloud 是首选,组件多,生态好。

基于通信延迟要求较小的情况下,采用 rpc 协议比 http 协议通信要好一些,dubbo 占优势 service mesh 是解决服务通信的基础设施,本身与微服务无关。

如果考虑容器化的方式部署,spring boot+kubernetes+spring cloud部分组件会更好一些,可以有效的减少组件依赖以及链路调用关系。

网友4:微服务拆分的原则?

按分享的经验来看,是需要将无关的功能都进行拆分,我理解就是原子化拆分。但现实业务场景中对于传统的应用系统,已经存在了大量的业务逻辑处理。这种迁移是一个比较长期且痛苦的事情,如何解决?

博云产品团队:服务拆分大的前提可以参考 DDD 领域驱动设计。进一步讲,业务需要考虑三方面问题:1.服务边界切分;2.服务依赖梳理;3.服务交互规范标准。

服务边界切分需要依赖“低耦合,高内聚”的原则,明确业务单元的边界,尽可能减少同一个业务的不同服务单元的调用依赖。

服务依赖,需要明确一个业务构成过程中的服务依赖关系,避免出现回环依赖,双向依赖的场景。最好的方式是实现链式依赖调用。

服务交互规范,从协议以及数据传输规范层面说明服务与服务之间的交互方式,包括采用的通信协议,数据传递格式等;

服务迁移的过程中,首先要考虑接口变化情况,对于前后端分离的架构,可以采用restful 的方式进行,尽可能避免接口的频繁变更。同时复用原有的业务代码实现。线上迁移过程中,可以利用负载路由的控制实现逐步发布。

网友5:微服务架构下底层数据存储的实现方式?

从分享的材料来看,使用了分布式的多个数据库存储,从而达到高并发支持。在这种架构下,数据一致性的要求就很高,能否详细说明一下底层数据的同步方式?

博云产品团队:无论是否采用微服务架构,针对高并发的支持的情况,数据存储可以分为两个阶段:第一持久化存储;第二缓存。

针对持久化存储,首先微服务架构的各个服务是分库存储,针对不同的数据类型,可以采用不同的数据持久化引擎。例如关系型数据可以采用 mysql 做数据持久化引擎,时序数据可以采用influxdb,以及其他擅长存储不同数据类型的持久化引擎。但是需要注意集群化部署时的数据同步,数据备份以及故障切换等问题。针对缓存的,是对数据库的补充,能够有效的避免平凡操作数据库,导致请求延迟增大的效果。

针对数据同步以来 CAP 原理,首先需要考虑业务需求,需要满足强一致性,还是最终一致性来保证。根据不同的特性,可以选择其他的存储引擎,例如 etcd,zookeeper,consul 等。

网友6:微服务的高可用主要用什么方法保证高可用呢?硬负载均衡设备,还是软负载方式保证?

博云产品团队:高可用有两种不同的方式:主从,双活。与具体采用的服务架构关系相对没有那么紧密。软负载,或者硬负载在项目的实施过程中都会遇到。从适用场景而言,软负载更多适用在内网环境,内部服务与服务的交互接口处;硬负载更多呈现在整个应用的入口处,除了负载以外同时包含部分网关的功能。

下周预告:

关于 “ DevOps ” ,任何你感兴趣或者想了解,欢迎留言,下周我们将为大家解答有关 DevOps 建设的相关问题。 收起阅读 »

关于DevOps,数据科学家需要了解这些


【编者的话】本文是使用持续集成(通过GitHub Actions)构建自动模型训练系统的哲学和实践指南。

随着机器学习(ML)在过去几年的快速发展,开始ML实验变得非常容易。多亏了像scikit-learn和Keras这样的库,用几行代码就可以创建模型。

但是,将数据科学项目转化为有意义的应用程序比以往任何时候都更加困难,比如将模型转化为团队决策或成为产品的一部分。典型的ML项目涉及到许多不同的技能集,对于任何一个人来说,如果不是完全不可能的话,那也是一种挑战——如此困难,少有的同时还能开发高质量软件和游戏工程师的数据科学家被称为独角兽!

随着这一领域的成熟,很多工作将需要软件、工程和数学技能的结合,有些人说他们已经这么做了。

引用一位无与伦比的数据科学家/工程师/评论家Vicki Boykis在她的博客data science is different now里的话:


越来越清楚的是,在炒作周期的后期阶段,数据科学正逐渐接近工程,数据科学家需要的技能不再是可视化和基于统计的,而是与传统的计算机科学课程更加一致。

为什么数据科学家需要了解DevOps

那么,在众多的工程和软件技能中,数据科学家应该学习哪一种呢?我的钱花在DevOps上了。

DevOps是development和operations的合成词,于2009年在比利时的一次会议上正式诞生。这次会议的召开是为了应对科技公司在历史上经历过深刻分歧的两个方面之间的紧张关系。软件开发人员需要快速行动并经常进行试验,而运维团队则优先考虑服务的稳定性和可用性(这些人让服务器每天都在运行)。他们的目标不仅是对立,而且是竞争。

这听起来很像今天的数据科学。数据科学家通过实验创造价值:数据建模、组合和转换的新方法。与此同时,雇佣数据科学家的组织受到稳定的激励。

这种划分的后果是深远的:在最新的Anaconda数据科学状态”报告中,“不到一半(48%)的受访者认为他们可以证明数据科学对他们的组织的影响”。据估计,绝大多数由数据科学家创建的模型最终都被束之高阁。我们还没有强大的实践来在创建模型的团队和部署模型的团队之间传递模型。数据科学家和实现他们工作的开发人员和工程师拥有完全不同的工具、约束条件和技能集。

DevOps的出现就是为了解决软件中的这种僵局,就像开发人员vs运维一样。它取得了巨大的成功:许多团队已经从每几个月部署一次新代码发展到一天部署几次。既然我们已经有了机器学习和操作,那么现在就该考虑MLOps了——来自DevOps的用于数据科学的原则。

引入持续集成

DevOps既是一种哲学,也是一套实践,包括:
  1. 自动化你所能做到的一切
  2. 快速获得对新想法的反馈
  3. 减少工作流程中的手工交接


在一个典型的数据科学项目中,我们可以看到一些应用:
  1. 自动化你所能做到的一切。自动化部分重复和可预测的数据处理、模型训练和模型测试。
  2. 快速获得对新想法的反馈。当你的数据、代码或软件环境发生变化时,立即在类似生产的环境(即具有预期在生产中具有的依赖关系和约束的机器)中进行测试。
  3. 减少工作流程中的手工交接。为数据科学家寻找机会,尽可能多地测试他们自己的模型。不要等到有开发人员时才查看模型在类似生产环境中的行为。


实现这些目标的标准DevOps方法是一种称为持续集成(CI)的方法。

要点是,当你更改项目的源代码时(通常通过Git提交注册更改),你的软件将被自动构建和测试。每个动作都会引发反馈。CI通常与Git-flow一起使用,Git-flow是一种开发架构,其中的新特性构建在Git分支上。当一个特性分支通过自动化测试时,它就成为了一个候选分支,可以合并到主分支中。
1_6RdJsAL4xzScb6zmZ6rYFg.png

软件开发中的持续集成

通过这种设置,我们有了自动化——代码更改触发一个自动构建,然后进行测试。我们有快速的反馈,因为我们可以快速得到测试结果,所以开发人员可以不断迭代他们的代码。而且因为所有这些都是自动发生的,你不需要等待其他人得到反馈——少了一个切换!

那么我们为什么不在ML中使用持续集成呢?一些原因是文化上的,比如数据科学和软件工程社区之间的低交叉。其他的则是技术性的——例如,为了理解模型的性能,你需要查看诸如准确性、特异性和敏感性等指标。数据可视化可能会帮助你,比如混淆矩阵或损失图。所以通过/失败的测试不会减少反馈。理解一个模型是否得到了改进需要一些关于手头问题的领域知识,因此测试结果需要以一种有效的和可理解的方式进行报告。
1_MWH4fcSEc8z8197t0A6qQg.png

机器学习项目中持续集成的样子

CI系统是如何工作的?

现在我们要更实际一些,让我们看看典型的CI系统是如何工作的。对于学习者来说,幸运的是,由于GitHub Actions和GitLab CI等工具的出现,障碍从来没有降低过——它们有清晰的图形界面和为首次用户准备的优秀文档。由于GitHub操作对于公共项目是完全免费的,所以我们将在本例中使用它。

它是这样工作的:

1、你创建了一个GitHub存储库。你创建了一个名为.github/workflows的目录,并在其中放置了一个特殊的.yaml文件,其中包含你想要运行的脚本。
$ python train.py

2、你可以以某种方式更改项目存储库中的文件,然后Git提交更改。然后,推到GitHub存储库。
# Create a new git branch for experimenting
$ git checkout -b "experiment"
$ edit train.py
# git add, commit, and push your changes
$ git add . && commit -m "Normalized features"
$ git push origin experiment

3、一旦GitHub检测到push,GitHub就会部署他们的一台计算机来运行.yaml中的函数。

4、如果函数运行成功或失败,GitHub会返回一个通知。
1_A0-chRcV1Pq3QtnPhy5zzA.png

在GitHub存储库的Actions选项卡中找到它

就是这样!真正奇妙的是,你正在使用GitHub的计算机来运行你的代码。你所要做的就是更新代码并将更改推送到存储库中,工作流就会自动发生。

回到我在第1步中提到的特殊的.yaml文件——让我们快速查看一个。它可以有任何你喜欢的名称,只要文件扩展名是.yaml,并且它存储在.github/workflows目录中。这里有一个:
# .github/workflows/ci.yaml
name: train-my-model
on: [push]
jobs:
run:
  runs-on: [ubuntu-latest]
steps:
  - uses: actions/checkout@v2
  - name: training
  run: |
     pip install -r requirements.txt
     python train.py

有很多操作在进行,但大多数操作都是相同的——你可以复制粘贴这个标准的GitHub动作模板,但在“运行”字段中填写你的工作流。

如果这个文件在你的项目repo中,每当GitHub检测到对你的代码的更改(通过push注册),GitHub Actions就会部署一个Ubuntu运行程序,并尝试执行你的命令来安装需求并运行Python脚本。请注意,你必须在项目repo中包含你的工作流所需的文件——这里是requirementes .txt和train.py。

得到更好的反馈

正如我们之前提到的,自动训练是非常酷的,但重要的是要有一个容易理解的形式的结果。目前,GitHub操作允许你访问运行的纯文本日志。
1_422ZyRLdIlhaVT9Tncy7Nw.png

从GitHub动作日志中打印出来的示例

但是理解你的模型的性能是很棘手的。模型和数据是高维的,并且通常是非线性的——如果没有图片,这两件事是特别难以理解的。

我可以向你展示一种将数据viz放入CI循环的方法。在过去的几个月里,我的团队在Iterative.ai(我们做数据版本控制)正在开发一个工具包,帮助在机器学习项目中使用GitHub动作和GitLab CI。它被称为持续机器学习(简称CML),并且是开源免费的。

从“让我们使用GitHub动作来训练ML模型”的基本思想出发,我们构建了一些函数来提供比通过/失败通知更详细的报告。CML帮助你在报告中放入图像和表格,就像这个由SciKit-learn生成的混淆矩阵:
1_Bemfr5-pIjzf6vrFyIyvoQ.png

当你在GitHub中请求Pull时,这个报告就会出现

为了制作这个报告,我们的GitHub操作执行了一个Python模型训练脚本,然后使用CML函数将我们的模型准确性和混淆矩阵写入一个markdown文档。然后CML将减价文档传递给GitHub。

我们修改后的.yaml文件包含以下工作流(新添加的行被加粗以示强调):
name: train-my-model 
on: [push] 
jobs:  
run:    
  runs-on: [ubuntu-latest]    
  container: docker://dvcorg/cml-py3:latest     
  steps:      
  - uses: actions/checkout@v2       
  - name: training        
    env:          
       repo_token: ${{ secrets.GITHUB_TOKEN }}   
    run: |      

       # train.py outputs metrics.txt and confusion_matrix.png  
       pip3 install -r requirements.txt          
       python train.py                    

       # copy the contents of metrics.txt to our markdown report
       cat metrics.txt >> report.md          
       # add our confusion matrix to report.md
       cml-publish confusion_matrix.png --md >> report.md 
       # send the report to GitHub for display  
       cml-send-comment report.md

你可以在这里看到整个项目存储库。注意,我们的.yaml现在包含更多的配置细节,比如一个特殊的Docker容器和一个环境变量,以及一些要运行的新代码。容器和环境变量细节在每个CML项目中都是标准的,而不是用户需要操作的东西,所以请关注代码。

在工作流中添加了这些CML功能后,我们在CI系统中创建了一个更完整的反馈循环:
  1. 创建一个Git分支并更改该分支上的代码。
  2. 自动训练模型并产生度量(准确性)和可视化(混淆矩阵)。
  3. 将这些结果嵌入到Pull请求的可视报告中。


现在,当你和你的团队成员决定你的变更是否对你的建模目标有积极的影响时,你就有了一个可以检查的仪表板。另外,Git还将此报告链接到你的确切项目版本(数据和代码)、用于训练的跑步器以及那次运行的日志。很彻底,不再有那些很久以前就失去了与代码的任何连接的图形在你的工作空间中浮动。

这就是数据科学项目中CI的基本思想。明确地说,这个示例是使用CI的最简单方法之一。在现实生活中,你可能会遇到相当复杂的场景。CML还有一些功能可以帮助你使用存储在GitHub存储库之外的大型数据集(使用DVC),并在云实例上进行训练,而不是使用默认的GitHub动作运行器。这意味着你可以使用GPU和其他专门的设置。

例如,我做了一个使用GitHub Actions部署EC2 GPU的项目,然后训练一个神经类型的传输模型。以下是我的CML报告:
1_X9z6lYCzF2GoS5L3Uh9LYA.png

你还可以使用自己的Docker容器,这样就可以在生产中紧密地模拟模型的环境。以后我将更多地介绍这些高级用例。

关于ML的CI的最后思考

总结一下我们到目前为止所说的:

DevOps不是一种特定的技术,而是一种哲学、一套原则和实践,用于从根本上重构创建软件的过程。它之所以有效,是因为它解决了团队如何工作和试验新代码的系统瓶颈。

随着数据科学在未来几年的成熟,懂得如何将DevOps原则应用到他们的机器学习项目中的人将成为一种有价值的商品——无论是从薪水还是从组织影响的角度。持续集成是DevOps的主要内容,也是构建具有可靠自动化、快速测试和团队自治的文化的最有效的已知方法之一。

CI可以通过GitHub Actions或GitLab CI等系统实现,你可以使用这些服务来构建自动模型培训系统。好处很多:
  1. 你的代码、数据、模型和培训基础设施(硬件和软件环境)都是Git版本化的。
  2. 你正在自动化工作,频繁地进行测试并获得快速的反馈(如果使用CML,则使用可视化的报告)。从长远来看,这几乎肯定会加速项目的开发。
  3. CI系统使你的工作对团队中的每个人都可见。没有人需要非常费力地搜索你的最佳运行的代码、数据和模型。


我保证,一旦你进入最佳状态,通过一个Git提交自动启动你的模型训练、记录和报告是非常有趣的。

你会觉得很酷。

进一步的阅读

  • 持续集成,Martin Fowler关于这个主题的开创性博客
  • 机器学习的持续交付,Martin Fowler网站上另一个关于为ML构建持续集成和持续交付系统的优秀博客
  • DevOps手册,深受喜爱的指南,推荐给几乎所有组织(ML、软件或非组织)


原文链接:What data scientists need to know about DevOps(翻译:刘志超)
继续阅读 »

【编者的话】本文是使用持续集成(通过GitHub Actions)构建自动模型训练系统的哲学和实践指南。

随着机器学习(ML)在过去几年的快速发展,开始ML实验变得非常容易。多亏了像scikit-learn和Keras这样的库,用几行代码就可以创建模型。

但是,将数据科学项目转化为有意义的应用程序比以往任何时候都更加困难,比如将模型转化为团队决策或成为产品的一部分。典型的ML项目涉及到许多不同的技能集,对于任何一个人来说,如果不是完全不可能的话,那也是一种挑战——如此困难,少有的同时还能开发高质量软件和游戏工程师的数据科学家被称为独角兽!

随着这一领域的成熟,很多工作将需要软件、工程和数学技能的结合,有些人说他们已经这么做了。

引用一位无与伦比的数据科学家/工程师/评论家Vicki Boykis在她的博客data science is different now里的话:


越来越清楚的是,在炒作周期的后期阶段,数据科学正逐渐接近工程,数据科学家需要的技能不再是可视化和基于统计的,而是与传统的计算机科学课程更加一致。

为什么数据科学家需要了解DevOps

那么,在众多的工程和软件技能中,数据科学家应该学习哪一种呢?我的钱花在DevOps上了。

DevOps是development和operations的合成词,于2009年在比利时的一次会议上正式诞生。这次会议的召开是为了应对科技公司在历史上经历过深刻分歧的两个方面之间的紧张关系。软件开发人员需要快速行动并经常进行试验,而运维团队则优先考虑服务的稳定性和可用性(这些人让服务器每天都在运行)。他们的目标不仅是对立,而且是竞争。

这听起来很像今天的数据科学。数据科学家通过实验创造价值:数据建模、组合和转换的新方法。与此同时,雇佣数据科学家的组织受到稳定的激励。

这种划分的后果是深远的:在最新的Anaconda数据科学状态”报告中,“不到一半(48%)的受访者认为他们可以证明数据科学对他们的组织的影响”。据估计,绝大多数由数据科学家创建的模型最终都被束之高阁。我们还没有强大的实践来在创建模型的团队和部署模型的团队之间传递模型。数据科学家和实现他们工作的开发人员和工程师拥有完全不同的工具、约束条件和技能集。

DevOps的出现就是为了解决软件中的这种僵局,就像开发人员vs运维一样。它取得了巨大的成功:许多团队已经从每几个月部署一次新代码发展到一天部署几次。既然我们已经有了机器学习和操作,那么现在就该考虑MLOps了——来自DevOps的用于数据科学的原则。

引入持续集成

DevOps既是一种哲学,也是一套实践,包括:
  1. 自动化你所能做到的一切
  2. 快速获得对新想法的反馈
  3. 减少工作流程中的手工交接


在一个典型的数据科学项目中,我们可以看到一些应用:
  1. 自动化你所能做到的一切。自动化部分重复和可预测的数据处理、模型训练和模型测试。
  2. 快速获得对新想法的反馈。当你的数据、代码或软件环境发生变化时,立即在类似生产的环境(即具有预期在生产中具有的依赖关系和约束的机器)中进行测试。
  3. 减少工作流程中的手工交接。为数据科学家寻找机会,尽可能多地测试他们自己的模型。不要等到有开发人员时才查看模型在类似生产环境中的行为。


实现这些目标的标准DevOps方法是一种称为持续集成(CI)的方法。

要点是,当你更改项目的源代码时(通常通过Git提交注册更改),你的软件将被自动构建和测试。每个动作都会引发反馈。CI通常与Git-flow一起使用,Git-flow是一种开发架构,其中的新特性构建在Git分支上。当一个特性分支通过自动化测试时,它就成为了一个候选分支,可以合并到主分支中。
1_6RdJsAL4xzScb6zmZ6rYFg.png

软件开发中的持续集成

通过这种设置,我们有了自动化——代码更改触发一个自动构建,然后进行测试。我们有快速的反馈,因为我们可以快速得到测试结果,所以开发人员可以不断迭代他们的代码。而且因为所有这些都是自动发生的,你不需要等待其他人得到反馈——少了一个切换!

那么我们为什么不在ML中使用持续集成呢?一些原因是文化上的,比如数据科学和软件工程社区之间的低交叉。其他的则是技术性的——例如,为了理解模型的性能,你需要查看诸如准确性、特异性和敏感性等指标。数据可视化可能会帮助你,比如混淆矩阵或损失图。所以通过/失败的测试不会减少反馈。理解一个模型是否得到了改进需要一些关于手头问题的领域知识,因此测试结果需要以一种有效的和可理解的方式进行报告。
1_MWH4fcSEc8z8197t0A6qQg.png

机器学习项目中持续集成的样子

CI系统是如何工作的?

现在我们要更实际一些,让我们看看典型的CI系统是如何工作的。对于学习者来说,幸运的是,由于GitHub Actions和GitLab CI等工具的出现,障碍从来没有降低过——它们有清晰的图形界面和为首次用户准备的优秀文档。由于GitHub操作对于公共项目是完全免费的,所以我们将在本例中使用它。

它是这样工作的:

1、你创建了一个GitHub存储库。你创建了一个名为.github/workflows的目录,并在其中放置了一个特殊的.yaml文件,其中包含你想要运行的脚本。
$ python train.py

2、你可以以某种方式更改项目存储库中的文件,然后Git提交更改。然后,推到GitHub存储库。
# Create a new git branch for experimenting
$ git checkout -b "experiment"
$ edit train.py
# git add, commit, and push your changes
$ git add . && commit -m "Normalized features"
$ git push origin experiment

3、一旦GitHub检测到push,GitHub就会部署他们的一台计算机来运行.yaml中的函数。

4、如果函数运行成功或失败,GitHub会返回一个通知。
1_A0-chRcV1Pq3QtnPhy5zzA.png

在GitHub存储库的Actions选项卡中找到它

就是这样!真正奇妙的是,你正在使用GitHub的计算机来运行你的代码。你所要做的就是更新代码并将更改推送到存储库中,工作流就会自动发生。

回到我在第1步中提到的特殊的.yaml文件——让我们快速查看一个。它可以有任何你喜欢的名称,只要文件扩展名是.yaml,并且它存储在.github/workflows目录中。这里有一个:
# .github/workflows/ci.yaml
name: train-my-model
on: [push]
jobs:
run:
  runs-on: [ubuntu-latest]
steps:
  - uses: actions/checkout@v2
  - name: training
  run: |
     pip install -r requirements.txt
     python train.py

有很多操作在进行,但大多数操作都是相同的——你可以复制粘贴这个标准的GitHub动作模板,但在“运行”字段中填写你的工作流。

如果这个文件在你的项目repo中,每当GitHub检测到对你的代码的更改(通过push注册),GitHub Actions就会部署一个Ubuntu运行程序,并尝试执行你的命令来安装需求并运行Python脚本。请注意,你必须在项目repo中包含你的工作流所需的文件——这里是requirementes .txt和train.py。

得到更好的反馈

正如我们之前提到的,自动训练是非常酷的,但重要的是要有一个容易理解的形式的结果。目前,GitHub操作允许你访问运行的纯文本日志。
1_422ZyRLdIlhaVT9Tncy7Nw.png

从GitHub动作日志中打印出来的示例

但是理解你的模型的性能是很棘手的。模型和数据是高维的,并且通常是非线性的——如果没有图片,这两件事是特别难以理解的。

我可以向你展示一种将数据viz放入CI循环的方法。在过去的几个月里,我的团队在Iterative.ai(我们做数据版本控制)正在开发一个工具包,帮助在机器学习项目中使用GitHub动作和GitLab CI。它被称为持续机器学习(简称CML),并且是开源免费的。

从“让我们使用GitHub动作来训练ML模型”的基本思想出发,我们构建了一些函数来提供比通过/失败通知更详细的报告。CML帮助你在报告中放入图像和表格,就像这个由SciKit-learn生成的混淆矩阵:
1_Bemfr5-pIjzf6vrFyIyvoQ.png

当你在GitHub中请求Pull时,这个报告就会出现

为了制作这个报告,我们的GitHub操作执行了一个Python模型训练脚本,然后使用CML函数将我们的模型准确性和混淆矩阵写入一个markdown文档。然后CML将减价文档传递给GitHub。

我们修改后的.yaml文件包含以下工作流(新添加的行被加粗以示强调):
name: train-my-model 
on: [push] 
jobs:  
run:    
  runs-on: [ubuntu-latest]    
  container: docker://dvcorg/cml-py3:latest     
  steps:      
  - uses: actions/checkout@v2       
  - name: training        
    env:          
       repo_token: ${{ secrets.GITHUB_TOKEN }}   
    run: |      

       # train.py outputs metrics.txt and confusion_matrix.png  
       pip3 install -r requirements.txt          
       python train.py                    

       # copy the contents of metrics.txt to our markdown report
       cat metrics.txt >> report.md          
       # add our confusion matrix to report.md
       cml-publish confusion_matrix.png --md >> report.md 
       # send the report to GitHub for display  
       cml-send-comment report.md

你可以在这里看到整个项目存储库。注意,我们的.yaml现在包含更多的配置细节,比如一个特殊的Docker容器和一个环境变量,以及一些要运行的新代码。容器和环境变量细节在每个CML项目中都是标准的,而不是用户需要操作的东西,所以请关注代码。

在工作流中添加了这些CML功能后,我们在CI系统中创建了一个更完整的反馈循环:
  1. 创建一个Git分支并更改该分支上的代码。
  2. 自动训练模型并产生度量(准确性)和可视化(混淆矩阵)。
  3. 将这些结果嵌入到Pull请求的可视报告中。


现在,当你和你的团队成员决定你的变更是否对你的建模目标有积极的影响时,你就有了一个可以检查的仪表板。另外,Git还将此报告链接到你的确切项目版本(数据和代码)、用于训练的跑步器以及那次运行的日志。很彻底,不再有那些很久以前就失去了与代码的任何连接的图形在你的工作空间中浮动。

这就是数据科学项目中CI的基本思想。明确地说,这个示例是使用CI的最简单方法之一。在现实生活中,你可能会遇到相当复杂的场景。CML还有一些功能可以帮助你使用存储在GitHub存储库之外的大型数据集(使用DVC),并在云实例上进行训练,而不是使用默认的GitHub动作运行器。这意味着你可以使用GPU和其他专门的设置。

例如,我做了一个使用GitHub Actions部署EC2 GPU的项目,然后训练一个神经类型的传输模型。以下是我的CML报告:
1_X9z6lYCzF2GoS5L3Uh9LYA.png

你还可以使用自己的Docker容器,这样就可以在生产中紧密地模拟模型的环境。以后我将更多地介绍这些高级用例。

关于ML的CI的最后思考

总结一下我们到目前为止所说的:

DevOps不是一种特定的技术,而是一种哲学、一套原则和实践,用于从根本上重构创建软件的过程。它之所以有效,是因为它解决了团队如何工作和试验新代码的系统瓶颈。

随着数据科学在未来几年的成熟,懂得如何将DevOps原则应用到他们的机器学习项目中的人将成为一种有价值的商品——无论是从薪水还是从组织影响的角度。持续集成是DevOps的主要内容,也是构建具有可靠自动化、快速测试和团队自治的文化的最有效的已知方法之一。

CI可以通过GitHub Actions或GitLab CI等系统实现,你可以使用这些服务来构建自动模型培训系统。好处很多:
  1. 你的代码、数据、模型和培训基础设施(硬件和软件环境)都是Git版本化的。
  2. 你正在自动化工作,频繁地进行测试并获得快速的反馈(如果使用CML,则使用可视化的报告)。从长远来看,这几乎肯定会加速项目的开发。
  3. CI系统使你的工作对团队中的每个人都可见。没有人需要非常费力地搜索你的最佳运行的代码、数据和模型。


我保证,一旦你进入最佳状态,通过一个Git提交自动启动你的模型训练、记录和报告是非常有趣的。

你会觉得很酷。

进一步的阅读

  • 持续集成,Martin Fowler关于这个主题的开创性博客
  • 机器学习的持续交付,Martin Fowler网站上另一个关于为ML构建持续集成和持续交付系统的优秀博客
  • DevOps手册,深受喜爱的指南,推荐给几乎所有组织(ML、软件或非组织)


原文链接:What data scientists need to know about DevOps(翻译:刘志超) 收起阅读 »

SpringCloud 应用在 Kubernetes 上的最佳实践 — 线上发布(可灰度)


作者 | 白寂  阿里云开发工程师

导读:前三篇文章我们介绍了应用的开发和部署,那么在应用成功上云后,我就要面对应用的管理话题了,这一篇我们来看看如何做线上发布,并且是可灰度的。

相关文章推荐:


前言

在新版本上线时,无论是从产品稳定性还是用户对新版本的接受程度上考虑,直接将老应用升级到新版本应用都有很大风险的。我们一般的做法是,保证新老版本同时在线,并且先将少部分流量切换到新版本应用上,同时在此期间对新版本的应用请求进行观察。在确认新版本没有问题后,再逐步将更大比例的流量切换到新版本上。这个过程的核心是可以对流量的流入转发规则进行配置,EDAS 的金丝雀发布能力,提供了多个版本同时在线的能力,并且提供了灵活的配置规则来给不同的版本进行流量分配。

部署在 EDAS Kubernetes 集群中的 Spring Cloud 微服务应用,在新版本发布的时候可以使用金丝雀发布进行小规模验证,验证通过后再全量升级。

金丝雀发布配置

首先,进入 EDAS 的应用部署页面,对我们要进行部署升级的应用进行发布,在这里我们选择金丝雀(灰度)发布。需要注意的是,对灰度发布的流量控制,当前只对非入口应用的 Dubbo 和 Spring Cloud 应用生效。所谓入口应用,即承接外部流量的第一个应用节点。并且若您的应用使用了 HPA、Rancher、Istio、或者依赖Deployment.Metadata.Name 或 Deployment.Metadata.Uid 的功能与配置等 K8s 原生功能或配置时,请勿使用灰度发布或分批发布。否则,应用部署之后,这些 K8s 原生功能或配置将出现异常。

1.png


在发布页面,可以选择通过上传 JAR 包或者填入 JAR 包地址的方式选择要进行发布的新版本应用部署包。

2.png


在选择好要进行发布的新版本应用部署包后,接下来进行发布策略的配置。这里分为两个部分:
  • 第一部分可以对发布批次进行设置,例如设置发布灰度批次,首批进行灰度的 pod 实例个数,分批间处理方式等;
  • 第二部分可以对流量灰度规则进行配置,我们可以选择按流量内容进行灰度或者简单地按照流量比例进行灰度,下面将详细介绍这两种发布策略配置。


设置发布策略

在批次发布这里我们可以进行的配置有:
  • 首批灰度数量:在点击发布后,会首先将首批灰度数量个数的实例进行新版本的发布,为了保证应用的稳定性,首批灰度的实例数不能超过应用实例总数的 50%。比如当前实例数是 7 台,那么最多只能选择 3 台作为首批灰度的实例;
  • 剩余批次:首批灰度发布完成后,剩余的应用实例将按照此处指定的批次发布完成;
  • 分批间处理方式:剩余批次间的处理方式可选择手动或者自动,若选择自动,则剩余的几个批次将在前一批发布完成后进行自动发布,自动发布的批次间隔也可进行配置,例如配置每批次在发布完成后,30 分钟后自动进行下一批次的发布;
  • 批次内部署间隔:每一批次内,如果此批次内要发布的应用实例数大于 1,则要进行此配置指定批次内实例部署间隔。


在下面的例子中,我们现在有 7 个 pod 应用实例,选择首批对 2 个实例进行灰度升级。在首批 2 个实例的灰度发布完成后,将剩下的 5 个实例分 3 个批次进行发布。这3个批次的批次间处理方式选择自动发布,在当前批次发布完成 30 分钟后自动进行下一批次的发布。同时,由于第 2 批次和第 2 批次内实例个数为两台,因此选择批次内两台实例部署间隔为 60 秒。在发布页面右侧可以对我们的发布策略配置信息进行预览。

3.png


设置灰度规则

目前支持按内容灰度按比例灰度两种方式设置灰度规则。按请求内容进行灰度支持将请求内容符合指定灰度规则条件的流量作为灰度流量,进入到灰度实例中,例如,选择用户 ID 模 100 小于等于 40 的流量作为灰度流量进入灰度实例进行处理,而用户 ID 模 100 大于 40 的仍然进入非灰度实例进行处理,如图 1 所示。而按流量比例进行灰度是指,将指定比例的请求流量作为灰度流量进入灰度实例进行处理,例如指定 40% 的流量作为灰度流量,如图 2 所示。

4.png

(图1)
5.png

(图2)

按请求内容进行灰度

按请求内容进行灰度可以进行下面指定参数的配置,来决定有哪些请求内容特征的流量将作为灰度流量进入灰度实例中。
  • 协议类型:可选择 Spring Cloud 和 Dubbo,这里我们主要介绍 Spring Cloud 协议。在 Spring Cloud 协议下需要对 HTTP 请求路径进行配置;
  • 条件模式:针对下面配置的的条件列表,可配置条件模式为:同时满足下列条件满足下列任一条件。符合条件模式的请求将作为灰度流量;
  • 条件列表:Spring Cloud 协议下可分别对 Cookie、Header 和 Parameter 3 种请求内容进行条件配置。


6.png


按比例进行灰度

按比例灰度即设置流量比例,然后请求流量会按配置的比例被转发到当前的灰度分组中进行处理。

7.png


灰度发布并验证新版本应用是否符合预期

配置好发布配置后,即可开始进行灰度发布,EDAS 将先在指定的灰度分组中部署新版本应用,可在进入变更详情页面查看部署进度和状态。如果在灰度发布时,发现新版本有问题,还可以终止变更并对应用进行回滚。

在灰度的发布过程中,可对应用进行监控,以监控灰度流量是否符合预期,同时可以对应用状态进行新老版本的对比。在当前批次的灰度流量验证完成后,在变更详情页面单击开始下一批,完成后续分批发布。如果在验证过程中,发现新版本应用有问题,可以在变更详情页面右上角单击立即回滚。在弹出的立即回滚对话框确认回滚的影响,然后单击回滚。

关于如何监控灰度流量,可以参考 EDAS文档《监控灰度流量》

8.png


灰度发布后,在基本信息页面查看部署包是否为新部署的应用版本。在实例部署信息页面查看应用实例的运行状态是否为运行正常。

9.png


结语及其后续

本章我们介绍了如何对 EDAS Kubernetes 集群上的 Spring Cloud 应用进行灰度发布,在灰度发布过程中,我们可以灵活地配置发布策略、灰度规则以及在发布过程中对流量及应用状态进行监控,并且提供了终止回滚等操作,最大程度地保证应用能够平滑地进行版本升级。接下来的文章中,我们将详细介绍在发布过程中如何对应用进行监控。

阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”
继续阅读 »

作者 | 白寂  阿里云开发工程师

导读:前三篇文章我们介绍了应用的开发和部署,那么在应用成功上云后,我就要面对应用的管理话题了,这一篇我们来看看如何做线上发布,并且是可灰度的。

相关文章推荐:


前言

在新版本上线时,无论是从产品稳定性还是用户对新版本的接受程度上考虑,直接将老应用升级到新版本应用都有很大风险的。我们一般的做法是,保证新老版本同时在线,并且先将少部分流量切换到新版本应用上,同时在此期间对新版本的应用请求进行观察。在确认新版本没有问题后,再逐步将更大比例的流量切换到新版本上。这个过程的核心是可以对流量的流入转发规则进行配置,EDAS 的金丝雀发布能力,提供了多个版本同时在线的能力,并且提供了灵活的配置规则来给不同的版本进行流量分配。

部署在 EDAS Kubernetes 集群中的 Spring Cloud 微服务应用,在新版本发布的时候可以使用金丝雀发布进行小规模验证,验证通过后再全量升级。

金丝雀发布配置

首先,进入 EDAS 的应用部署页面,对我们要进行部署升级的应用进行发布,在这里我们选择金丝雀(灰度)发布。需要注意的是,对灰度发布的流量控制,当前只对非入口应用的 Dubbo 和 Spring Cloud 应用生效。所谓入口应用,即承接外部流量的第一个应用节点。并且若您的应用使用了 HPA、Rancher、Istio、或者依赖Deployment.Metadata.Name 或 Deployment.Metadata.Uid 的功能与配置等 K8s 原生功能或配置时,请勿使用灰度发布或分批发布。否则,应用部署之后,这些 K8s 原生功能或配置将出现异常。

1.png


在发布页面,可以选择通过上传 JAR 包或者填入 JAR 包地址的方式选择要进行发布的新版本应用部署包。

2.png


在选择好要进行发布的新版本应用部署包后,接下来进行发布策略的配置。这里分为两个部分:
  • 第一部分可以对发布批次进行设置,例如设置发布灰度批次,首批进行灰度的 pod 实例个数,分批间处理方式等;
  • 第二部分可以对流量灰度规则进行配置,我们可以选择按流量内容进行灰度或者简单地按照流量比例进行灰度,下面将详细介绍这两种发布策略配置。


设置发布策略

在批次发布这里我们可以进行的配置有:
  • 首批灰度数量:在点击发布后,会首先将首批灰度数量个数的实例进行新版本的发布,为了保证应用的稳定性,首批灰度的实例数不能超过应用实例总数的 50%。比如当前实例数是 7 台,那么最多只能选择 3 台作为首批灰度的实例;
  • 剩余批次:首批灰度发布完成后,剩余的应用实例将按照此处指定的批次发布完成;
  • 分批间处理方式:剩余批次间的处理方式可选择手动或者自动,若选择自动,则剩余的几个批次将在前一批发布完成后进行自动发布,自动发布的批次间隔也可进行配置,例如配置每批次在发布完成后,30 分钟后自动进行下一批次的发布;
  • 批次内部署间隔:每一批次内,如果此批次内要发布的应用实例数大于 1,则要进行此配置指定批次内实例部署间隔。


在下面的例子中,我们现在有 7 个 pod 应用实例,选择首批对 2 个实例进行灰度升级。在首批 2 个实例的灰度发布完成后,将剩下的 5 个实例分 3 个批次进行发布。这3个批次的批次间处理方式选择自动发布,在当前批次发布完成 30 分钟后自动进行下一批次的发布。同时,由于第 2 批次和第 2 批次内实例个数为两台,因此选择批次内两台实例部署间隔为 60 秒。在发布页面右侧可以对我们的发布策略配置信息进行预览。

3.png


设置灰度规则

目前支持按内容灰度按比例灰度两种方式设置灰度规则。按请求内容进行灰度支持将请求内容符合指定灰度规则条件的流量作为灰度流量,进入到灰度实例中,例如,选择用户 ID 模 100 小于等于 40 的流量作为灰度流量进入灰度实例进行处理,而用户 ID 模 100 大于 40 的仍然进入非灰度实例进行处理,如图 1 所示。而按流量比例进行灰度是指,将指定比例的请求流量作为灰度流量进入灰度实例进行处理,例如指定 40% 的流量作为灰度流量,如图 2 所示。

4.png

(图1)
5.png

(图2)

按请求内容进行灰度

按请求内容进行灰度可以进行下面指定参数的配置,来决定有哪些请求内容特征的流量将作为灰度流量进入灰度实例中。
  • 协议类型:可选择 Spring Cloud 和 Dubbo,这里我们主要介绍 Spring Cloud 协议。在 Spring Cloud 协议下需要对 HTTP 请求路径进行配置;
  • 条件模式:针对下面配置的的条件列表,可配置条件模式为:同时满足下列条件满足下列任一条件。符合条件模式的请求将作为灰度流量;
  • 条件列表:Spring Cloud 协议下可分别对 Cookie、Header 和 Parameter 3 种请求内容进行条件配置。


6.png


按比例进行灰度

按比例灰度即设置流量比例,然后请求流量会按配置的比例被转发到当前的灰度分组中进行处理。

7.png


灰度发布并验证新版本应用是否符合预期

配置好发布配置后,即可开始进行灰度发布,EDAS 将先在指定的灰度分组中部署新版本应用,可在进入变更详情页面查看部署进度和状态。如果在灰度发布时,发现新版本有问题,还可以终止变更并对应用进行回滚。

在灰度的发布过程中,可对应用进行监控,以监控灰度流量是否符合预期,同时可以对应用状态进行新老版本的对比。在当前批次的灰度流量验证完成后,在变更详情页面单击开始下一批,完成后续分批发布。如果在验证过程中,发现新版本应用有问题,可以在变更详情页面右上角单击立即回滚。在弹出的立即回滚对话框确认回滚的影响,然后单击回滚。

关于如何监控灰度流量,可以参考 EDAS文档《监控灰度流量》

8.png


灰度发布后,在基本信息页面查看部署包是否为新部署的应用版本。在实例部署信息页面查看应用实例的运行状态是否为运行正常。

9.png


结语及其后续

本章我们介绍了如何对 EDAS Kubernetes 集群上的 Spring Cloud 应用进行灰度发布,在灰度发布过程中,我们可以灵活地配置发布策略、灰度规则以及在发布过程中对流量及应用状态进行监控,并且提供了终止回滚等操作,最大程度地保证应用能够平滑地进行版本升级。接下来的文章中,我们将详细介绍在发布过程中如何对应用进行监控。

阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的公众号。”
收起阅读 »

SkyWalking观测Service Mesh技术大公开


Service Mesh的监控往往被称为可观测性(Observability),其内涵是要超越传统的监控体系的。它一般包括监控、告警、可视化、分布式追踪与日志分析。可见可观测性是监控的一个超集。监控认为目标系统是一个“黑盒”,通过观察其关键指标来展现系统状态,并报告异常情况。而可观测性在此基础上增加了“问题定位”的功能,通过可视化、分布式追踪和日志分析功能来提供给用户交互式定位问题的能力。

传统应用的SRE只能够通过监控系统发现失败的目标应用,而后由产品工程师来从代码层面最终定位到具体问题。对于维护基于Service Mesh的微服务集群,SRE就需要可观测性赋予的各种综合能力来发现更加具体的问题,这种过程类似于在微服务集群中进行调试操作。

可观测性是Service Mesh原生就需要解决的核心问题。由于Service Mesh被认为是新一代的基础设施,在其上构建可观测组件将会比在应用中构建更为便捷。同时,随着基础设施的落地与标准的逐步成型,可观测组件将会进行稳定的演进,而不会随着应用技术栈的变迁而推倒重来。基于以上原因,作用于Service Mesh之上的可观测性将会有更强的生命力与更大的商业潜力。

本文首先介绍SkyWalking的可观测性模型,然后以Istio和Envoy为例来介绍SkyWalking对它们的观测手段和未来技术的演进趋势。

SkyWalking可观测性模型

监控指标

SkyWalking主要使用“黑盒”追踪模型来生成Service Mesh的监控指标。与经典“黑盒”算法不同,SkyWalking并不会使用回归模型生成单条Trace数据,而是直接使用分析引擎构建监控指标和拓扑图。

如图所示,SkyWalking从Service Mesh数据平面获取到图中被标记为奇数的请求数据(1,3,5,7,9,11)。传统的“黑盒”算法会尝试还原被标记为偶数的链路,从而形成完整的调用链。而SkyWalking会直接进行汇总统计,计算出两节点之间的监控指标,再使用这些成对的数据构建出一段时间内的拓扑图。
1.png

Service Mesh流量图

故SkyWalking在Service Mesh模式下,Trace功能是缺失的,而其他功能是完好的。这是在效率和功能完整性之间的平衡。当然,如果希望使用Trace功能,可以通过另外一套SkyWalking集群实现。

通用Service Mesh的协议保存在https://github.com/apache/skyw ... proto。目前SkyWalking仅仅支持Istio,如果用户希望支持其他的Service Mesh平台,可以使用该协议向SkyWalking写入监控数据。

让我们看一下协议的核心内容:
message ServiceMeshMetric {
int64 startTime = 1;
int64 endTime = 2;
string sourceServiceName = 3;
int32 sourceServiceId = 4;
string sourceServiceInstance = 5;
int32 sourceServiceInstanceId = 6;
string destServiceName = 7;
int32 destServiceId = 8;
string destServiceInstance = 9;
int32 destServiceInstanceId = 10;
string endpoint = 11;
int32 latency = 12;
int32 responseCode = 13;
bool status = 14;
Protocol protocol = 15;
DetectPoint detectPoint = 16;


如协议所示,主要内容都是写入一次调用的双端信息。这里要注意,要想获得正确的拓扑图,服务的ID要保持一致。假如需要生成A→B→C的拓扑图,则需要产生如下两条数据:
sourceServiceId = A
...
destServiceId = B
sourceServiceId = B
...
destServiceId = C

告警与可视化

Service Mesh的监控指标与分布式追踪的指标是使用统一的引擎聚合计算的,故其告警体系完全可以复用。这里唯一需要注意的是维度的映射。

以Kubernetes环境为例,其内置资源非常丰富,到底用什么资源来映射到SkyWalking的Service呢?这里选择范围是很广泛的,Deployment、Service、Statefulset看起来都可以,甚至一些Custom Resource也是可以的。这就需要使用者进行相关的设计,根据自己系统的状况来将特定的目标进行映射。目前官方的做法是使用Statefulset来映射到Service,因为它可以指向多种二级资源,监控性非常好。如果用户有定制化需求,也可以自行添加。

可视化与告警类似,只要维度定义得当,监控指标和拓扑图就会依照维度进行完美展示。

分布式追踪和日志

从理论上讲,Service Mesh并不能给追踪带来任何变化。由于Service Mesh仅仅控制了流量的入口和出口,仅仅在proxy和sidecar上增加追踪上下文的注入并不能将整个上下文在集群内传播,所以服务本身需要被注入追踪上下文。

可能有读者会认为,既然如此,那么就不要在Service Mesh组件内增加传播模块了,还能减少额外的消耗而不影响追踪链路。需要说明的是,追踪标记点越多,其实越能更好地理解系统状态,帮助定位问题。

这里举一个例子来说明在Service Mesh组件上增加追踪能力的作用。一个服务如果响应超时,传统上我们是不能区分是网络问题还是服务本身的问题的。但是有了Service Mesh的inbound agent,我们就可以从该agent有无数据来判断是哪种问题:如果inbound有数据,说明是目标服务的问题;如果inbound没有数据,则很可能是网络问题。

对于日志,SkyWalking从系统设计上并不涵盖日志的搜集和存储,但是部分用户在实践中,会使用LocalSpan将业务日志写入其中。同时由于7.0.0以后SkyWalking会引入业务扩展字段,可以预见未来将会有更多用户将SkyWalking作为接收和分析日志的系统。日志、分布式追踪与监控指标的结合也是SkyWalking后端分析的发展
目标。

观测Istio的监控指标

SkyWalking主要是接受Istio的监控指标来进行聚合分析。由于Istio并不支持SkyWalking的追踪上下文传播的功能,故这部分不在讨论范围内。现在让我们讨论一下SkyWalking与Istio的两种集成模式。

Mixer模式集成

除了网络流量控制服务以外,Istio同时提供了对Telemetry数据集成的功能。Telemetry组件主要通过Mixer进行集成,如图2所示,而这恰恰就是SkyWalking首先与Istio集成的点。早期Istio可以进行进程内的集成,即将集成代码添加到其源码进行变异,以达到最高性能。后来Istio为了降低系统的集成复杂性,将该功能演变为进程外的适配器。目前SkyWalking就是采用这种进程外适配器进行集成的。
2.png

SkyWalking集成Mixer

未来Mixer 2.0版本将会采用Envoy的WASM系统模型进行构建,Mixer插件将可以二进制形式被Envoy进行动态的变异加载。SkyWalking社区会跟进该模式,以实现新的适配器模型。

集成后,我们就可以看到如图中所示的监控指标页面和服务拓扑图了。
3.png

监控指标Dashboard

4.png

使用Mixer生成的服务拓扑图

ALS模式集成

除了进行Mixer的集成以外,SkyWalking同时可以与Envoy的ALS(Access Log Service)进行相关的系统集成(见图5),以达到Mixer类似的效果。与Envoy集成的优势在于,可以非常高效地将访问日志发送给SkyWalking的接收器,这样延迟最小。但缺点是目前的ALS发送数据非常多,会潜在影响SkyWalking的处理性能和网络带宽;同时,所有的分析模块都依赖于较为底层的访问日志,一些Istio的相关特性不能被识别。比如这种模式下只能识别Envoy的元数据,Istio的虚拟服务等无法有效识别。对比图6与图4所示的拓扑图,我们并没有发现istio-policy组件,这是由于该组件与sidecar之间的通信是不通过Envoy转发的,故从ALS中无法获得此信息。
5.png

SkyWalking与ALS

6.png

使用ALS生成的服务拓扑图

观测Istio的技术发展

目前Istio和SkyWalking都处于高速发展之中。Istio对于可观测的演进主要有以下几个方面。
  • Mixer被移除。Mixer由于其性能问题将被移除,上面介绍的第一种集成模式很快会成为历史。
  • Envoy WASM将会替代Mixer成为可观测的主力。未来,SkyWalking将会深度与Envoy WASM技术结合,它会带来如下好处。
  • 开发灵活。WASM技术类似Nginx的LuaJIT,依靠C 与Rust语言,可以获得很好的灵活性。
  • 性能优良。由于WASM代码会被编译到Envoy内部,其性能有很好的保证。
  • 功能丰富。根据不能的场景,可以提供不同的插件组合,组合出更丰富的功能。基于以上的特点,SkyWalking对于Envoy和Istio可能有以下演进方向的影响。
  • 使Envoy和Istio支持SkyWalking专用的追踪传播协议。
  • 精细控制Envoy发送到OAP的数据粒度,目前ALS模式传入的数据过于繁杂,且不能裁剪,使用WASM插件后希望可以进行更细的控制。
  • 支持更多的控制平面。由于使用Envoy作为数据平面的Service Mesh系统已经有一定规模,使用WASM模式可以避免与特定控制平面绑定,从而支持更多的系统。


本文转载自《Apache SkyWalking实战》一书,本文经出版社授权发布。
继续阅读 »

Service Mesh的监控往往被称为可观测性(Observability),其内涵是要超越传统的监控体系的。它一般包括监控、告警、可视化、分布式追踪与日志分析。可见可观测性是监控的一个超集。监控认为目标系统是一个“黑盒”,通过观察其关键指标来展现系统状态,并报告异常情况。而可观测性在此基础上增加了“问题定位”的功能,通过可视化、分布式追踪和日志分析功能来提供给用户交互式定位问题的能力。

传统应用的SRE只能够通过监控系统发现失败的目标应用,而后由产品工程师来从代码层面最终定位到具体问题。对于维护基于Service Mesh的微服务集群,SRE就需要可观测性赋予的各种综合能力来发现更加具体的问题,这种过程类似于在微服务集群中进行调试操作。

可观测性是Service Mesh原生就需要解决的核心问题。由于Service Mesh被认为是新一代的基础设施,在其上构建可观测组件将会比在应用中构建更为便捷。同时,随着基础设施的落地与标准的逐步成型,可观测组件将会进行稳定的演进,而不会随着应用技术栈的变迁而推倒重来。基于以上原因,作用于Service Mesh之上的可观测性将会有更强的生命力与更大的商业潜力。

本文首先介绍SkyWalking的可观测性模型,然后以Istio和Envoy为例来介绍SkyWalking对它们的观测手段和未来技术的演进趋势。

SkyWalking可观测性模型

监控指标

SkyWalking主要使用“黑盒”追踪模型来生成Service Mesh的监控指标。与经典“黑盒”算法不同,SkyWalking并不会使用回归模型生成单条Trace数据,而是直接使用分析引擎构建监控指标和拓扑图。

如图所示,SkyWalking从Service Mesh数据平面获取到图中被标记为奇数的请求数据(1,3,5,7,9,11)。传统的“黑盒”算法会尝试还原被标记为偶数的链路,从而形成完整的调用链。而SkyWalking会直接进行汇总统计,计算出两节点之间的监控指标,再使用这些成对的数据构建出一段时间内的拓扑图。
1.png

Service Mesh流量图

故SkyWalking在Service Mesh模式下,Trace功能是缺失的,而其他功能是完好的。这是在效率和功能完整性之间的平衡。当然,如果希望使用Trace功能,可以通过另外一套SkyWalking集群实现。

通用Service Mesh的协议保存在https://github.com/apache/skyw ... proto。目前SkyWalking仅仅支持Istio,如果用户希望支持其他的Service Mesh平台,可以使用该协议向SkyWalking写入监控数据。

让我们看一下协议的核心内容:
message ServiceMeshMetric {
int64 startTime = 1;
int64 endTime = 2;
string sourceServiceName = 3;
int32 sourceServiceId = 4;
string sourceServiceInstance = 5;
int32 sourceServiceInstanceId = 6;
string destServiceName = 7;
int32 destServiceId = 8;
string destServiceInstance = 9;
int32 destServiceInstanceId = 10;
string endpoint = 11;
int32 latency = 12;
int32 responseCode = 13;
bool status = 14;
Protocol protocol = 15;
DetectPoint detectPoint = 16;


如协议所示,主要内容都是写入一次调用的双端信息。这里要注意,要想获得正确的拓扑图,服务的ID要保持一致。假如需要生成A→B→C的拓扑图,则需要产生如下两条数据:
sourceServiceId = A
...
destServiceId = B
sourceServiceId = B
...
destServiceId = C

告警与可视化

Service Mesh的监控指标与分布式追踪的指标是使用统一的引擎聚合计算的,故其告警体系完全可以复用。这里唯一需要注意的是维度的映射。

以Kubernetes环境为例,其内置资源非常丰富,到底用什么资源来映射到SkyWalking的Service呢?这里选择范围是很广泛的,Deployment、Service、Statefulset看起来都可以,甚至一些Custom Resource也是可以的。这就需要使用者进行相关的设计,根据自己系统的状况来将特定的目标进行映射。目前官方的做法是使用Statefulset来映射到Service,因为它可以指向多种二级资源,监控性非常好。如果用户有定制化需求,也可以自行添加。

可视化与告警类似,只要维度定义得当,监控指标和拓扑图就会依照维度进行完美展示。

分布式追踪和日志

从理论上讲,Service Mesh并不能给追踪带来任何变化。由于Service Mesh仅仅控制了流量的入口和出口,仅仅在proxy和sidecar上增加追踪上下文的注入并不能将整个上下文在集群内传播,所以服务本身需要被注入追踪上下文。

可能有读者会认为,既然如此,那么就不要在Service Mesh组件内增加传播模块了,还能减少额外的消耗而不影响追踪链路。需要说明的是,追踪标记点越多,其实越能更好地理解系统状态,帮助定位问题。

这里举一个例子来说明在Service Mesh组件上增加追踪能力的作用。一个服务如果响应超时,传统上我们是不能区分是网络问题还是服务本身的问题的。但是有了Service Mesh的inbound agent,我们就可以从该agent有无数据来判断是哪种问题:如果inbound有数据,说明是目标服务的问题;如果inbound没有数据,则很可能是网络问题。

对于日志,SkyWalking从系统设计上并不涵盖日志的搜集和存储,但是部分用户在实践中,会使用LocalSpan将业务日志写入其中。同时由于7.0.0以后SkyWalking会引入业务扩展字段,可以预见未来将会有更多用户将SkyWalking作为接收和分析日志的系统。日志、分布式追踪与监控指标的结合也是SkyWalking后端分析的发展
目标。

观测Istio的监控指标

SkyWalking主要是接受Istio的监控指标来进行聚合分析。由于Istio并不支持SkyWalking的追踪上下文传播的功能,故这部分不在讨论范围内。现在让我们讨论一下SkyWalking与Istio的两种集成模式。

Mixer模式集成

除了网络流量控制服务以外,Istio同时提供了对Telemetry数据集成的功能。Telemetry组件主要通过Mixer进行集成,如图2所示,而这恰恰就是SkyWalking首先与Istio集成的点。早期Istio可以进行进程内的集成,即将集成代码添加到其源码进行变异,以达到最高性能。后来Istio为了降低系统的集成复杂性,将该功能演变为进程外的适配器。目前SkyWalking就是采用这种进程外适配器进行集成的。
2.png

SkyWalking集成Mixer

未来Mixer 2.0版本将会采用Envoy的WASM系统模型进行构建,Mixer插件将可以二进制形式被Envoy进行动态的变异加载。SkyWalking社区会跟进该模式,以实现新的适配器模型。

集成后,我们就可以看到如图中所示的监控指标页面和服务拓扑图了。
3.png

监控指标Dashboard

4.png

使用Mixer生成的服务拓扑图

ALS模式集成

除了进行Mixer的集成以外,SkyWalking同时可以与Envoy的ALS(Access Log Service)进行相关的系统集成(见图5),以达到Mixer类似的效果。与Envoy集成的优势在于,可以非常高效地将访问日志发送给SkyWalking的接收器,这样延迟最小。但缺点是目前的ALS发送数据非常多,会潜在影响SkyWalking的处理性能和网络带宽;同时,所有的分析模块都依赖于较为底层的访问日志,一些Istio的相关特性不能被识别。比如这种模式下只能识别Envoy的元数据,Istio的虚拟服务等无法有效识别。对比图6与图4所示的拓扑图,我们并没有发现istio-policy组件,这是由于该组件与sidecar之间的通信是不通过Envoy转发的,故从ALS中无法获得此信息。
5.png

SkyWalking与ALS

6.png

使用ALS生成的服务拓扑图

观测Istio的技术发展

目前Istio和SkyWalking都处于高速发展之中。Istio对于可观测的演进主要有以下几个方面。
  • Mixer被移除。Mixer由于其性能问题将被移除,上面介绍的第一种集成模式很快会成为历史。
  • Envoy WASM将会替代Mixer成为可观测的主力。未来,SkyWalking将会深度与Envoy WASM技术结合,它会带来如下好处。
  • 开发灵活。WASM技术类似Nginx的LuaJIT,依靠C 与Rust语言,可以获得很好的灵活性。
  • 性能优良。由于WASM代码会被编译到Envoy内部,其性能有很好的保证。
  • 功能丰富。根据不能的场景,可以提供不同的插件组合,组合出更丰富的功能。基于以上的特点,SkyWalking对于Envoy和Istio可能有以下演进方向的影响。
  • 使Envoy和Istio支持SkyWalking专用的追踪传播协议。
  • 精细控制Envoy发送到OAP的数据粒度,目前ALS模式传入的数据过于繁杂,且不能裁剪,使用WASM插件后希望可以进行更细的控制。
  • 支持更多的控制平面。由于使用Envoy作为数据平面的Service Mesh系统已经有一定规模,使用WASM模式可以避免与特定控制平面绑定,从而支持更多的系统。


本文转载自《Apache SkyWalking实战》一书,本文经出版社授权发布。 收起阅读 »

Kubernetes网络与防火墙联动方案探索


【编者的话】作为事实上的容器云标准,Kubernetes为应用带来了快速部署、快速迭代、快速扩缩容等便利,同时在简化运维和提高硬件资源利用率等方面也有很大的优势。但Kubernetes中应用的Pod IP是允许变化的,而且Pod使用Kubernetes内部虚拟网络,Pod本身IP对外不可见,应用Pod出集群数据包源IP地址使用的是其所在宿主机IP。在这种情况下,为满足对应用流量管控的要求,需要为应用划分专用的虚拟机节点,以虚拟机的IP区分应用进行流量管控,这不能充分发挥Kubernetes资源利用率方面的优势。为达到对应用Pod流量进行精细化管控的目的,提高Kubernetes资源利用率,我们对Kubernetes网络和防火墙联动方案进行探索。

Kubernetes网络方案介绍

在介绍Kubernetes网络与防火墙联动方案之前,需要先简单介绍一下Kubernetes的网络方案。

Kubernetes网络的基本设计原则是每个Pod都拥有唯一一个独立的IP地址,用户不需要额外考虑如何建立Pod之间的连接,也不需要考虑容器端口与宿主机端口映射等问题。Kubernetes并不具体去实现诸如给Pod分配IP、回收IP、记录宿主机IP—Pod IP对应关系之类的细节,而是委托CNI实例去管理Pod的网络资源并为Pod建立互通能力。CNI(Container Network Interface)是一个标准的接口规范,其本身实现了一些基本的插件, 比如bridge、ipvlan、macvlan、loopback、vlan等网络接口。

目前主流的容器网络解决方案都有对应CNI的支持能力,比如Flannel、Calico、Weave、Contiv、SR-IOV、Amazon ECS CNI Plugins等。我行Kubernetes集群使用的网络插件即为Flannel插件。一般来说,这些容器网络插件的工作模式可从容器网络流量穿越宿主机网络的形态方面分为两种:
  • Overlay网络:容器网络的IP和MAC地址对宿主机网络不可见,跨宿主机容器间通信需要将容器流量进行封装转发,而容器出集群的流量需要进行SNAT转换。Flannel的vxlan工作模式、Calico的IPIP模式均属于该类型。
  • Underlay网络:容器网络对宿主机可见,在容器进行通信时不需要对流量进行封装,直接建立路由表,根据规则进行路由转发进行通信。Flannel的host-gw工作模式、Calico的BGP工作模式均属于该类型。


目前我行使用的Fannel插件的VXLAN工作模式即属于第一种方案。如下图所示,在该模式下,Pod-1通过veth pair的方式连接到node1的cni0网桥上。在跟Pod-2通信时数据包首先通过cni0到达宿主机,根据宿主机路由规则(172.16.2.0/24 via 172.16.2.0 dev flannel.1 onlink)将数据包交给VTEP设备Flannel.1处理。然后,Flannel.1设备将数据包进行VXLAN封装,在宿主机网络中进行传输,待数据包到达Node2时再由Node2上的Flannel.1设备解封得到原始数据包并传递给Pod-2。
1.png

在该种模式下,跨宿主机Pod间的通信需要进行封装传输,Pod的IP地址不会暴露在宿主机网络,使得不同集群可以使用同一个Pod地址池。但是,在该种模式下,除了Pod间跨宿主机通信会对原始消息进行封装,Pod出集群的数据包也会进行SNAT转换,出集群的所有Pod流量其源地址使用的均是宿主机IP地址,导致我们无法对单个Pod进行精确的流量管控。

Kubernetes网络与防火墙联动方案

为达到对应用Pod流量进行精确管控的目的,第一,Pod数据流量需要可以区分;第二,Kubernetes中Pod的IP不是一直不变的,会随着Pod的建立、销毁、漂移等动作进行分配、回收、更新,这需要流量管控方随时掌握Pod和IP的对应关系。对于第一个问题,我们考虑使用基于路由转发方式的underlay容器网络方案,将Pod的IP地址对外暴露。对于第二个问题,我们使用Kubernetes客户端编写 Kubemonitor工具对Pod的变动信息进行监控,并实时把变动信息发送给网络防火墙更新策略。

基于路由转发的容器网络方案

行内Kubernetes平台使用的Flannel网络插件可以使用host-gw工作模式,该模式将宿主机作为主机路由,对其上的Pod流量进行路由转发,如图所示:
2.png

在host-gw网络模式下,Pod-1转发给Pod-2的流量不再经过封装,直接根据Node1的路由表转发至Node2传递到Pod-2。除此之外,要在集群外监控Pod-1的流量包,还需Pod-1的IP地址对集群外可见,需要配置Flannel的启动参数 –ip-masq=false 使得出群流量不经过SNAT转换。

使用Flannel host-gw网络模式,并且配置出集群流量不经过SNAT转换,除了需要网络方面配置Pod IP地址的回程路由外,每个集群将单独需要一个地址段来作为本集群的Pod 网络地址池。现用的VXLAN模式,集群的IP地址池是一个子网掩码为16为的虚拟地址段(172.16.0.0/16),该地址段最多支持256个集群节点,每个节点上可以为256个Pod分配IP地址。使用host-gw后,为了区分Pod流量和配置Pod的回程路由,Pod网络不能再使用虚拟地址段,且不同集群间也不能共用同一个地址段。该种情况下如果继续使用16位掩码的地址段作为Pod的IP地址池,会大量浪费行内IP地址段资源。为避免该问题,可将集群Pod网络的地址池的子网掩码调整为18,这样能在很大程度上减轻地址段的浪费。子网掩码为18的Pod地址段支持64个节点,每个节点支持256个Pod,可以满足我行集群需求。

Pod IP信息实时推送工具——Kubemonitor

要达到精细化管控Pod流量的目的,除了区分出Pod的流量,在Kubernetes中应用Pod会发生销毁、重建、副本缩放、漂移等情况,应用的Pod数量和IP地址是会发生变化的,需要编写自动化工具将Pod IP的变动信息实时推送防火墙开通策略。

如下图所示,Kubemonitor主要包含以下几个部分。
640.png

  • Kubernetes Client是Kubernetes集群的开源客户端,完成与Kuberetes集群的连接、验证、资源获取、监听等功能。该客户端使用了Kubernetes统一的异步消息处理机制——List-Watch机制,其中List机制用于一次性获取集群资源最新的状态,Watch机制用于监听Kubernetes资源变动,在资源新建、更新、删除时实时获得最新信息。
  • Resources Controller 根据配置文件选择监听的集群资源类型(Pod、Server、Statefultset、Deployment等),并调动Resources Manager模块去处理所监听资源的变动信息。
  • 当集群资源的任何属性值发生变化(如状态、硬件资源申请量、网络属性等)Resources Controller都会监听并获取到,但这么庞杂的变动信息不一定是我们关注的。在与防火墙联动的需求中,我们其实主要关注(应用系统,Pod名称,IP地址)这样一个三元组信息,而对其余的比如硬件资源申请量等并不关注。Resources Manager模块主要用于去除无关变动信息,并按约定格式生成通知消息。
  • Interface模块实现了与其他系统的对接接口。Kubemonitor通过Interface支持的接口类型(如Webhook、Kafka)将资源变动消息通知给所需系统。
  • Consensus Server共识服务。在容器环境部署需要考虑在Pod在被迁移、杀死、出错时的产生的服务连续性问题。Kubemonitor通过多副本部署来实现高可用行。但是多副本部署时每个副本都会独立监听并发送资源变动信息,导致对接系统收到变动消息重复。为此Kubeminitor使用分布式一致性协议Raft实现了Consensus Server功能。Consensus Server负责监听Kubemonitor副本的变化,选举出Master节点与对接系统通信,同时负责同步Kubemonitor所有副本获取到的资源变动信息的状态。该共识服务模块完成多副本部署时消息去重任务,且最多能容忍不多于一半的Kubemonitor副本掉线。
  • Kubemonitor的配置文件通过Config模块进行管理。除了给防火墙通知Pod变动信息外,未来所有需要Kubernete集群资源最新状态的系统均可进行配置,通过Kubemonitor进行实时推送。


后记

该工作完成后,Kubernetes集群内部东西向网络性能将提升20%,并可在对Pod流量进行精细化网络管控的前提下实现集群内应用混合部署,极大提高硬件资源利用率。

Kubernetes网络与防火墙联动方案目前已经与网络中心配合完成了前期的测试验证工作,即将交付业务进行试用。该方案对于容器平台来说除了涉及到Kubernetes集群underlay网络改造外,还要保证Kubemonitor推送消息的准确性和及时性;对于网络方也要论证使用underlay方案后的Kubernetes集群Pod地址段的划分、Pod回程路由的建立和路由规则下发、以及针对Pod进行的防火墙策略更新等问题,这些问题需要双方共同探索、论证、携手推进。

原文链接:https://mp.weixin.qq.com/s/FRTXWvn_Q-CpZFGELjhGHA
继续阅读 »

【编者的话】作为事实上的容器云标准,Kubernetes为应用带来了快速部署、快速迭代、快速扩缩容等便利,同时在简化运维和提高硬件资源利用率等方面也有很大的优势。但Kubernetes中应用的Pod IP是允许变化的,而且Pod使用Kubernetes内部虚拟网络,Pod本身IP对外不可见,应用Pod出集群数据包源IP地址使用的是其所在宿主机IP。在这种情况下,为满足对应用流量管控的要求,需要为应用划分专用的虚拟机节点,以虚拟机的IP区分应用进行流量管控,这不能充分发挥Kubernetes资源利用率方面的优势。为达到对应用Pod流量进行精细化管控的目的,提高Kubernetes资源利用率,我们对Kubernetes网络和防火墙联动方案进行探索。

Kubernetes网络方案介绍

在介绍Kubernetes网络与防火墙联动方案之前,需要先简单介绍一下Kubernetes的网络方案。

Kubernetes网络的基本设计原则是每个Pod都拥有唯一一个独立的IP地址,用户不需要额外考虑如何建立Pod之间的连接,也不需要考虑容器端口与宿主机端口映射等问题。Kubernetes并不具体去实现诸如给Pod分配IP、回收IP、记录宿主机IP—Pod IP对应关系之类的细节,而是委托CNI实例去管理Pod的网络资源并为Pod建立互通能力。CNI(Container Network Interface)是一个标准的接口规范,其本身实现了一些基本的插件, 比如bridge、ipvlan、macvlan、loopback、vlan等网络接口。

目前主流的容器网络解决方案都有对应CNI的支持能力,比如Flannel、Calico、Weave、Contiv、SR-IOV、Amazon ECS CNI Plugins等。我行Kubernetes集群使用的网络插件即为Flannel插件。一般来说,这些容器网络插件的工作模式可从容器网络流量穿越宿主机网络的形态方面分为两种:
  • Overlay网络:容器网络的IP和MAC地址对宿主机网络不可见,跨宿主机容器间通信需要将容器流量进行封装转发,而容器出集群的流量需要进行SNAT转换。Flannel的vxlan工作模式、Calico的IPIP模式均属于该类型。
  • Underlay网络:容器网络对宿主机可见,在容器进行通信时不需要对流量进行封装,直接建立路由表,根据规则进行路由转发进行通信。Flannel的host-gw工作模式、Calico的BGP工作模式均属于该类型。


目前我行使用的Fannel插件的VXLAN工作模式即属于第一种方案。如下图所示,在该模式下,Pod-1通过veth pair的方式连接到node1的cni0网桥上。在跟Pod-2通信时数据包首先通过cni0到达宿主机,根据宿主机路由规则(172.16.2.0/24 via 172.16.2.0 dev flannel.1 onlink)将数据包交给VTEP设备Flannel.1处理。然后,Flannel.1设备将数据包进行VXLAN封装,在宿主机网络中进行传输,待数据包到达Node2时再由Node2上的Flannel.1设备解封得到原始数据包并传递给Pod-2。
1.png

在该种模式下,跨宿主机Pod间的通信需要进行封装传输,Pod的IP地址不会暴露在宿主机网络,使得不同集群可以使用同一个Pod地址池。但是,在该种模式下,除了Pod间跨宿主机通信会对原始消息进行封装,Pod出集群的数据包也会进行SNAT转换,出集群的所有Pod流量其源地址使用的均是宿主机IP地址,导致我们无法对单个Pod进行精确的流量管控。

Kubernetes网络与防火墙联动方案

为达到对应用Pod流量进行精确管控的目的,第一,Pod数据流量需要可以区分;第二,Kubernetes中Pod的IP不是一直不变的,会随着Pod的建立、销毁、漂移等动作进行分配、回收、更新,这需要流量管控方随时掌握Pod和IP的对应关系。对于第一个问题,我们考虑使用基于路由转发方式的underlay容器网络方案,将Pod的IP地址对外暴露。对于第二个问题,我们使用Kubernetes客户端编写 Kubemonitor工具对Pod的变动信息进行监控,并实时把变动信息发送给网络防火墙更新策略。

基于路由转发的容器网络方案

行内Kubernetes平台使用的Flannel网络插件可以使用host-gw工作模式,该模式将宿主机作为主机路由,对其上的Pod流量进行路由转发,如图所示:
2.png

在host-gw网络模式下,Pod-1转发给Pod-2的流量不再经过封装,直接根据Node1的路由表转发至Node2传递到Pod-2。除此之外,要在集群外监控Pod-1的流量包,还需Pod-1的IP地址对集群外可见,需要配置Flannel的启动参数 –ip-masq=false 使得出群流量不经过SNAT转换。

使用Flannel host-gw网络模式,并且配置出集群流量不经过SNAT转换,除了需要网络方面配置Pod IP地址的回程路由外,每个集群将单独需要一个地址段来作为本集群的Pod 网络地址池。现用的VXLAN模式,集群的IP地址池是一个子网掩码为16为的虚拟地址段(172.16.0.0/16),该地址段最多支持256个集群节点,每个节点上可以为256个Pod分配IP地址。使用host-gw后,为了区分Pod流量和配置Pod的回程路由,Pod网络不能再使用虚拟地址段,且不同集群间也不能共用同一个地址段。该种情况下如果继续使用16位掩码的地址段作为Pod的IP地址池,会大量浪费行内IP地址段资源。为避免该问题,可将集群Pod网络的地址池的子网掩码调整为18,这样能在很大程度上减轻地址段的浪费。子网掩码为18的Pod地址段支持64个节点,每个节点支持256个Pod,可以满足我行集群需求。

Pod IP信息实时推送工具——Kubemonitor

要达到精细化管控Pod流量的目的,除了区分出Pod的流量,在Kubernetes中应用Pod会发生销毁、重建、副本缩放、漂移等情况,应用的Pod数量和IP地址是会发生变化的,需要编写自动化工具将Pod IP的变动信息实时推送防火墙开通策略。

如下图所示,Kubemonitor主要包含以下几个部分。
640.png

  • Kubernetes Client是Kubernetes集群的开源客户端,完成与Kuberetes集群的连接、验证、资源获取、监听等功能。该客户端使用了Kubernetes统一的异步消息处理机制——List-Watch机制,其中List机制用于一次性获取集群资源最新的状态,Watch机制用于监听Kubernetes资源变动,在资源新建、更新、删除时实时获得最新信息。
  • Resources Controller 根据配置文件选择监听的集群资源类型(Pod、Server、Statefultset、Deployment等),并调动Resources Manager模块去处理所监听资源的变动信息。
  • 当集群资源的任何属性值发生变化(如状态、硬件资源申请量、网络属性等)Resources Controller都会监听并获取到,但这么庞杂的变动信息不一定是我们关注的。在与防火墙联动的需求中,我们其实主要关注(应用系统,Pod名称,IP地址)这样一个三元组信息,而对其余的比如硬件资源申请量等并不关注。Resources Manager模块主要用于去除无关变动信息,并按约定格式生成通知消息。
  • Interface模块实现了与其他系统的对接接口。Kubemonitor通过Interface支持的接口类型(如Webhook、Kafka)将资源变动消息通知给所需系统。
  • Consensus Server共识服务。在容器环境部署需要考虑在Pod在被迁移、杀死、出错时的产生的服务连续性问题。Kubemonitor通过多副本部署来实现高可用行。但是多副本部署时每个副本都会独立监听并发送资源变动信息,导致对接系统收到变动消息重复。为此Kubeminitor使用分布式一致性协议Raft实现了Consensus Server功能。Consensus Server负责监听Kubemonitor副本的变化,选举出Master节点与对接系统通信,同时负责同步Kubemonitor所有副本获取到的资源变动信息的状态。该共识服务模块完成多副本部署时消息去重任务,且最多能容忍不多于一半的Kubemonitor副本掉线。
  • Kubemonitor的配置文件通过Config模块进行管理。除了给防火墙通知Pod变动信息外,未来所有需要Kubernete集群资源最新状态的系统均可进行配置,通过Kubemonitor进行实时推送。


后记

该工作完成后,Kubernetes集群内部东西向网络性能将提升20%,并可在对Pod流量进行精细化网络管控的前提下实现集群内应用混合部署,极大提高硬件资源利用率。

Kubernetes网络与防火墙联动方案目前已经与网络中心配合完成了前期的测试验证工作,即将交付业务进行试用。该方案对于容器平台来说除了涉及到Kubernetes集群underlay网络改造外,还要保证Kubemonitor推送消息的准确性和及时性;对于网络方也要论证使用underlay方案后的Kubernetes集群Pod地址段的划分、Pod回程路由的建立和路由规则下发、以及针对Pod进行的防火墙策略更新等问题,这些问题需要双方共同探索、论证、携手推进。

原文链接:https://mp.weixin.qq.com/s/FRTXWvn_Q-CpZFGELjhGHA 收起阅读 »