作为一家深耕教育一线多年的科技公司,作业帮具有规模化和复杂化业务特点。为了支撑数千个应用服务,应对不同语言栈、同一语言栈不同业务需求的复杂性,作业帮早就开始探索多云架构。至于,云架构如何来做?IaaS、服务治理、PaaS、SaaS每层要如何设计?如何从单云架构迁移到多云?本文结合作业帮实际业务发展,具体介绍了多云架构的实践经验。
本期分享嘉宾
董晓聪
作业帮基础架构负责人
【简介】董晓聪,之前主要曾在百度、旷视等公司负责架构和技术管理工作,擅长业务中台、技术中台、研发中台的搭建和迭代。19年底加入作业帮担任基础架构负责人,负责作业帮架构研发、运维、DBA、安全等工作。20年初主导了作业帮云原生建设,开始进行底层技术的重塑,当前已完成96%以上业务的容器化改造,建成了一套完备的微服务治理、DevSecOps、多云多活架构体系,带来了一系列稳定性、成本、效率、安全上的收益。成为阿里云云原生方向的MVP,腾讯云云原生方向的TVP。作业帮在FinOps领域也取得一定成绩,成为中国产业互联网发展联盟主办的FinOps产品标准工作组中副组长单位。
作业帮教育科技(北京)有限公司成立于2015年,一直致力于用科技手段助力教育普惠,运用人工智能、大数据等前沿技术,为学生、老师、家长提供更高效的学习、教育解决方案,智能硬件产品等。
技术现状
作业帮的技术现状可以归纳为两点,即规模化和复杂化。“规模化”。是指作业帮有数千个应用服务,然后对应数万个服务实例,这么多的业务实例跑在数十万的计算核心之上;“复杂化”,是指作业帮的技术栈比较多元,基本上主流的技术栈都有,其中占比高的像PHP、Golang能占到公司的60%;除此之外还有大量模块是用Node.js、 Java、Python、C++等进行编写的。
大体来看,作业帮主要的技术栈是PHP。PHP主要的技术体系是基于odp,更准确地说是odp2.0,是百度2010年内部自研的一款以框架为核心的虚机架构的整体的解决方案,它能够快速实现新业务孵化。即便大家都同样使用odp这样的框架,也会因为不同业务特点、团队能力等因素出现技术栈上的差异。比如:工具侧的产品更侧重于客户端,所以在服务端上的一些技术其实是偏向于保守;但像产业互联网这类业务,其实是领域驱动,会大量使用微服务架构,当时由于没有统一标准,各自团队也在自研一些服务治理体系的基础设施。
混合部署其实也是odp的一大特色,将不同的模块部署在同一组机器、同一组服务单元上,这对成本是有帮助的,它能够有效提升资源的一个利用率。但是,也带来一系列的稳定性和效率的问题。究其本质,其实还是代码、模块、应用服务、机器之间其实没有一个明确的一个对应关系导致。
单云架构瓶颈
作业帮从创立之初,基础业务就是语音服务,充分享受到云计算带来的红利。但在传统单云架构下,作业帮遇到了一些问题和挑战:
▶︎ 首先,故障恢复
在单云架构出现故障的时候,尤其是大规模故障,涉及到了一些整体的网络故障,业务团队什么也做不了,就只能等着运维团队进行业务恢复。同时,运维团队也做不了什么,只能去等着云厂商恢复。至于,具体什么时间恢复,很难得到一个明确答复,有一种束手无策的感觉。其实,云厂商也没有我们想象的那么稳定。就公开数据来看,国内外的公有云厂商均出现过故障或者宕机的问题。而在线教育其实对稳定性要求很高,如果不能提供一体化的教育平台,很难保证服务体验。
▶︎ 其次,云成本优化
随着互联网红利的消退,降本增效成为各个公司的时代主题。云服务成本是公司除了营销之外靠前的几项之一,是重点要解决的问题。因为选择的是单云,基本被云厂商绑定。很多公司的云成本优化已经不是CTO在处理,而是CFO挂帅。
▶︎ 其三,服务质量
早期,业务刚上云的时候没问题,但随着时间推移,服务的质量是否还能够一如既往,各种需求是否能够及时响应,很多时候要打一个问号。这也能够理解,毕竟人力资源有限,根源还是单一供应商服务的问题。
单云架构解决路径
那么,从行业角度看,关于单云架构会有哪些解决路径呢?
针对单一供应商不可控的问题,其实有两条比较明显的一个思路:
一个思路是:下云,回归IDC。时至今日,拥抱云已经是一个不可争议的主旋律,当然IDC也依然会存在。但像一些大体量公司,比如计算资产有几百万核的企业,选择IDC会更划算,有些公司还会提供公有云的一些服务,但是对于一些相对一般体量的公司,他们选择IDC可能会有几点考虑。
可能公司在云厂商获得的折扣一般,或者是中间有一些捆绑的一些商业因素等等。再或者,有些公司还会出于对自身的一些数据、模型有保护需求,所以去选择了IDC。对很多公司而言,基础设施的掌控能力确实提升了,但是要操心的事情也会更多,机房的风、火、水、电,再比如制冷、消防、防潮、备用电力等所有的问题都需要进行关心。
另外一个思路,是多云架构。也是本文关注的重点,即采用多个供应商解决不可控的问题。多云的定义是,一个公司使用了两个及以上的云IaaS的供应商。泛化来讲啊,广义的来看,混合云其实也属于多云架构。
那么,多云会有一些什么优势呢?
• 1.灾难恢复,当出现单云故障的时候,数据存储不至于不可挽回,可以从其他地方进行恢复。
• 2.故障转移,指的是当云出现故障的时候,通过故障转移,可以使用另外一家云来承接这个服务,从而做到业务不中断。
• 3.成本优化,不管是什么采购,只要有两家及以上供应商,采购方就会有一个充分选择和议价能力,也就避免被供应商锁定。
• 4.数据主权,是指国家或者相关机构对数对服务产生的数据有一定的产权需求,导致企业云基础设施也会受到影响。
• 5.特定服务访问,是指不同云都会有自己的特色服务,一般会出现在PaaS层。比如:各家都有各种各样的数据库、大数据实施方案,但都在某些领域里极具优势,使用多云后就可以集各家之长。
架构模式分析
那么,多云到底是有哪些架构模式呢?是不是就只有一种固定不变的架构模式?答案是否定的,多云有多种架构模式!
▶︎ 主备多云
企业的应用服务在一家云上,用户通过DNS数据沿着网关应用、数据存储这条链路进行流转。忽然有一天,企业出于对数据灾备的一个考虑,将数据存储同步到另外一边云,或者说企业有一些海量的对象数据归档的一些需求,会进行数据备份,选择另外一家在云存储价格上有一定优势的企业。同时,企业还有可能会在这个备份的云上开一些衍生的离线计算,用来进行一些加工处理,比如支持对图片、文件、视频等转码之类的服务。
基于多云架构上述的六个优点,我们看下主备多云有哪些优势。首先看灾难恢复,因为把数据备份到另外一个云上了,所以灾难恢复在数据层面肯定是满分,任何故障都不会对数据造成一个毁灭性影响。但是,对于故障转移却无能为力,因为只把数据存过去了,应用服务其实没有什么变化,所以这块肯定是零分。
▶︎ 弹性多云
基于上述考虑,企业开始考虑一些特色服务。比如:深度归档,或者基于深度归档衍生的一些基于对象存储的一些更丰富的图片处理能力,或者更多弹性计算的能力。这样,企业在原来备份云上的使用会更多,不再仅仅满足备份需求,开始把一些重要服务部署过去,应对流量突增的一些弹性需求。在这种架构下,为了保证需要临时去扩的时候,服务完备,是需要长期做多活。所以在日常的时候,就会有一部分的流量,是在这边这个云进行流转。中间也是通过DNS去进行一个流量的分发。当出现真的一些突增的一些流量、一些非预期的一些流量的时候,弹性的云我就可以做一个计算资源的一个快速的扩容。然后通过DNS或者是网关,将主云无法承载的流量转移到弹性云上。
我们看下在弹性多云这种架构下,各方面表现如何?
基于主备多云,数据完成了多云存储,灾难恢复肯定是满分。因为,企业已经把一些核心的服务部署在了第二家云上,故障转移能力更强了。但因为只把一些新服务部署过来,应对一些弹性流量,一旦主云挂掉,这个弹性云能不能工作,没有准确答案。因为在弹性云上,还是有些服务会依赖主云,这会导致企业迈向下一步。
▶︎ 业务切分多云
其实这个也很好理解,并且现在应该是各家多云里面相对比较主流的一种方式。很多公司都有多个部门,或者因为是个集团型公司,有多个子公司。各部门都有自己相对比较中立的一个云厂商,就形成了一个局面,就是我的一部分业务在一家云上,另一部分业务在其他的云上,用户访问不同的业务,需要通过不同的域名、DNS,两家云结合起来才能支撑公司业务。这种情况下,和之前相反,灾难恢复、故障转移,基本是零分,因为数据、服务其实没有一个备份,没有冗余。如果真的出现问题,就会出现严重的迁移成本。
▶︎ 数据主权多云
不同用户群体通过DNS、路由到不同的云上,其实已经不一样了,每个云上都是一个完整的应用,但是这些数据只是各自这些用户的数据,它其实也是组合起来之后才能是完整的数据。主要使用场景有几种,比如业务出海,不同国家限定了数据,不允许出境,主权只能在这个国家内,基于这个原因会去签订一些相关的云厂商,进而导致出现这么一个数据主权多云。另外,某些像国内的一些私有化交付项目,雇主其实对数据部署在在公有云,或者哪个私有云,是有一定要求的。对于服务的企业而言,其实是想用一份代码去服务多家企业,所以也有可能会出现这样一个数据多云的一个场景。
▶︎ 多活多云
企业将服务等量部署在两家云上,同一份用户它是通过DNS进行分流,分流到不同的云上,完成一个完整的链路,数据存储这里列的是相对比较经典的一个储存模式。当然,随着分布式数据库的完善,也有一些分布式的选型,我们这里先简单讲讲主从模式。在这种架构下,其实因为我的所有应用、所有的数据存储在每一家云上都是有对等的一份儿,所以我的灾难恢复、故障转移特别容易。当出现机房故障的时候,我只去进行一个DNS切换,就又可以正常提供服务了。不同云上都是有完整的服务,只是大家各自的一个占比的流量不同,并且成本比较低,也不太可能会被绑定。
看上去,多活多云是一个特别理想的模式,但在多数应用服务场景下很难实现,而且代价巨大,会引发新的问题。如果我们做不到业务在各自云之间是完整的一个闭环,彼此之间如果还会存在一些跨云、千丝万缕的一些调用依赖的话,故障率很有可能没有减少,而是被增加了。如果两边云的稳定性做得不好,对于业务而言肯定要做冗余差情况下,在两边各部署能够承担百分之百容量的一个服务。这样,成本肯定会增加,因为两边加起来是百分之二百,比之前百分之一百多很多,是巨大的一个浪费,跟初目标相悖。重要的是,运维效率大幅降低,会反作用于稳定性。
所以,在不完备的、多活的方案下,对多云没有等量地做部署,所以不得不需要一次又一次地去演练,通过人肉的方式去保证多云架构的有效性。中间一旦松懈,很有可能就导致耗费巨大精力做的这套架构,在单元故障之前完全没有任何的作用。
作业帮多云建设
作业帮坚定地选择多云多活策略,只有这样,才能达到理想的稳定性、成本收益等。我们生活在云原生时代,K8S相当于把云厂商的北向接口统一了,极大地抹平了多种技术之间的差异,让多云交付相对统一。而云内部是一个完整的闭环,常态的应用调用发生在云内,云间只需要做数据的同步,或者主集群的写流量。当然,会有一些跨云的需求,比如新扩建服务的时候不能一下把所有服务切过去,各业务没有办法做到完整的一致,一定会有先部署的模块,在多云侧也要有一定的集群间发现的能力,尽量把问题域从集群服务降低到集群这个单一的维度,再就是南北向的调度优先使用DNS来进行。
此种背景下,作业帮是如何基于多云架构进行资源调配、服务治理的呢?
从大的架构来看,分为两层:一个是资源层,包含计算、存储、网络等诸多IaaS资源。计算包含CPU、异构计算,存储会有块存储、文件存储、对象存储等等。另一个是应用层,会有各种各样的PaaS应用组件,包括数据存储、安全、消息队列、大数据等等。再往上是各种业务中台、业务线,以Docker+K8S为代表的容器技术,通过容器镜像、作业编排、资源调度、资源管理实现了资源对上层业务的透明。上层业务想要跑得更快,需要一套服务治理体系,以服务发现为基础,包含观察、通信协议、流量管控等方面,这是架构全貌。
具体而言,底层架构,首要能力是网络。这是一切上层互通的一个基础,在基本的一个连通性上,需要各家云厂商之间可以进行互通。我们的工区,不管是北京,还是外地,可以去访问云上的一个内网。服务连通性,其实是基础的一个要求,更高层面的要求是需要网络更加高可用。另外,在所有的网络边界上,会有更强的感知能力和管控能力。至于高可用,其实也并不只针对是云上,也针对工区,作为帮对工区的一个稳定性要求会比较高。
在传统互联网公司,其实工区如果网络出故障,会影响研发,晚提交一会代码,不会对下游业务造成影响,其实这些还是一个相对比较间接的影响。但是作业帮,有几万辅导老师,在学校上课的时候,需要同步做着一些辅导、答疑的一些事情,内网的不稳定会直接影响学习质量,应用的稳定性一定要重点保障。
作业帮整体的网络发展历程梳理如下:
▶︎ 以工区为中心的双云互通
2019年,公司还没有一个正式的网络运维人员,主要方案就是满足连通性,工区需要上云,会从工区直接去连到那个云的IDC,然后工区之间再联通起来,多云也就自然也联通起来了。解决完北京工区和云的互通问题后,对于外地工区,是通过打一个VPN通道,走公网,然后连到了北京的工区,自然也就可以上云了,这套方案让联通性基本得到了满足。
但是,这套方案问题也比较多。首先,在别的可靠性、感知能力上有一些问题。两家云之间是通过工区来进行桥接的。我云上本来是一个IDC级别的可靠性要求,一下子降低到一个楼宇物业的级别,中间但凡临时停个电,服务就可能会出现故障。同时,外地工区上云本质上走的还是一个公网的链路,只不过在上面加上了一个VPN的安全防护,而且防护质量其实并不高。
▶︎ IDC级别的双云互通
如何提升网络的稳定性级别?经过综合对比,包括重点考察了裸纤组网服务,实现端到端铺设组网线路。涉及到传输层面,除了后一公里去接线之外,其实大量的还是去用专线厂商已有的一个城域网。后,以接触点的方式帮企业组成了一张内网。当时,其实只有两家的云厂商,所以终选择的是裸纤的一个方案。我们分析了一下两家云厂商的一个pop点的一个分布,他们其实在亦庄、顺义都有相关的一个pop点,并且离得还比较近,所以我们选择用裸纤的方案将这家云的顺义pop点跟另外一家云的顺义的pop点连起来。在亦庄这边也是同样的,这样就实现了一个IDC级别的一个互通。除此之外,我们也对外地工区上云做了一定的优化。
理想的方案,还是想像北京这边一样,去找一个中立的第三方,然后复用它的一个的骨干网络来进行上云。但对于专线厂商而言呢,他们骨干网的覆盖更多是去覆盖一个比较大的城市,比如华北、华中、华南以及华东的某些点,因为他们毕竟还是做IDC级别的一个互通,没法覆盖到我们的一个外地工区,真正能做到这么密集去覆盖的其实就只有云厂商。因为云厂商本身的业务主体是一个比较大的互联网业务,所以说他们也有这样一个需求,需要更好的一个覆盖,能覆盖到主要的一些省会城市。后,我们选择的方案是,借助云厂商的一个骨干网络,进行一个外地工区上云的联通,访问我们的内网服务。同时,就原有的那个Ipsec-VPN通道,还是进行了一个保留,作为一个备用的一个链路。
▶︎ 多云组网
之后,我们新的问题就随之而来,原来之前是两云,就现在我们需要去接入新的第三家云,就是因为各种合作的一些原因,我们的网络需要进行怎样的调整呢?另外,在之前方案下,感知和管控能力其实并没有提升,相反还是有一些降低了。在早的那版方案里,虽然走的是工区的网络,但是工区毕竟有可控的交换机,可以做管控、感知,但是现在完全采用裸纤的方案,是两家云厂商直接点到点的一个连接,我们的感知管控能力其实是丧失了,因为中间并没有我们的一个设备。
基于上述这些问题,作业帮对网络进行了第三代演化,实现多云之间的优化。新加一个云厂商,作业帮原有的网络拓扑其实并不适用了。之前讲到专项供应商,提供了三种方案。作业帮分析了一下多云组网的方案,其实更适合这种需要接入两家以上的一个点。在新的方案下面,也是有各种各样的高可靠要求,比如从供应商的一个连接上,供应商自身的一些城域网会有一些冗余,有故障的抗干扰,以及一些弹性能力。除此外,也做了一些双联路,不仅使用了两家不同的供应商,每家供应商去接入的地域其实也不一样,还是一边是从亦庄,一边是在顺义方向进行接入,整个链路之间实现了链路的负载均衡,当单条链路出现故障的时候,从协议层面可以实现一个秒级的自动切换,并不需要人工的一个干预。在这样的网络架构下,供应商跟云厂商的网络设备是缺乏管控状态,作业帮在专业供应商这边去租了相关设备实现了感知跟管控能力,在后面像云的一些故障演练、跨云的流量分析上,起了一些相对比较重要的一些作用。
其次,是计算。计算是横在多云架构上 “一块难啃的骨头”。在单云的时候,其实如果我们没有统一个机型规划的话,看到云上有什么样的机器,我就开什么样的机器。云上的机型特别多,2c、4c、8c、16c、32c、48c、96c都有。然后,那个内存比有1:2、1:4、1:6、1:8,两项一组合,就会形成一个大的机型列表,可能会有几十甚至上百种。这个时候,一旦去做多云,再乘上多云的一个数量,就是对运维而言是一个巨大的灾难。这么多的机型如何我去做一一的适配以及更好的维护?
面对这个问题,终解法是要去定义一个机型的一个规范,从这些发展的机型里面去进行梳理,定义各家云主流的一些规格。首先,让所有的业务尽量往一个规格上靠拢,各业务大规格上云把裸金属作为一个主力的机型,比如像在容器里面,让容器的宿主都使用这种大规格的裸金属。一方面既可以减少集群中管理的节点数量,另一方面也是缩减机型的一个诉求。
早期的数据存储,会优先让其使用这种裸金属,然后在其上进行一个混部,像MySQL跟Redis也都是这么做的。除此之外,有些真是主力机型满足不了,比如像各种各样对网络吞吐要求比较高的就是流媒体的机型,某些特定的采买的一些服务的机器,这种做不了。
除了这些特定的服务以及我们收敛的主机机型之外,虚机肯定还是会存在,但是不能像之前一样任其发散。作业帮选择两款作为选择,选项就是8核16G、32核64G,规格相对适中,跨度也并不是特别大,能涵盖百分之九十五以上的虚机需求。如果再有一些其他需求的话,我们其实建议其迁到容器。
再到下一个阶段,随着部分服务的一些资源使用量越来越多,比如超过了10000核,就是像数据库或者Redis结合降本增效的一个背景,其实终发现,要努力的方向要么是软件,要么是硬件。在硬件上其实更多的就是在机型上去下功夫。比如像DB的机器,其实使用不了那么多的一个CPU,我需要更多的内存、更多的磁盘,我们就去使用各种大量的一些专用的大磁盘的一些机器。而在Redis场景,选用了傲腾来实现降本。
计算生命周期管理
接下来的问题是,计算生命周期管理如何来做?如何通过自动化、平台化去提升多云效率?
首先,有了机型之后,也不是直接去购买机器,中间还缺少一环网络。因为,所有的资源其实都被划分到一个个网络的安全域里面,比如有测试域、生产域、管理域、三方服务域等等,每个域里面又会有直网的网段划分。如果我们将这个概念一股脑地抛给研发,其实代价比较高,也不太利于后续的升级迭代。
我们把机型结合网络划分,再变成一个个套餐,这样业务和研发就可以直接基于套餐来进行机器的购买。交付到业务之后,业务再做一些初始化,机器在运行的过程中对上层的应用提供一个稳定性支撑,当机器故障或者需要缩容的时候,就走销毁流程。在这个生命周期里面,财务是重要一环。财务人员会有两个账单,一个是按照云厂商的各种计费规则,包年包月、按量计费等算出的一个账单流水,用于跟云厂商对账,然后进行一个对公的付款;另外一个账单,是研发部门的一个用量视图。
服务治理:注册发现、通信、感知、管控
多云中,下游对上游提供的服务的名字要一致,这样整个部署拓普就对业务进行透明了,便于运维去调整部署。这块有一个新的挑战,就是多云跟容器是同步化来做,如何合拢呢?需要一个注册发现能力!基于这块的一个进阶的要求,就是虚机和容器如何去解决互相发现通信的一个问题。更理想一点,服务对外能不能提供一致的名字,有统一的控制面?
作业帮通过云原生的方式服务治理,两个服务访问直接通过Service域名实现单云、多云的互通。当然,容器化进展也不是一蹴而就,比如:没法在一个时间点同时从虚机变到容器;现在的做法是,通过数据打通来完成整个控制面的打通。
除了上述这些基础能力,多云架构改造还涉及PaaS层的数据存储、流量调度等问题,包括SaaS层的改造,这里不逐一介绍。
从终结果来看,随着多云架构的不断迭代,收益也是持续上升状态。核心模块完成多云部署后,公司实现了60%的收益;核心模块+一般模块完成多云部署,多云收益是90%;核心模块+一般模块完成容器化改造,容器收益近乎;全部完成多云部署,多云收益。大体步骤是,先容器化再多云,先进行基础建设迁移,再完成边缘模块、一般模块的迁移,后是核心模块迁移。
结论
走到今天,可以肯定的方向是,未来应用服务一定是的云原生。虽然作业帮现在已经完成90%的改造,比如数据存储、外呼、检索都是容器化方式,但距离还有一些距离,后续计划会对流媒体等一些服务进行升级。另外,基于多云的云边协同,也是重要探索方向,可以让业务服务不受云、机房等基础设施能力的限制,比如业务出海会基于云边协同达到更好的收益目标。后是,多云数据存储目前还是主从为为主,未来会考虑分布式数据库单元化设施的进一步完备。