2021年5月

个人博客请访问 http://www.x0100.top  


机房迁移是一个很大的动作:


15年在58同城实施过一次(“逐日”项目),几千台物理机,从IDC迁到了腾讯的天津机房,项目做了10个多月,跨所有的部门,与所有的业务都相关;


16年在58到家又实施了一次(“凌云”项目),几百台虚拟机,从IDC迁到阿里云,前后大概一个季度的时间,也是所有技术部门都需要配合的一个大项目。


 


“单机房架构-全连”

要说机房迁移,先来看看被迁移的系统是一个什么样的架构。



上图是一个典型的互联网单机房系统架构:


(1)上游是客户端,PC浏览器或者APP;


(2)然后是站点接入层,为了面对高流量,保证架构的高可用,站点冗余了多份;


(3)接下来是服务层,服务层又分为与业务相关的业务服务,以及业务无关的基础服务,为了保证高可用,所有服务也冗余了多份;


(4)底层是数据层,数据层又分为缓存数据与数据库;


 


至于为什么要做分层架构,不是今天的重点,不做展开讨论,这是一个典型的互联网单机房分层架构:所有的应用、服务、数据是部署在同一个机房,这个架构有的一个关键词,叫做“全连”:


(1)站点层调用业务服务层,业务服务复制了多少份,上层就要连接多少个服务;


(2)业务服务层调用基础服务层,基础服务复制了多少份,上层就要连多少个服务;


(3)服务层调用数据库,从库冗余了多少份,上层就要连多少个从库;


 


比如说,站点接入层某一个应用有10台机器,业务服务层某一个服务有8层机器,那肯定是上游的10台会与下游的8台进行一个全相连的。系统架构的可用性保证,负载均衡保证,是服务的连接池去做的。不仅仅接入层连接业务服务层是这样,业务服务层连接基础服务层,服务层连接数据库也都是这样,这就是所谓的“全连”。


 


“机房迁移的目标是平滑”

单机房架构的特点是“全连”,那么机房迁移我们是要做一个什么样的事情呢?先看这张图:



之前单机房架构部署在机房A内,迁移之后仍然是单机房架构,只是换了一个B机房,做完这个迁移,有什么好的方案?最容易想到的一个方案,把所有服务在新机房全部搭一套,然后流量切过来了。


 


当系统有几千台机器,有非常非常多的业务的时候,这是一种“不成功便成仁”的方案。做技术的都知道,设计时要考虑回滚方案,如果只有上线方案而没有回滚方案,这便是一个“不成功便成仁”的方案,根据经验,不成功便成仁的操作结果,往往就“便成仁”了。


 


最重要的是,全量搭建一套再流量切换,数据层你怎么搭建一套?怎么切?数据层原来都在A机房,B机房还没有全量的数据,是没办法直接切的。要做一个数据同步的方案,最简单的,停两个小时服务,把数据从旧机房导到新机房,数据导完流量再切过去,这是一个数据迁移的简单方案。这个方案对业务有影响,需要停止服务,这个是无法接受的,何况像58同城一样有两千多台机器,无限多的数据库实例,无限多的数据表的时候,停服务迁移数据根本是不可能的。


 


所以,机房迁移的难点,是“平滑”迁移,整个过程不停服务,整体迁移方案的目标是:


(1)可以分批迁移;


(2)随时可以回滚;


(3)平滑迁移,不停服务;


 


“伪多机房架构-同连”

如果想要平滑的迁移机房,不停服务,在10个月的逐步迁移过程中,肯定存在一个中间过渡阶段,两边机房都有流量,两边机房都对外提供服务,这就是一个多机房的架构了。


 


多机房架构是什么样的架构呢?刚刚提到了单机房架构,上层连中层,中层连下层,它是一个全连的架构,能不能直接将单机房的全连架构套用到多机房呢?在另一个机房部署好站点层、服务层、数据层,直接使用“全连”的单机房架构,我们会发现:会有非常多跨机房的连接


(1)站点层连接业务服务层,一半的请求跨机房


(2)业务服务层连接基础服务层,一半的请求跨机房


(3)基础服务层连数据层(例如从库),一半的请求跨机房


 


大量的跨机房连接会带来什么样的问题呢?


我们知道,同机房连接,内网的性能损耗几乎可以忽略不计,但是一旦涉及到跨机房的访问,即使机房和机房之间有专线,访问的时延可能增加到几毫秒(跟几房间光纤距离有关)。


 


用户访问一个动态页面,需要用到很多数据,这些数据可能需要10次的业务服务层调用,业务服务层可能又有若干次基础服务层的调用,基础服务层可能又有若干次数据层的调用,假设整个过程中有20次调用,其中有一半调用跨机房,假设机房之间延迟是5毫秒,因为跨机房调用导致的请求迟延就达到了50毫秒,这个是不能接受的。


 


因此,在多机房架构设计时,要尽量避免跨机房调用(避免跨机房调用做不到,也要做到“最小化”跨机房调用),会使用“同连”的系统架构。



“同连”也很好理解,在非必须的情况下,优先连接同机房的站点与服务:


(1)站点层只连接同机房的业务服务层;


(2)业务服务层只连接同机房的基础服务层;


(3)服务层只连接同机房的“读”库;


(4)对于写库,没办法,只有跨机房读“写”库了;


 


这个方案没有完全避免跨机房调用,但其实它做到了“最小化”跨机房调用,写主库是需要跨机房的。但互联网的业务,99%都是读多写少的业务,例如百度的搜索100%是读业务,京东淘宝的电商99%的浏览搜索是读业务,只有下单支付是写业务,58同城99%帖子的列表详情查看是读业务,发布帖子是写业务,写业务比例相对少,只有这一部分请求会跨机房调用。


 


迁移机房的过程使用这样一个多机房的架构,最大的好处就是,除了“配置文件”,整个单机房的架构不需要做任何修改,这个优点是很诱人的,所有的技术部门,所有的业务线,只需要配合在新机房部署应用与服务(数据库是DBA统一部署的),然后使用不同的配置文件(如果有配置中心,这一步都省了),就能实现这个迁移过程,大大简化了迁移步骤。


 


这个方案当然也有它的不足:


(1)跨机房同步数据,会多5毫秒(举个栗子,不要叫真这个数值)延时(主从本来会有延时,这个延时会增大),这个影响的是某一个机房的数据读取;


(2)跨机房写,会多5毫秒延时,这个影响的是某一个机房的数据写入,当然这个写请求比例是很小的;


 


这个“同连”架构非常适用于做机房迁移,当然也可以用作多机房架构,用作多机房架构时,还有一个缺点:这个架构有“主机房”和“从机房”的区分。


 


多机房架构的本意是容机房故障,这个架构当出现机房故障时,例如一个机房地震了,把入口处流量切到另一个机房就能容错,不过:


(1)挂掉的是不包含数据库主库的从机房,迁移流量后直接容错;


(2)挂掉的是包含数据库主库的主机房,只迁移流量,其实系统整体99%的读请求可以容错,但1%的写请求其实会受到影响,此时需要人工介入,将从库变为主库,才能完全容错。这个过程只需要DBA介入,不需要所有业务线上游修改(除非,除非,业务线直接使用的IP连接,这个,我就不说什么了)。


 


也正是因为这个原因,在机房故障的时候,有一定概率需要少量人工介入,才能容100%的机房故障,因此这个架构才被称为“伪多机房架构”,还不是完全的“多机房多活”架构。


 


“自顶向下的机房迁移方案”

话题收回来,机房迁移的过程中,一定存在一个中间过渡阶段,两边机房都有流量,两边机房都对外提供服务的多机房架构。具体到机房的逐步迁移,又是个什么步骤呢?通常有两种方案,一种是自顶向下的迁移,一种是自底向上的迁移,这两种方案在58到家和58同城分别实行过,都是可行的,方案有类似的地方,也有很多细节不一样,因为时间关系展开说一种,在58到家实施过的“自顶向下”的机房迁移方案,整个过程是平滑的,逐步迁移的,可回滚的,对业务无影响的。


 


“站点与服务的迁移”



迁移之前当然要做一些提前准备,新机房要准备就绪,专线要准备就绪,这个是前提。


 


自顶向下的的迁移,最先迁移站点层和服务层:先在新机房,把站点层和服务层搭建好,并做充分的测试(此时数据层比如说缓存和数据库还是在原来的机房)。测试,测试,测试,只要流量没有迁移,在新机房想怎么玩都行,新机房准备的过程中,要注意“同连”,原有机房的配制文件是完全不动的,肯定也是“同连”。


 


站点层与服务层的迁移,也是一个业务一个业务的逐步迁移的,类似蚂蚁搬家。充分的测试完一个业务的站点层和服务层之后,为了求稳,先切1%的流量到新机房,观察新机房的站点与服务有没有异常,没有问题的话,再5%,10%,20%,50%,100%的逐步放量,直至第一波蚂蚁搬完家。


 


第一个业务的站点和服务迁移完之后,第二个业务、第三个业务,蚂蚁继续搬家,直至所有的业务把站点层和服务层都全流量的迁移到新机房。


 


在整个迁移的过程中,任何一个业务,任何时间点发现有问题,可以将流量切回,旧机房的站点、服务、配置都没有动过,依然能提供服务。整个迁移步骤,是比较保险的,有问题随时可以迁回来。


 


“缓存的迁移”



站点层和服务层迁移完之后,接下来我们迁数据层,数据层又分为缓存层和数据库层,先迁缓存。


 


经过第一步的迁移,所有的入口流量都已经迁到了新的机房(当然旧机房的站点和服务还是不能停,只要旧机房不停,任何时间点出问题,最坏的情况下流量迁回来),接下来迁移缓存,先在新机房要搭建好缓存,缓存的规模和体量与旧机房一样大。


 


流程上仍然是蚂蚁搬家,按照业务线逐步的迁缓存,使用同连的方式。这个缓存切换的步骤非常的简单:运维做一个缓存内网DNS的切换(内网域名不变,IP切到新机房),并杀掉原有缓存连接,业务线不需要做任何修改,只需要配合观察服务。运维杀掉原有缓存连接之后,程序会自动重连,重连上的缓存就是新机房的缓存了,bingo,迁移完毕。


 


这里要注意几个点:


(1)有些公司缓存没有使用内网域名,而是采用IP直连的话,则需要业务层配合,换新机房IP重启一下即可(如果是IP直连,说明这个架构还有改进的空间哟);


(2)这个操作尽量选在流量低峰期,旧缓存中都是热数据,而新缓存是空数据,如果选在流量高峰期,缓存切换之后,短时间内可能会有大量请求透传到数据库上去,导致数据库压力过大;


(3)这个通用步骤,适用于允许cache miss的业务场景,如果业务对缓存有高可用的要求,不允许cache miss,则需要双写缓存,或者缓存使用主从同步的架构。大部分缓存的业务场景都是允许cache miss的,少数特殊业务使用特殊的方案迁移。


 


缓存的迁移也是按照业务线,一步步蚂蚁搬家式完成的。在迁移过程中,任何一个业务,任何时间点发现有问题,可以将流量切回原来的缓存。所以迁移的过程中,不仅是站点层和服务层,旧机房的缓存层也是不停服务的,至少保证了流量迁回这个兜底方案。


 


“数据库的迁移”


站点层,服务层,缓存层都迁移完之后,最后是数据库的迁移。



数据库还是在旧机房,其他的缓存,服务,站点都迁移到新机房了,服务通过专线跨机房连数据库。


 


如何进行数据库迁移呢,首先肯定是在新机房搭建新的数据库,如果是自建的IDC机房,需要自己搭建数据库实例,58到家直接用的是阿里云的RDS。


 


搭建好数据库之后,接下来进行数据同步,自建机房可以使用数据库MM/MS架构同步,阿里云可以使用DTS同步,DTS同步有一个大坑,只能使用公网进行同步,但问题也不大,只是同步的时间比较长(不知道现能通过专线同步数据了吗?)。


 


数据库同步完之后,如何进行切换和迁移呢?能不能像缓存的迁移一样,运维改一个数据库内网DNS指向,然后切断数据库连接,让服务重连新的数据库,这样业务服务不需要改动,也不需要重启,这样可以么?


这个方式看上去很不错,但数据库的迁移没有那么理想:


第一,得保证数据库同步完成,才能切流量,但数据同步总是有迟延的,旧机房一直在不停的写如数据,何时才算同步完成呢?


第二,只有域名和端口不发生变化,才能不修改配置完成切换,但如果域名和端口(主要是端口)发生变化,是做不到不修改配置和重启的。举个例子,假设原有数据库实例端口用了5858,很吉利,而阿里云要求你使用3200,就必须改端口重启。


 


所以,我们最终的迁移方案,是DBA在旧机房的数据库设置一个read only,停止数据的写入,在秒级别,RDS同步完成之后,业务线修改数据库端口,重启连接新机房的数据库,完成数据层的切换。


 



经过上述站点、服务、缓存、数据库的迁移,我们的平滑机房的目标就这么一步步完成啦。


 


总结与问答

四十分钟很短,focus讲了几个点,希望大家有收获。


做个简要的总结:


(1)互联网单机房架构的特点,全连,站点层全连业务服务层,业务服务层全连的基础服务层,基础服务层全连数据库和缓存;


(2)多机房架构的特点,同连,接入层同连服务层,服务层同连缓存和数据库,架构设计上最大程度的减少跨机房的调用;


(3)自顶向下的机房迁移方案:先进行站点接入层、业务服务层和基础服务层的迁移,搭建服务,逐步的迁移流量;然后是缓存迁移,搭建缓存,运维修改缓存的内网DNS指向,断开旧连接,重连新缓存,完成迁移;最后数据库的迁移,搭建数据库,数据进行同步,只读,保证数据同步完成之后,修改配置,重启,完成迁移。整个过程分批迁移,一个业务线一个业务线的迁移,一块缓存一块缓存的迁移,一个数据库一个数据库的迁移,任何步骤出现问题是可以回滚的,整个过程不停服务。


 


主持人:讲的很细致,大家有什么问题吗,可以提一些问题,可以举手示意我。


提问:做数据迁移的时候,因为您讲的数据中心的都是在同一个老机房,同时又在做同步,我就在想这个数据库的压力是不是特别大。


沈剑:非常好的问题,这个地方一方面要考虑压力,更重要的是考虑跨机房的专线,风险最大的是在带宽这一部分,你在第一步迁移完之后,其实所有的缓存,数据库用其实都是跨机房的,都是通过专线去走的,这个专线带宽是需要重点考虑与评估的,数据库的压力其实还好。


 


提问:我想请教一个问题,你这个流量切换的过程中,有测试性的阶段还是直接切过去的。


沈剑:在切流量之前,肯定是有测试的,在新机房将服务搭建,在切换流量之前,测试的同学需要进行回归,回归的过程可以提前发现很多问题。逐步的切流量也是为了保证可靠性,我们不是一次性百分之百流量都切过来,先切1%的流量过来,观察服务没有问题,再逐步增大流量切换。

————————————————

版权声明:本文为CSDN博主「HelloWorld搬运工」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/wufaliang003/article/details/78725400


做为中小站长来说,一般购买了云服务器之后,可以自己在云服务器ECS上搭建数据库,并不需要另外购买云数据库。但是当网站的数据量规模已经大到一定程度之后,这种应用与数据库不分离的模式就会显露弊端了,会出现服务器反应迟缓卡顿现象。


 

云数据库结合云服务器使用,布局站库分离的网站,这样的站库分离模式速度更快,也减少了数据安全风险,更降低了运营成本。云数据库RDS提供高可用、高可靠、高安全、可扩展的托管数据库服务,性能等同于商业数据库,但是价格相比ECS自建数据库,仅需约1/3,相比自购服务器搭建数据库,仅需约1/10。云数据库与自建数据库的成本比较,请看以下对比表:

价格对比

 

费用云数据库RDSECS自建数据库自购服务器搭建数据库

硬件费用和备品配件费用RDS实例的费用。例如,2 CPU、4 GB内存、存储空间 100 GB(IOPS能力可达到6800)的实例费用是8000元/年。至少需要2台ECS实例作为主备实例。2台2 CPU、4 GB内存、存储空间 100 GB(IOPS能力可达到6800)的ECS实例费用是6800元/年。

至少需要2台数据库服务器。每台IOPS能力达到6800的服务器费用大约是8000元。

1台用于连接前端Web服务器的内网交换机(便宜的1U非网管交换机为1000元左右)。

后期硬件损坏和更换至少还要消耗30%费用。

硬件花费:(8000 × 2 + 1000)× 130% = 22100元。

每年费用:22100元/3 = 7366元(硬件按照3年折旧计算)。


机房托管费用服务商负责,无需付费。服务商负责,无需付费。1U机柜空间托管费用为3000元/年,共有2台1U服务器和1台1U内网交换机需要计费,机房托管费用:3000 × 3 = 9000元。

带宽费用

同一地域内,ECS和RDS可以通过内网互通,且不收取费用。

若在不同地域,ECS和RDS可以通过外网互通,需收取外网流量费用,详细收费标准请参见云数据库RDS详细价格信息。

同一地域内,ECS实例之间可以通过内网互通,不收取费用。

若在不同地域,ECS实例之间可以通过外网互通,需收取外网流量费用,详细收费标准请参见公网带宽计费方式。

只用于内网,不产生公网费用。

数据库运维工程师费用数据库维护由服务商负责,无人员成本。1个初级DBA工程师月薪至少5000/月,假设当前项目占用该工程师30%的工作量,则人员成本为5000 × 12× 30% = 18000元。1个初级DBA工程师月薪至少5000/月,假设当前项目占用该工程师30%的工作量,则人员成本为5000 × 12× 30% = 18000元。

每年总费用8000元/年24800元/年34366元/年

RDS MySQL与自建数据库对比优势

 

对比项RDS MySQLECS自建自购服务器搭建数据库

性价比

弹性资源。

ALISQL提供各种特性功能,提升用户使用感受。

备份有一半实例空间免费。

公网流量免费。

免费使用自带的域名。

更新速度快,紧跟MySQL最新版本。

弹性资源。

开源版无性能优化。

备份空间独立收费。

公网流量收费。

一次投入的沉没成本大。

开源版无性能优化。

需要独立准备备份资源,成本极高。

公网流量收费,域名费用高。

可用性

基础版约15分钟即可完成故障转移。

高可用版和集群版提供自研高可用系统,实现30秒内故障恢复。

只读实例自动实现负载均衡。

读写分离使用方便。

未来会推出分析节点,满足分析型场景需求。

基础版约30分钟完成故障转移。

需要单独购买高可用系统。

需要单独实现或者购买负载均衡服务。

分析型场景需要与分析型数据库结合,搭建难度大、成本高。

单机实例,少则两小时,多则等待配货数周。

需要单独购买高可用系统。

需要单独实现或者购买负载均衡设备。

分析型场景需要与分析型数据库结合,搭建难度大、成本高。

可靠性

数据可靠性高,自动主备复制、数据备份、日志备份等。

MySQL 5.6三节点企业版,实现RPO(Recovery Point Object)=0。

MySQL 5.7三节点企业版(MGR),实现RPO=0、RTO(Recovery Time Objective) < 1分钟。

在好的架构下才能实现高可靠性。

实现RPO=0的成本极高,需要单独购买研发服务。

数据可靠性一般,取决于单块磁盘的损害概率。

实现RPO=0的成本极高,需要单独购买研发服务。

易用性

自动化备份恢复系统,支持按时间点恢复、单库备份恢复等,流式备份对实例性能影响小。

自动化监控告警系统,支持秒级监控,覆盖实例和数据库所有性能指标,支持短信、邮箱、旺旺、钉钉等通道,且根据消费有大额度的免费短信数量。

支持异地容灾。

支持一键版本升级。

无自动备份系统,流式备份能力需要单独实现,实现按时间点恢复功能成本高。

需要单独购买监控系统,在云监控中配置告警系统。

技术实现难度极大。

版本升级成本高。

无自动备份系统,流式备份能力需要单独实现,实现按时间点恢复功能成本高。

需要单独购买或配置监控系统,通道较少,成本较高。

异地数据中心成本极高,技术实现难度也大,很难实现异地容灾。

版本升级成本高。

性能

MySQL的本地SSD盘实例性能极佳。

MySQL的ESSD性能较SSD提升显著。

增加只读实例之后性能强劲且负载均衡。

CloudDBA提供高级优化能力。

SQL洞察满足大部分监控及性能优化数据库场景。

ECS本地盘意味着降低数据可靠性,采用云盘需要规划架构,成本支出较大。

基于ESSD的ECS自建MySQL性能低于基于ESSD的RDS MySQL性能。

实现集群版的难度较高,咨询成本较高,维护成本极高。

依赖资深DBA,支出大,受制于人。

比云计算硬件更新速度慢,性能一般都会低于云数据库。

难以实现计算和存储分离,若使用高端存储实现计算和存储分离,动辄需要数千万支出。

实现集群版的难度较高,咨询成本较高,维护成本极高。

依赖资深DBA,支出大,受制于人。

安全

事前防护:白名单、安全组、专有网络隔离。

事中保护:连接链路加密、数据落盘加密(BYOK覆盖多种存储介质)。

事后审计:SQL洞察、历史事件。

事前防护:白名单、安全组、专有网络隔离。

事中保护:需要单独实现连接链路加密和数据落盘加密,BYOK密钥轮转难度大,咨询成本较高。

事后审计:审计困难,需要单独保存SQL日志。

事前防护:白名单和专有网络隔离的咨询成本较高。

事中保护:需要单独实现连接链路加密和数据落盘加密,BYOK密钥轮转难度大,咨询成本较高。

事后审计:审计困难,需要单独保存SQL日志。

RDS SQL Server与自建数据库对比优势

 

对比项RDS SQL ServerECS自建自购服务器搭建数据库

性价比

弹性资源。

WEB版性价比极高。

备份有一半实例空间免费。

公网流量免费。

弹性资源。

不可使用WEB版。

备份空间独立收费。

公网流量收费。

一次投入的沉没成本大。

不可使用WEB版。

需要独立准备备份资源,成本极高。

公网流量收费,域名费用高。

可用性

基础版约15分钟即可完成故障转移。

高可用版和集群版提供自研高可用系统,实现30秒内故障恢复。

集群版的只读实例自动实现负载均衡。

集群版的读写分离使用方便。

基础版约30分钟完成故障转移。

需要单独购买高可用系统。

需要单独实现或者购买负载均衡服务。

单机实例,少则两小时,多则等待配货数周。

需要单独购买高可用系统。

需要单独实现或者购买负载均衡设备。

可靠性

数据可靠性高,自动主备复制、数据备份、日志备份等。

集群版可实现RPO(Recovery Point Object)=0。

在好的架构下才能实现高可靠性。

实现RPO=0的成本极高,需要单独购买研发服务。

数据可靠性一般,取决于单块磁盘的损害概率。

实现RPO=0的成本极高,需要单独购买研发服务。

易用性

自动化备份恢复系统,支持按时间点恢复、单库备份恢复等,流式备份对实例性能影响小。

自动化监控告警系统,支持秒级监控,覆盖实例和数据库所有性能指标,支持短信、邮箱、旺旺、钉钉等通道,且根据消费有大额度的免费短信数量。

即将支持异地容灾。

无自动备份系统,流式备份能力需要单独实现,实现按时间点恢复功能成本高。

需要单独购买监控系统,在云监控中配置告警系统。

技术实现难度极大。

无自动备份系统,流式备份能力需要单独实现,实现按时间点恢复功能成本高。

需要单独购买或配置监控系统,通道较少,成本较高。

异地数据中心成本极高,技术实现难度也大,很难实现异地容灾。

性能

SQL Server 2008 R2的本地SSD盘实例性能极佳,SQL Server 201x版本新计算存储分离架构可享受硬件红利 。

SQL Server的ESSD性能较SSD提升显著。

增加只读实例之后性能强劲且负载均衡。

CloudDBA提供高级优化能力。

ECS本地盘意味着降低数据可靠性,采用云盘需要规划架构,成本支出较大。

基于ESSD的ECS自建SQL Server性能低于基于ESSD的RDS SQL Server性能。

实现集群版的难度较高,咨询成本较高,维护成本极高。

依赖资深DBA,支出大,受制于人。

比云计算硬件更新速度慢,性能一般都会低于云数据库。

难以实现计算和存储分离,若使用高端存储实现计算和存储分离,动辄需要数千万支出。

实现集群版的难度较高,咨询成本较高,维护成本极高。

依赖资深DBA,支出大,受制于人。

安全

事前防护:白名单、专有网络隔离。

事中保护:连接链路加密、数据落盘加密。

事后审计:SQL审计(数据库审计)、历史事件。

微软安全更新,阿里技术兜底。

事前防护:白名单、安全组、专有网络隔离。

事中保护:需要单独实现连接链路加密和数据落盘加密,咨询成本较高。

事后审计:审计困难,需要单独保存SQL日志。

事前防护:白名单和专有网络隔离的咨询成本较高。

事中保护:需要单独实现连接链路加密和数据落盘加密,咨询成本较高。

事后审计:审计困难,需要单独保存SQL日志。

法律

附带License,无法律风险。

即将支持自带License,降低整体成本支出。

只有单独购买License。只有单独购买License,否则法律风险极大。

RDS PostgreSQL与自建数据库对比优势

 

对比项RDS PostgreSQLECS自建自购服务器搭建数据库

性价比

弹性资源。

内核优化,提供各种特性功能,提升用户使用感受。

备份有一半实例空间免费。

公网流量免费。

免费使用自带的域名。

更新速度快,紧跟PostgreSQL最新版本。

弹性资源。

开源版无性能优化。

备份空间独立收费。

公网流量收费。

一次投入的沉没成本大。

开源版无性能优化。

需要独立准备备份资源,成本极高。

公网流量收费,域名费用高。

可用性

基础版约15分钟即可完成故障转移。

高可用版提供自研高可用系统,实现30秒内故障恢复。

只读实例自动实现负载均衡。

基础版约30分钟完成故障转移。

需要单独购买高可用系统。

需要单独实现或者购买负载均衡服务。

单机实例,少则两小时,多则等待配货数周。

需要单独购买高可用系统。

需要单独实现或者购买负载均衡设备。

可靠性

数据可靠性高,自动主备复制、数据备份、日志备份等。

支持设置保护级别,最高RPO=0。

在好的架构下才能实现高可靠性。

实现RPO=0的成本极高,需要单独购买研发服务。

数据可靠性一般,取决于单块磁盘的损害概率。

实现RPO=0的成本极高,需要单独购买研发服务。

易用性

自动化备份恢复系统,支持按时间点恢复、单库备份恢复等,流式备份对实例性能影响小。

自动化监控告警系统,覆盖实例和数据库所有性能指标,支持短信、邮箱、旺旺、钉钉等通道,且根据消费有大额度的免费短信数量。

无自动备份系统,流式备份能力需要单独实现,实现按时间点恢复功能成本高。

需要单独购买监控系统,在云监控中配置告警系统。

无自动备份系统,流式备份能力需要单独实现,实现按时间点恢复功能成本高。

需要单独购买或配置监控系统,通道较少,成本较高。

性能

PostgreSQL的本地SSD盘实例性能极佳。

PostgreSQL的ESSD性能较SSD提升显著。

增加只读实例之后性能强劲且负载均衡。

CloudDBA提供高级优化能力。

SQL审计(数据库审计)满足大部分监控及性能优化数据库场景。

ECS本地盘意味着降低数据可靠性,采用云盘需要规划架构,成本支出较大。

基于ESSD的ECS自建PostgreSQL性能低于基于ESSD的RDS PostgreSQL性能。

依赖资深DBA,支出大,受制于人。

比云计算硬件更新速度慢,性能一般都会低于云数据库。

难以实现计算和存储分离,若使用高端存储实现计算和存储分离,动辄需要数千万支出。

依赖资深DBA,支出大,受制于人。

安全

事前防护:白名单、安全组、专有网络隔离。

事中保护:连接链路加密、云盘加密。

事后审计:SQL审计(数据库审计)、历史事件。

事前防护:白名单、安全组、专有网络隔离。

事中保护:需要单独实现连接链路加密。

事后审计:审计困难,需要单独保存SQL日志。

事前防护:白名单和专有网络隔离的咨询成本较高。

事中保护:需要单独实现连接链路加密。

事后审计:审计困难,需要单独保存SQL日志。

综合上面的对比表格,尊托云数给大家总结一下云数据库与传统自建数据库的对比如下:


1.       服务可用性:    在服务可用性方面,云数据库RDS是99.95%可用的;而在自购服务器搭建的传统数据库服务中,需自行保障, 自行搭建主从复制,自建RAID等。 


2.       数据可靠性:    对数据的可靠性来说,云数据库RDS是保证99.9999%可靠的;而在自购服务器搭建的传统数据库服务中,需自行保障, 自行搭建主从复制,自建RAID等。


3.       系统安全性:    云数据库RDS可防DDoS攻击,流量清洗,能及时有效地修复各种数据库安全漏洞,而在自购服务器搭建的传统数据库,则需自行部署,价格高昂,同时也需自行修复数据库安全漏洞。


4.       数据库备份:   云数据库RDS可自动为数据库进行备份,而自购服务器搭建的传统数据库需自行实现,同时需要寻找备份存放空间以及定期验证备份是否可恢复。


5.       软硬件投入:   云数据库RDS无软硬件投入,并按需付费;而自购服务器搭建的传统数据库服务器成本相对较高,对于SQL Server需支付许可证费用。


6.       系统托管:    云数据库RDS无需托管费用,而自购服务器搭建的传统数据库每台2U服务器每年超过5000元(如果需要主从,两台服务器需超过10000元/年)。


7.       维护成本:    云数据库RDS无需运维,而自购服务器搭建的传统数据库需招聘专职DBA来维护,花费大量人力成本。


8.       部署扩容:    云数据库RDS即时开通,快速部署,弹性扩容,按需开通,而自购服务器搭建的传统数据库需硬件采购、机房托管、部署机器等工作,周期较长。


9.       资源利用率:    云数据库RDS按实际结算,100%利用率,而自购服务器搭建的传统数据库需考虑峰值,资源利用率很低。


现在大的云计算服务商都有提供云数据库产品,比如:腾讯云云数据库、阿里云云数据库、华为云云数据库等等(正在进行的品牌云数据库1折抢购活动可进入尊托云数:9i0i.com了解详情)。大型网站应用有必要购买云数据库,有利于网站的健康稳定运营及长期发展。一般需要云数据库的行业应用场景主要有:电商/金融类网站、游戏数据缓存、大数据计算,连接大数据存储、计算和可视化引擎等。

————————————————

版权声明:本文为CSDN博主「xtyly1」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/xtyly1/article/details/107154098/


作者:华为云开发者社区
链接:https://www.zhihu.com/question/19656397/answer/492063096
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

云服务器和传统服务器的区别主要是:

云服务器是实现软硬件解耦的,通常是部署在虑拟化平台之上的,对外提供的是一个服务,用户可以像使用自来水一样方便来使用,实现一个按需收费的特点。而传统服务器软件是强依赖于硬件设备的,用户需一次买断其使用权,是独享的。

总结几点:

a、稳定:云服务器ECS,实例可用性达99.95%,数据可靠性不低于99.999%,自动宕机迁移,自动快照备份,数据恢复更方便。

传统服务器,传统服务器受限于硬件可靠性,易出问题。需手工备份,人工数据恢复困难、耗时

b、弹性:云服务器ECS,自由配置CPU、内存、带宽,可随时升级,升级配置数据不丢失,业务暂停时间可控

传统服务器,固定配置,难以满足各类需求,改配置需硬件升级,周期长,服务停止时间不可控

c、安全:云服务器ECS,免费提供DDoS防护、木马查杀、防暴力破解等服务,可轻松实现多用户对多服务器的访问控制

传統服务器,需额外购买、部署各种安全措施,基本上做不到多用户对多服务器访问控制

d、成本:云服务器ECS,高性价比,支持包年包月或按量计费,满足不同需求,无需服务器网络和硬件等维护,0成本运维

传统服务器,租用费用高,只能包年包月购买,大量人员负责机器运维,成本高

e、易用性:云服务器ECS,丰富的操作系统和应用软件,通过镜像可一键简单部署,同一镜像可在多台ECS中快速复制环境,轻松扩展

传统服务器,几乎不提供任何软件支持,新增服务器需人工重复所有的部署操作

f、可拓展性:云服务器ECS,ECS可与华为云各种丰富的云产品无缝衔接,可持续为业务发展提供完整的计算、存储、安全等解决方案

传统服务器,很难在同一服务商內找到完整的服务,不能保证业务増长的可扩展性和持续性

更多精彩内容可以关注 华为云技术宅基地


https://max.book118.com/html/2018/0502/164325853.shtm

Docker化之前,阿里主要交易业务已经容器化。采用T4做容器化,T4是2011年开发的一套系统,基于LXC开发,在开发T4的过程中,跟业界很大的不同在于,T4更像VM的容器。当用户登进T4后,看起来与标准的KVM等几乎完全一样,对用户来讲是非常透明化的。所以,容器化不是我们推进Docker的原因。

  a)触发我们Docker化的主要原因一:Docker最重要的一点是镜像化,可以做到拿着镜像就可以从一台完全空的机器的应用环境搭建起来,可以把单机环境完全从零搭好。Docker化之前,阿里巴巴的应用部署方式主要由Java、C来编写的,不同的业务BU可能采用完全不同的部署方式,没有统一标准。内部尝试通过基线来建立部署标准,定义的基线包括应用依赖的基础环境(OS、JDK版本等)、应用依赖的脚本,基础环境的配置(启动脚本、Nginx配置等)、应用目录结构、应用包、应用依赖的DNS、VIP、ACI等,但不成功。部署标准做不了,直接导致自动化很难做到。

  b)触发我们Docker化的主要原因二:DevOps是一个更好的方向,阿里巴巴做了很多运维和研发融合的调整。Docker是帮助DevOps思想真正落地的一种手段,所有的思想最终都体现在工具或框架上,变成一个强制性的手段,Docker会通过Dockerfile的描述,来声明应用的整个运行环境是怎样的,也就意味着在编写Dockerfile过程中,就已经清楚在不同环境中的依赖状况到底是怎样的,而且,这个环境是通过一个团队来维护的。

  Docker化目标

  2016年7月,阿里巴巴制定了两个Docker化目标:

  交易核心应用100%Docker化;

  DB其中一个交易单元全部Docker化。

Docker化之路

  推进Dcoker之前,我们有一个准备的过程。在准备阶段,我们需要Docker更像VM和更贴合阿里运维体系的Docker,我们将改造过的Docker称为AliDocker;除了AliDocker以外,我们需要支持AliDocker的工具体系,比如编译、镜像库、镜像分发机制,在完成这些准备工作后,我们认为可以一帆风顺地开始大规模的AliDocker上线。但事实并非如此。

  第一轮Docker化

  我们碰到了很多问题:

  工具不完善,阿里很多应用之前都是在T4容器中,怎样将T4容器转换成AliDocker是首要面临的问题;

  镜像Build后上传,以前阿里一个应用转成多个,很多时候需要在自己的机器上做Build,然后自己上传,导致做应用时很痛苦;

  应用从T4切换成走Docker的链路,链路没有完全准备好,从资源创建到发布,很多需要手工去做,大规模去做效率非常低。

  第二轮Docker化

  在推进的过程中,我们又遭遇了新的问题。Docker的发布模式是典型的通过镜像,拉到镜像后将原来的容器销毁,重新创建一个容器,把镜像放进去,拉起来。Docker单一化的发布方式支持不了多种发布模式,更改velocity模板发布效率低;有本地内存cache的发布,重启本地内存cache就会消失。怎样在基于镜像模式情况下又能支持多种发布模式呢?

  我们在Docker的镜像模式基础上做出一个crofix的模式,这个模式不是绕开镜像,而是从镜像中拉起我们需要的文件,去做覆盖等动作,这样就可以完成整个发布。Docker化镜像模式是必须坚持的,否则失去了Docker化的意义。

  第三轮Docker化

  继续推进到很多应用切换到Docker的时候,我们又遇到了更大的问题:

  首先,很多研发人员都有明显的感受,切换到Docker后变慢。第一,编译打包镜像慢,编译打包完应用的压缩包后,还需要把整个环境打包成镜像,这是在原有基础上增加的过程,如果编译时每次都是新机器,以前依赖的所有环境都要重新拉,一个应用Docker的完整镜像通常会很大,因为它包括依赖的所有环境。对此,我们在编译层做了很多优化,尽可能让你每次都在之前编译的基础上进行编译。第二,镜像压缩问题,Go在1.6以前的版本压缩是单线程,意味着压缩整个镜像时效率会非常低,所以我们选择暂时把镜像压缩关闭掉。

  其次是发布问题,Docker的镜像化模式决定了分发一定是镜像分发,使用Docker时不能完全把它当作透明化东西去用,对所有研发人员来说,要非常清楚依赖的环境、Dockerfile中镜像的分层改怎么做,将频繁变化部分与不频繁变化部分做好分层,镜像分层是改变Docker慢的重要方案;阿里制定了镜像分发多机房优化,比如打包后将所有镜像同步到所有机房;阿里也做了发布优化(P2P、镜像预分发、流式发布),还通过Docker Volume将目录绑定到Dockerfile中,可以保证镜像文件每次拉起时不会被删掉。

  在整个Docker化的过程中,我们在“慢”这个问题上遇到了最大的挑战,不管是编译慢还是发布慢,都做了很多突击的改造项目,最后才让整个编译过程、发布过程在可控的响应速度内。

  第四轮Docker化

  在推进过程中,我们还遇到规模问题:

  由于规模比较大,开源软件很容易碰到支撑规模不够,稳定性差的问题。目前我们使用Swarm来管理,Swarm的规模能力大概可以支撑1000个节点、50000个容器,而我们需要单Swarm实例健康节点数在3W+,对此,我们对Swarm进行了优化。

  规模我们做到从支撑1000到3W+,压力减小了很多。而Swarm的稳定性对我们来讲,最大的问题在HA上,一个Swarm实例如果挂掉,重新拉起需要时间,所以我们在用Swarm时进行了改造。在前面加了一层Proxy,不同业务、不同场景都可以通过Proxy转换到自己不同的Swarm实例上。另外,所有的Swarm节点我们都会用一个备方案在旁边,而且都是不同机房去备。

  通过改造增强HA机制后,可以做到每次切换、简单发布。

Bugfix和功能增强

  除了上面四轮次比较明显的问题,在整个Docker化过程中,还做了很多的Bugfix和功能增强,具体有以下几方面:

  Daemon升级或crash后,所有容器被自动销毁的问题;

  Cpuset、cpuacct和CPU子系统mount到一起时CGroup操作错误的bug;

  支持基于目录的磁盘配额功能(依赖内核patch);

  支持制定IP启动容器,支持通过DHCP获取IP;

  支持启动容器前后执行特定脚本;

  支持镜像下载接入各种链式分发和内部mirror的机制;

  增加Docker Build时的各种参数优化效率和适应内部运维环境;

  优化Engine和Registry的交互。

  经历了这么多坎坷,我们终于完成了全部目标,实现双11时交易所有核心应用都AliDocker化,DB其中一个交易单元全部AliDocker化,生产环境共几十万的AliDocker。

未来

  容器化的好处是可以把很多对物理机型的强制要求虚拟化,可能也需要Docker在内核层面的改造,对于未来,我们已经做好了准备,希望:

  所有软件AliDocker化;

  和Docker公司紧密合作回馈社区;

  AliDocker生态体系逐渐输出到阿里云。


背景

2014年乐视云开始尝试Docker的推广和使用,我们的团队开始开发第一代容器云平台Harbor (分享网址:http://dockone.io/article/1091 )。(在这里提醒一下,这与VMware公司中国团队为企业用户设计的Docker Registry erver开源项目Harbor 重名)。

第一代容器云平台可以认为是一个开放的托管平台。开发者可以将自己从公司申请的虚拟机或者物理机添加到Harbor系统中进行托管管理,平台基本包含:镜像自动构建(CI),应用快速扩容、缩容、灰度升级,资源权限管理,多集群主机管理等功能。

由于那时容器才刚刚兴起,刚开始在公司内部推动也有一定的阻力,刚开始给业务线推广的时候,需要首先介绍Docker,介绍容器和虚拟机的区别,然后再介绍平台本身和使用方法,推广成本以及业务线学习成本也比较高。接入Harbor上的业务的大多是业务线自己提供虚拟机,而物理机占少数。不过鉴于Harbor的易用程度,吸引了很多新业务接入。到现在为止Harbor已经完全实现开发自助化。业务自己添加主机,自主管理应用和容器,对应用进行升级、回滚,弹性伸缩,镜像构建,现在已经稳定运行2年多。

第一代容器云平台不足之处

  1. 网络方面也是用的最基本的Nat,端口映射模式,存在性能问题。业务必须要知道容器对外映射出来的端口,对业务不透明,不便于报警和运维,也不便于对接负载均衡。

  2. 容器的分发调度全部自己开发,任务量大,当时没有能够做到容器自动迁移。

  3. 不支持应用的全球部署。

  4. Harbor管理的计算资源需要业务线自己申请,计算资源可以是物理机也可以是虚拟机,导致业务线需要关心底层的计算资源,计算资源无法对业务线完全透明。

  5. 为了降低用户对Dockerfile的学习成本,我们对Dockerfile进行了封装,只让用户写Shell脚本,因封装的不合理,导致制作出的镜像太大,尤其Maven项目,需要编译,每次在Docker Build时候,都会重新下载依赖包,导致编译过程长,镜像大,并且容器内服务启动方式不灵活。

  6. 监控报警机制不完善,没有做到容器和应用级别的监控和报警。

  7. 镜像仓库Registry并没有做得到像Docker Hub那样用户权限划分。

随着Kubernetes在越来越多公司开始使用,乐视内部更多的团队和业务线开始接受或者主动了解Docker,同时为了解决第一代平台的存在问题和基于乐视现有服务部署情况,到2015年底,我们团队计划替换掉之前自己写的调度方案,着手尝试使用Kubernetes作为容器的调度引擎,在对比多套网络方案(Calico,Flannel等等)后,结合乐视现有状况,采用Bridge模式,容器大二层网络方案。负载均衡使用Nginx,计算资源全部使用物理机,计算资源完全对业务透明。经过半年多的调研和开发,在2016年10月第二代PaaS平台LeEngine在美国上线,半个月后,北京地区上线。LeEngine现在保持着一月一版本的开发迭代速度,到现在为止已经开发了3个版本。

LeEngine 采用全新的架构,主要面向于无状态或者RPC应用。现在已经承接了乐视云计算,乐视体育章鱼TV,风云直播,乐视网乐看搜索,云相册等近100多个重要业务,使用的客户普遍反映一旦掌握了LeEngine的使用流程,从开发到上线部署,弹性伸缩,升级的效率可成倍增长,极大简化了运维成本。LeEngine拥有极强的用户粘性,吸引了很多业务线主动申请试用LeEngine,现阶段已经不需要再增加额外的精力在公司内部推广。

简介

Kubernetes:Google开源的的容器编排工具,在整个2016年,越来越多的公司开始在线上使用Kubernetes,同时Kubernetes具备我们迫切需要的容器自动迁移和高可用功能。关于Kubernetes 的架构在这里我就不多介绍了,虽然架构偏重,但是我们最终决定使用它,并且尽量只使用它的Pod,Replicationtroller和Service功能。

这里首先解释一下几个概念:

用户

:乐视各个产品线下的产品、开发、测试、运维等人员。

Region

:偏向于地理概念,例如北京和洛杉矶是两个Region。 同一个Region内要求内网可达,网络可靠,低延迟。同一个Region共用一套镜像Registry,镜像构建系统,负载均衡系统和监控报警系统,不同Region 共享全局唯一的SDNS和GitLab代码仓库。

Cell

:我们现在使用的Kubernetes 1.2.0版本,理论上能控制1000个计算节点,为谨慎使用,规定一个Kubernetes集群最大计算节点会控制在600个左右。 Cell 概念的引入是为了扩充单个Region下计算节点的规模,偏向于机房的概念,一个Cell 即一个Kubernetes集群,每个Region下可以搭建多个Cell。所有Cell共享本Region下的镜像Registry,镜像构建系统,负载均衡系统和监控系统。为同一个Cell下的容器配置一个或者多个网段,每个网段划分单独的VLAN。同一Cell下的计算节点不会跨机房部署。

LeEngine Registry

:基于Docker Registry 2.0做的部分修改,后端支持乐视云的Ceph存储。并仿照Docker Hub增加权限和认证机制,只有拥有相应权限的用户才能对特定的镜像进行Push和Pull操作。也可以设置镜像公开,公开的镜像任何用户都可以Pull。

计算节点

: 物理机,Kubernetes的Node概念。

应用

: 定义提供相同业务逻辑的一组容器为一个应用,可以认为应用是一个微服务。这类应用要求是无状态Web服务或者RPC类的服务。应用可以部署在多个Cell中。上文提到过,一个Cell可以认为是一个机房。LeEngine在一个Region下会至少部署2个Cell,部署应用时候,我们要求应用至少部署在2个Cell中,这样即使一个机房出现网络故障时,另一个机房的应用容器还能继续对外提供服务。一个应用下可以部署多个版本的容器,因此可以支持应用的灰度升级。访问web类应用时候,我们强制要求这类应用(如果是线上应用)前面必须使用负载均衡,由我们的服务发现系统告诉负载均衡当前应用下有哪些容器IP。从Kubernetes层面讲,我们规定一个应用对应Kubernetes下的一个Namespace,因此在应用的数据库表中会存在一个Namespace的字段,并需要全局唯一,而应用的多个版本对应了在这个Namespace下创建的多个Replicationtroller。

Region、Cell 和kubernetes的关系:

关系.png

架构平台设计

容器直接运行在物理机上,计算节点全部由我们提供,业务线不需要关心,LeEngine可以作为一个企业解决方案对外全套输出,平台架构如下:

架构.png

业务层: 乐视使用容器的各个业务线,是LeEngine的最终用户。

PaaS 层: LeEngine提供的各种服务,主要是完成对应用的弹性伸缩,灰度升级,自动接入负载均衡,监控,报警,快速部署,代码构建等服务。

宿主机资源层:主要指Docker 物理机集群,并包含IP池的管理。

逻辑.png

用户访问部署在LeEngine上的应用时,首先通过SDNS智能解析到对应的Nginx负载均衡集群,然后由Nginx将请求打到对应的容器中。数据库,缓存等有状态的服务并没有在LeEngine体系之内,因为采用大二层网络,容器可以直接连接公司其他团队提供的数据库或者缓存等服务。

下图是为了更好的说明支持多地域,多kubernetes集群的部署。

Region.png

单一Region下单Cell部署图:

单cell.png

我们将计算节点的管理网络和容器网络划分开并给容器网络划分单独的VLAN。

成员、权限管理

LeEngine下面定义了四大资源,应用、镜像、镜像分组和代码构建。为了团队协同操作,这4大资源都增加了成员和权限管理。成员和权限仿照了GitLab进行了设计,成员角色分为:Owner、Master、Developer、Reporter、Guest。 不同的角色针对不同的资源系统都定义了不同的权限。比如应用,只有Owner和Master有权限对应用部署新版本,弹性伸缩等等。 假如一个用户A创建了一个应用A1,那么A就默认是应用A1的Owner,拥有对应用A1所有操作权限,包括部署新版本,弹性伸缩,修改应用,删除应用等所有操作。而用户B此时对应用A1不可见,若想可见,必须由A对这个应用A1执行添加成员的操作,把B添加到A1中,并赋为除Owner以外的任何一个角色,若此时B被赋为Master角色,那B拥有了对应用A1部署新版本,弹性伸缩等权限,反之则没有。

根据上面的权限设计,通过LeEngine的Console界面,不同的用户登录后看到的仅仅是跟自己相关的资源,如下图,在应用中,能看到我创建的以及我参与的应用:

参与应用.png

在镜像页面,能够看到我创建的以及我参与的镜像,如下图:

参与镜像.png

帮助文档会提供给用户不同资源的权限说明:

帮助.png

帮助2.png

用户端和管理端

LeEngine具有面向用户端的Console界面和面向运维管理员的boss界面,在用户端用户可以看到自己创建和参与的4种不同的资源。管理端则主要是对整个LeEngine平台资源进行管理,包括用户可使用最大资源的限制,负载均衡特殊配置,Cell集群下的资源使用情况,操作频率统计等等。

下图是LeEngine测试环境boss系统关于操作频率统计:

操作频率.png

操作频率包括每天所用应用的部署次数,代码的构建次数,镜像的Push次数,弹性伸缩次数,在一定程度上能展示出业务线对LeEngine平台本身的使用频率。

LeEngine-core

LeEngine-core是LeEngine最终对外提供服务的API接口层(beego实现),所有4大资源的操作,包括权限控制,都是通过这一层控制的。LeEngine只提供最原子的API接口,特殊业务线要想有特殊的需求,完全可以在现有API基础上进行二次开发。

容器网络

容器采用大二层网络,因此可以保证外部服务可以直接连通容器,容器也可以直接连通外部服务,比如数据库,缓存等等。采用此种方案可以保证容器横向可连接,纵向可访问。外部想连接容器可以通过容器IP地址直接连接,也可以通过负载均衡方式进行访问。而容器也可以直接访问LeEngine体系外的虚拟,物理机资源,以及MySQL等组件服务。

纵向访问.png

我们自己写了CNI插件和CNICTL管理工具,支持添加多个IP段,用来防止IP资源不够的情况。IP段的信息存在了当前Kubernetes集群里的etcd中。我们会为每个Cell即每个Kubernetes集群下都添加至少一个IP段,一般1024个IP地址22子网掩码,单独vlan防止广播风暴,这需要提前跟网络部门规划好IP段。如果这个IP段已经使用完,我们会使用CNICTL工具,重新增加一个新的IP段。

容器网络.png

为了进一步保证业务容器在网络方面的稳定性,我们所有的计算节点都是4个网卡,2千兆,2万兆,双双做bond,千兆bond1用来做管理网卡,万兆bond1用来跑业务容器,每个计算节点在交付时候会创建一个OVS网桥,并将bond1挂载上去,上联交换机做堆叠,计算节点尽量打散在多个不同机柜中。

计算节点物理机上的Kubulet在创建Pod的PAUSE容器后,会调用我们自己CNI插件,CNI会创建一个veth pair, 一端扔到这个容器的Namespace中,并命名eth0,一端挂载到OVS网桥上,之后从etcd中大的IP段中找出一个连续16个IP地址的小段给这个计算节点,然后再从这个子段中找一个空闲的IP给这个容器,配置好容器IP,以及路由信息,同时会根据配置来确定是否发送免费ARP信息,之后遵守CNI规范把相应的信息返回给kubelet。当这个计算节点再次创建新的Pod时,会优先从这个子段中选择空间的IP,若没有空闲的IP地址,会重新计算一个子段给这个计算节点用。

现在CNI不能保证Pod删掉重新创建时候IP保持不变,因此应用在每次升级操作后,容器IP地址会变,这就需要我们的服务发现与负载均衡做对接。

不过现在的这套方案也会存在一些问题:比如物理主机突然down掉,或者Docker进程死掉,导致本主机上所有容器挂掉,等kubelet重新启动后,原来死掉的容器所占用的IP并不会释放。我们现在的解决方案是通过我们开发CNICTL命令来进行定期检测。CNICTL提供一个check命令,会检索etcd中所有分配的IP和对应的POD信息,之后调用apiserver获得所有Pod信息,取差值则为没释放的IP地址。收到报警后,人工调用CNICTL的释放IP功能,手动释放IP。

服务发现

我们充分利用了Kubernetes的Service概念,前面已经提过,一个应用对应一个Namespace,一个版本对应一个RC,在用户通过API请求创建应用时候,LeEngine核心API层:LeEngin-core会默认在对应的Kubernetes集群中创建相关联的Namespace,同时默认在这个Namespace下创建一个Service,并创建一个唯一的标签属性,用户在部署新版本(RC)时候,LeEngine会给这个RC添加这个Service的唯一标签。这样就可以通过Service来发现后端的Endpoint。我们用Go写了一个服务发现服务,通过watch api-server的API接口,自动归类发现哪个应用下有IP变动,之后调用我们负载均衡的API接口,动态更改Nginx的后端upstream serverip。

在我们没使用Kubernetes的健康探测功能之前,会有一定的几率出现容器创建完成,服务没有完全启动,这时候容器IP已经加载到负载均衡的情况,如果这时候如果刚好有请求过来,会出现请求失败的现象。之后我们在最新一版中,加入了健康探测功能,用户在给应用部署新版本时,允许用户指定自己服务的监控探测HTTP接口,当容器内服务探测成功后,才会加入到负载均衡中去。而删除容器则不会出现这种情况,执行RC缩容命令后,需要删除的容器首先会立马从负载均衡中删除,之后才会执行容器的删除操作。

负载均衡

我们并没有使用Kubernetes的Proxy作为负载均衡,而是使用Nginx集群作为负载均衡。Nginx我们原则上会部署在同一个Region下的多个机房中,防止因为机房网络故障导致全部的Nginx不可用,支持Nginx横向可扩展,当负载均衡压力过大时候,可以快速横向增加Nginx物理机。为防止单一Nginx集群下代理的Domain数目过多,以及区分不同的业务逻辑,比如公网和内网负载均衡,我们支持创建多个Nginx负载集群。

下图为用户浏览请求路径。

请求路径.png

关于如何能够通知Nginx集群自动更新Upstream下的Server IP问题, 我们在Nginx集群外面用beego框架设计了一层API层:slb-core, 专门对外提供API接口,具体结构如下:

slb-core.png

etcd里面存放每个domain的配置信息。具体key结构如下:

/slb/{groupname or groupid}/domains/{domain_name}/

每一台Nginx主机上都会安装一个Agent,每个Agent监控他所属的groupid 的key,比如/slb/2/,这样可监控本Nginx 集群下所有Domain的配置变化,Agent 将变化过的Domain 配置更新到Nginx下的目录下,并判断配置变化是否是更改的upstream下的Server IP还是其他配置,如果发现是其他配置更改,比如location或者增加header,则会reload nginx, 如果发现单纯更改upstream 下Server IP,则直接调用Nginx动态更改upstream ip的接口。

上层的slb-core 则会提供domain动态更改后台upstream ip的接口, 供服务发现调用。

如果多个互相关联,互相调用的业务域名都同时被一个Nginx集群所代理,若其中一个domain需要更改配置,导致需要reload nginx,很可能会出现reload 时间过长的问题。

基于这套架构,后端Nginx主机可以快速扩展,迅速增加到对应集群中。由于增加了nginx test机制,当用户更改domain的配置有语法问题, 也不会影响负载均衡,还会保持上一个正确的配置。现在这套架构已经是乐视负载集群的通用架构,承载了乐视上千个域名的负载均衡。

用户在创建一个应用时候,如果需要负载均衡则需要填写负载均衡域名,Nginx集群等信息, 如下图:

创建应用.png

创建成功后,通过查看应用的负载均衡导航栏可以知道这个应用负载均衡的CNAME和VIP信息,等业务测试成功后,DNS系统上配置使域名生效。

如下图:

负载均衡.png

下图可以让用户查看负载均衡Nginx配置信息:

负载均衡配置.png

现阶段Nginx负载均衡集群并没有按照一个应用来进行划分,大多数情况是一个Nginx负载均衡集群代理了多组domain。因此对于用户端,为了防止业务线用户恶意或者无意的随便更改,而导致整个Nginx集群出现问题,现阶段用户端无权更改Nginx配置,如果需要更改特殊配置,需要联系管理员,由管理员进行配置。后续我们会考虑给一个应用分配一组Nginx容器进行负载均衡代理,这样用户就会拥有Nginx配置更改的最高权限。

LeEngine registry

LeEngine Registry是我们内部提供的镜像仓库,根据Docker Registry 2.0 版本:docker distribution做了修改,支持乐视Ceph后端存储,同时使用auth-server 以及LeEngine 的权限机制,定义用户和权限划分。允许镜像私有和公开。 公开的镜像任何用户可以执行Pull 操作。私有的镜像可以添加团队成员,不同角色的成员具有不同的Push,Pull, 删除权限。基于以上的设计LeEngine Registry 可以完全独立于LeEngine对外提供镜像仓库服务, 业务线如果不想使用LeEngine的代码构建功能,可以完全使用自己的构建方法,构建出镜像来,之后Push 到LeEngine registry中。

如下图是关于镜像tag的相关操作:

镜像tag.png

成员:

成员.png

动态:

动态.png

LeEngine下4大资源:应用、镜像、镜像组织、代码构建,在每个资源页里都是有动态一栏,用来记录操作记录,方便以后的问题追踪。

代码构建

为了快速将代码构建成Image,并Push到镜像仓库中,LeEngine后面会设置一组专门构建用的Docker物理机集群,用来执行构建任务,每个构建物理机都会安装一个Agent。

LeEngine的代码构建框架如下:

构建框架.png

每个构建物理机上的agent 启动后,都会将自己的信息定期自动注册到etcd中,表示新增一台构建机,当Agent意外停止或者主机挂掉,etcd中的注册信息会失效,表示已经下线一台构建机。另外Agent会监控自己的任务key,用来接收LeEngine-core下发的构建任务。

当有一个构建请求时会调用LeEngine-core的API,LeEngine-core会从etcd中选出一个合适的构建机(一般按照hash方式,尽量保证一个代码构建在同一台物理机上构建,加快构建速度), 然后将构建任务放到这个构建机的任务key中,对应的Agent监控到key变化后,会执行代码Clone,编译,Build和Push操作。

Etcd在LeEngine中扮演这非常重要的角色,是各个模块通信的消息总线。

鉴于Maven项目,需要编译,在第一代Harbor系统中,编译步骤放在了Docker Build 过程中,由于Maven编译需要大量的mvn依赖,每次编译都需要重新下载依赖,导致编译时间长,编译的镜像多大,因此我们在Build之前,会起一个Container,在Container中对代码进行编译,并将mvn依赖的目录映射到主机上,这样同一个代码构建,在每次构建时候,都会共享同一个mvn依赖,不需要重新下载,加快编译速度,同时还能保证不同的代码构建使用不同的mvn依赖目录,保证编译环境绝对纯净,最后只将编译好的二进制打到镜像中,在一定程度上保证代码不外泄。

代码构建仅限于放在Git上的代码,现阶段并不支持SVN,因此有的业务如果代码在SVN上,可以使用其他工具自己将代码制作成镜像,然后Push到LeEngine Registry上。由于LeEngine Registry上对镜像和镜像仓库做了权限认证,保证了镜像的安全。

代码构建支持手动构建和自动构建,在GitLab上设置相应的Web hook,这样用户只要提交代码,就会自动触发LeEngine的代码构建功能。

下图为创建代码构建的Web页:

添加构建.png

使用LeEngine的代码构建,我们要求用户的代码里需要自己写Dockerfile,Dockerfile 里FROM 的根镜像可以使用LeEngine Registry 里公开的镜像,也可以使用Docker Hub里公开的镜像。

如果业务代码需要编译,则可以指定编译环境,编译脚本也是需要放到代码中。

下图为手动构建页面:

手动构建.png

tag名如果不写,LeEngine会根据当前分支下的commit号作为镜像tag名。如果选用mvncache,则本次构建就会使用上次构建所下载的mvn依赖,加快构建速度。

下图为构建结果:

构建结果.png

构建过程:

构建日志.png

构建日志中,每一关键环节都记录了耗时时间,以及具体的执行过程。

应用管理

应用支持垮机房部署,多版本灰度升级,弹性伸缩等功能。我们规定一个应用对应一个镜像。

应用服务.png

部署版本(一个版本即一个RC)时候,需要指定镜像tag,容器数目,CPU,内存,环境变量,健康检查等等参数,现在的健康检查我们暂时只支持http接口方式:

创建新版本.png

由于大部分的升级,都是更改镜像tag,因此每次部署新版本时候,LeEngine会在新弹出框内,将上一版本的容器数目,CPU,内存,环境变量,健康检查等等参数自动填充到弹出框中,用户只需选择新的镜像tag就可以了。因此最后灰度上线,只需要创建新版本等新版本的容器完全启动,服务自动加入负载均衡后,再将旧版本删除即可。

下图为应用事件查看:

应用事件.png

应用事件主要收集的是应用在Kubernetes集群中的事件信息。

监控、告警系统

监控报警我们分PaaS平台和业务应用两大类。

PaaS平台主要聚焦在基础设施和LeEngine的各个服务组件的监控报警(比如主机CPU,内存,IO,磁盘空间,LeEngine各个服务进程等等),这一类使用公司统一的监控报警机制。

业务应用类,也就是跑在LeEngine上的各个业务线的监控和报警,需要由LeEngine进行对其进行监控和报警,触发报警后,会通知给各个应用的负责人。我们采用了heapster 来收集容器的监控信息和Kubernetes的各种事件。每个Cell集群中都部署一个heapster,监控数据存放到influxdb中。设定了一个应用全局对应一个Kubernetes的Namespace,因此我们能很好的聚合出应用和单个容器的监控数据。

如下图 针对应用的网络流量监控:

网络监控.png

容器 IP,运行时间和状态:

容器监控列表.png

下图是针对应用下单个容器的监控:

单个容器监控.png

现在heapster 没法收集容器的磁盘IO数据,后期我们会增加对于磁盘IO的监控收集,同时我们会丰富其他的监控数据(比如请求量等等)。关于报警,我们后期准备使用kapacitor 进行用户自助化报警,让用户自定义设定针对于应用cpu,内存,网络,IO,容器重启,删除等的报警阀值。触发报警后,会调用公司统一的告警平台(电话,邮件,短信三种方式)对相关人员进行报警。默认报警人员为当前应用的Owner和Master角色的成员。此功能已经基本调研完成,计划3月底上线。

日志收集

根据公司具体状况,容器的日志收集暂时还没有纳入LeEngine范围内,全部由业务线自己收集,然后统一收入到公司的日志系统中或者由业务线自己搭建日志存储和检索系统。我们后期会考虑日志统一收集。

总结

一键式解决方案

LeEngine提供了代码构建,镜像仓库,应用管理,基本上实现了开发者一键式解决方案:

一站式解决方案.png

各个业务线开发人员只需要提交代码,剩下的就会根据打包和构建规则自动生成特定的镜像版本,测试和运维人员只需要拿着对应的镜像版本进行测试和线上升级即可,极大简化开发运维工作。

减少运维成本

我们建议程序在容器内前台启动,利用Kubernetes的功能,程序死掉后,由kubelet自动拉起,实时保证线上容器实例数。若需要调试,业务或者运维可以直接通过SSH连接到容器内排查问题。由于Kubernetes强大的容器自动迁移功能,即使后端物理主机出现宕机或者网络问题,也不会产生严重的问题,除非后端物理计算资源不够,这在很大程度上减少了运维人员大半夜被叫起处理问题的次数。

计算资源对业务完全透明

底层计算资源完全由我们提供,业务线不用担心资源的问题。

产品化

LeEngine在设计之初,保证尽量少的依赖其他外部资源和服务,整个LeEngine可以作为一个解决方案整体对外输出。

存在的问题

任何一款产品不管怎么设计,都有它的不足之处,LeEngine在上线之后,我们也收到了不少反馈和问题。

  1. 按照之前的运维习惯,运维人员在排查问题时候,经常会根据IP来进行区分,而LeEngine下的应用每次升级后,容器IP都会变化,这对传统的运维造成一定的冲击。我们现在的解决思路是,如果运维人员一定要通过IP去排查,我们会让运维人员登录LeEngine的Console,查看当前应用下的容器IP列表,之后再去逐个排查。同时有的业务会对IP进行访问限制,针对这种情况,我们只能让这些业务对一个IP段进行限制。

  2. Kubernetes 1.2版本,对容器的swap并没有控制,若业务应用有bug,出现大量的内存泄露,往往会把容器所在物理机的swap吃满,而影响了物理机上其他的容器。 我们现在的解决方案暂时只能通过报警方式,尽快让用户修复问题。

  3. 由于Dockerfile 和编译脚本都要求放在用户Git代码中。会存在用户Git使用不规范,不同分支代码互相merge,导致Dockerfile和编译脚本出现变化,导致构建出的镜像与预期的不一样,从而上线失败。这种问题,我们只能要求业务线规范Git使用规范,LeEngine代码构建本身已经无法控制到这种细粒度。

  4. 现阶段我们还没法做到自动弹性扩容(给应用设定一个最小容器数目和最大容器数目的阀值,根据CPU、内存、IO、请求量或者其他值,自动觉得容器是否需要扩容,缩容)。

展望

Docker和Kubernetes也在飞速发展中,相信Kubernetes未来会有更加强劲的功能,我们后续也会考虑把有状态的服务跑到Kubernetes中去,欢迎大家一块探索。

Q&A

Q:你们的IP管理应该做了很大的开发工作吧?能详细介绍一下?

A:确实做了很多开发工作,其中很大的一个开发量是关于空闲IP获取这块。

Q:还有你们的灰度发布是用的Kubernetes本身滚动更新功能?还是自己实现的?

A:灰度发布没用Kubernetes 的滚动更新更能,而是用了不同的RC的相互切换。

Q:多个Region的镜像管理,如何实现镜像同步与更新?

A: 我们不需要实现镜像的同步。分享中已经提到过,各个Region有自己的镜像仓库。

Q:你好 请问你们大二层网络是用开源方案实现的还是自己根据OVS开发实现的?

A:是我们自己实现的,我们CNI中调用了OVS,主要是使用了OVS的网桥功能。

Q:应用跨机房部署,我理解也就是可以跨Kubernetes集群部署,Kubernetes里的调度是如何做的?

A:应用的概念,是在Kubernetes集群之上的,应用可以部署在多个Kubernetes 集群中。

Q:请问贵公司内部服务之间的互相调用是怎么控制的?容器到容器还是容器-Nginx-容器(等同外部)?

A:1. 容器->容器 2. 外部服务->Nginx->容器 3. 容器->Nginx->容器 4. 容器->外部服务。 这种情况都有,主要看业务场景。

Q:构建服务集群用到什么CI工具,还是自己开发的?etcd在其中有什么作用?

A:自己开发的,etcd 相当于消息队列,控制层收到构建请求后,etcd中存放了现阶段集群下都有哪些构建机,当来到构建请求后,控制层会寻找一个构建机器,并向构建机器所在的etcd key中发送命令, 对应的构建机器在监控自己的key发生变化后,会执行相应的构建任务。

以上内容根据2017年2月14日晚微信群分享内容整理。分享人

作者:张杰,乐视云计算有限公司PaaS平台LeEngine负责人。毕业于东北大学,专注于云计算领域PaaS平台的技术研究。14年入职乐视,目前从事基于Docker和Kubernetes的企业级PaaS平台的架构设计,研发以及平台落地工作。