新浪微博基于Docker的混合云架构与应用实践

大家好!先做一个自我介绍,我来自新浪微博,付稳,属于微博平台研发中心,本次分享的主题是新浪微博DCP基于Docker的混合云架构与应用实践。今天的主题是SwarmMesosKubernetes的三国演义,但是我可能更多讲的是大型互联网公司在调度框架选型或者它依赖的中间设施,如何把它应用到上千台服务器的一个规模,新浪微博遇到了哪些问题,并且如何来解决它们。

背景,挑战与实现

 

20161101214847

 

介绍一下本次项目微博混合云的背景,大家知道微博的体量是比较大的,线上规模大概几千台服务器,所以每一次架构改造对我们来说都是非常大的挑战,要考虑的因素会更多。

 

20161101214854

 

微博的峰值流量特点类似前一段时间的王宝强事件、奥运事件、乔任梁事件,在10分钟之内,微博的流量会涨到两到三倍。线上有三千台服务器,如果十分钟内流量来了三倍,以前是没办法的,申请机器、上架、初始化、服务部署,这一个流程大概需要一两个月,所以就要求平台研发中心具备在十分钟之内完成一千个节点的扩张能力。考虑几个方面:极端峰值、扩展性、成本和业务迭代。业界基本就是依靠混合云这种趋势,包括阿里云、AWS等公有云平台的成熟是一方面,国内的12306利用阿里云来解决它的余票查询业务,包括Docker、Mesos等容器新技术使大规模动态调度成为可能性,京东等也在这上面有一些实践,所以我们也提出了自己混合云的解决方案。

 

20161101214902

 

说一个大家能比较切身感受的例子,12306。这是12306的一个本地机房。它70%的业务来自于余票查询,即压力70%在余票查询上,它把这一部分放在公有云上,内部的IDC每五分钟之内缓存同步,同步到阿里云机房。用户来访问12306的时候,如果是其它业务、结算类业务就走本地IDC,如果余票查询就走阿里云的IDC。这给我们很好的一个启发,可以利用公有云节省成本,快速扩容,但是它的数据是分钟级同步的、流量可预期,而新浪微博整个峰值就是十分钟,比如王宝强发酵事件,要十分钟之内要扩容完成,完成服务发现流量引入;大家刷一条微博也不可能要求别人五分钟之后才能看到,所以对技术的要求很高。

混合云去年DCP的实战,具备了十分钟混合云扩容一千节点的技术能力,春晚两天之内完成了1000+台阿里云ECS,基本上就是16核16G或者16核64G高配的这种配置,当然容器数量肯定是成倍的增加。实现了无降级的平滑过渡,同时支持了微博50%的主体流量,利用Docker技术动态调度技术、基础设施跨云,包括微博Feed流、红包飞、手机微博不同业务方都使用。现在每天晚上也是利用这种动态调度标准体系的晚高峰扩容300+节点,热点事件也会进行弹性扩容。

基于混合云的微博项目总结两点,第一是基于Docker的弹性调度,第二是基础设施的跨云。当然服务编排是不可分割的一个部分,但是如果想让混合云体系运转起来可能还需要基础设施的跨云。接下来,我会对这几个问题分别讲解。

 

20161101214910

 

 

整个微博的容器技术发展体系, 2014年我们做了Docker化、容器化,2015年到现在我们做了私有云+混合云,还有动态调度。技术也是在不断积累中的,这是目前成型的一个技术体系。大家可以看主机层,主机层其实是内部和私有云打通,外部和公有云打通,它进行主机的创建。主机的创建之后,进行成本的结算。它还要承担一个最重要的任务就是初试化,比如Docker环境,Mesos、Swarm的环境,还有运维基础环境的初始化。服务编排下发编排任务,编排向调度层进行下发,下发根据调度策略选择进行资源调度。当你有资源的时候,它可以进行资源调度。如果没有物理资源,它向主机层进行申请。主机层申请之后,这里面创建机器,其实初始化做了很重要部分就是把它创建机器成为一个可运行的Docker编排环境。在调度层去年我们主体跑的Swarm大概有两千+节点,然后部分的业务线在Mesos上跑,今年主要在自研的容器调度平台。DCP的编排+调度+主机体系,和Docker三驾马车有类似,之后也会重点介绍。当集群是一、两千节点,并发量百亿级时候,服务发现、镜像中心、监控中心包括容量评估等周边体系建设等都是要考虑的。

 

20161101214919

20161101214928

 

新浪微博的技术栈基本上是内网私有云的裸主机,公有云上VM,CentOs全是7.0的,Docker1.6.2。为什么1.6.2?因为这是目前跑的最稳定的一个版本,近期也在考虑升级,去年调研的时候,因为我们用Swarm比较早,所以从0.1快到0.4,后来出了1.0,稳定版本一直在用。其实Docker1.6.2目前来说是最能和Swarm兼容的版本,因为Swarm是基于DockerAPI的,低版本的API是不支持的,这就要求我们Docker版本至少为Docker1.6.2。网络模式是Host的模式,因为我们的并发量比较大,我们调整过其它网络模式,但是网络性能损耗是非常大的,这方面不能忍受,所以是Host的模式。DockerRegistry是自建的镜像仓库V1、V2。

 

20161101214937

 

整个混合云的DCP流程,首先是内网主机申请,内网向私有云申请,公网向云端进行申请,申请之后进行初始化,初始化有两步,系统环境、运维环境(DNSmasq、Cron等)初始化。还有一些Docker环境, Docker Swarm、 Mesos进行安装和启动,安装和启动之后就代表一个可调度的Docker环境,然后根据你的调度策略和算法进行动态调度。之后容器镜像启动、服务发现全自动流程。关于服务发现是微博自己开源的平滑reload的服务发现版本nginx-upsync-module。

基础设施

新浪微博的基础设施很多功能现在都要用阿里云去改进或者是去定制,所以在公有云上做了很多经验。整个DCP的思路就是内网私有云,因为微博有着这样的特点,就是大家刷微博的时候,刷PC端一般是中午,刷手机端微博是晚上,它属于两个不同的业务方,当然从属于一个大的技术平台。当中午流量刷的时候,手机端微博的用户其实少了,可以把机器共享出来放入我们的私有云或者放到共享池。不管是私有云还是公有云的机器,通过资源调度的方式,当机器闲置的时候,把它放入一个共享池整合来利用,提高资源的利用率。

 

20161101214946

 

公有云方面,我们做了一些改造是封装阿里云的接口。大家封装阿里云可能是一台或者是几台的,但我们如果在几分钟之内要创建一百台或者一千台,肯定要对它的接口进行封装,包括它的一些BUG也提出要求,一些VPC或者是一些控制台的性能我们也做了封装和改进。假如有了上面的API,就可以创建机器了。创建机器的时候,首先建议大家定制一个自己的VM,这个VM镜像不是Docker镜像,是操作系统的镜像。我们的Docker基础镜像版本是这样每个层级来分的,比如说CentOS,然后所有的Mesos,Java,PHP,整个镜像大概是700M。如果一个镜像700M,当整个一千台集群开始拉这个镜像的时候,它是相当大的带宽,多机房镜像仓库是扛不住的。主要Docker镜像放置操作系统VM镜像,使只有代码部分或者你的配置变更部分,在拉取镜像时变更。利用的就是Docker镜像分层机制。

 

20161101214953

 

回到上面,我们创建一台VM的时候,配置所需要的环境和软件,构建快照,这些快照基本上把所需要的镜像先预放到操作系统里面,然后设置你的磁盘分区、机器权限及自定义的启动脚本,进行预设。下边一步是初始化,一般是在内网Puppet,阿里云上用的Ansible。然后用这些内网工具做初始化,我希望通过初始化把这个版本、把Swarm、Mesos这些组件进行启动。初始化完成以后,代表你是一个可运行的调度资源调度环境。关于Ansible大家知道有很多坑,包括性能非常差。一台Ansible配完能达到30、40台的规模,我们把它源码做了一些改造,包括一些初始化的稳定性和速度优化。

 

20161101215001

 

综上说,我们通过了一个VM的镜像加初始化,利用Docker镜像体系打造了一个标准化的运行平台,不同语言或者不同的跨云、跨业务都可以在这个Docker环境中进行动态调度。

 

20161101215009

 

我们的内网有自己的镜像仓库,版本是V1到V2,存储是Ceph。在内网所有的业务端上传镜像之后会自动同步到公有云或者同步到不同的机房,这样避免跨IDC之间的带宽传送太大。阿里云上为镜像Mirror的缓存,随时进行同步,节省了拉镜像的时间。其实整个容器启动是非常快的,但是遇到大镜像存在一两分钟无法拉去现象。镜像仓库最大的瓶颈其实是带宽,千兆网卡如果没达到瓶颈,你会看到它很正常;如果达到瓶颈,它会达到一个峰值恶化,性能急剧下滑。同时我们做了一些优化,包括镜像仓库根据扩容台数,比如扩一千台可能按比例自动扩容镜像仓库,支持动态扩展。

 

20161101215018

 

最后简单说一下公有云上有一个网络,就是微博内网联通电信两大机房之后,通过两根端线,比如阿里云的A区和C区进行打通、专线互联打通,同时构建了一个VPN网络,这个VPN网络是走公网的,性能要求不高可以走VPN网络,当然两个专线之间是互备的,比如这根断了之后,它会自动进行路由切换,走这条线路,保证网络的高可用。

弹性调度

 

20161101215026

 

接下来介绍拿到一个物理主机之后怎么样建成一个可动态调度的Docker环境,首先说一下弹性调度。其实弹性调度基本上离不开今天提的三个主题,Swarm、Mesos和K8S。我们在用的时候也做了很多调研,也纠结于选型,最后选择了Swarm,我们又自研了一些容器编排的工具。我们的需求其实很复杂,包括跨池调度、指定归还、单机业务的灰度、多实例的部署、故障的自动恢复、还有一些定制的调度算法、容器的监控、评估,跨IP调度等等。其实我们要实现的需求就是快速迭代,实现内网计算资源的统一管理,公有云上获取计算资源,快速进行部署。结果发现上面任何一个调度框架拿来直接用的都是不好用的,所以我们在上面做了改造,就是对调度框架进行了一个封装。它接受编排层的一个任务调度体系,告诉你不同的IDC、不同的服务,然后你的调度策略是怎么样的,根据你所要的资源、你所要的数量来下发。分几种模式,现在主要线上跑的有直接DockerDaemon的管理,以及Swarm、Mesos。Mesos将来预期管理离线存储业务,其实就是把它整个生态体系进行封装。我们做了自定义调度框架,还有资源的管理,特别是资源的编排和管理、容量的评估、监控报警基本上都在这一层来完成。

 

20161101215034

 

因为功能多,所以生产池的环境中有很多坑的问题。Swarm的架构基本上是业界很通用的CS的模式,Client节点向Master进行汇报,这里面有一个资源注册中心,我们用的是Consul,向Consul进行注册,Master通过Consul拿到节点信息后通过Http请求与client通信管理。之前早期的版本,Swarm性能非常差,因为它下发命令之后,任何命令会有一个全局锁,现在已改为分步式锁,性能比较高。整体来说,它的性能还是比较好的。单个集群节点,单个IDC,其实管最大的一千+节点是没有问题的。现在Swarm应该有了一个高可用的版本,当时我们做了基于Consul的一个多IDC的高可用、可扩展的机制。

 

20161101215043

 

为什么微博当时选择Swarm?因为它简单,是Docker原生,满足微博跨服务池一些编排或者一些抽象多租户的需求。因为当时K8S只能管理容器化,微博后期还有一些离线的业务想去做,所以就没有选K8S。Mesos,现在也是简单管理一些非容器。

 

20161101215052

 

Swarm的调度策略基本上分为两个部分,第一个部分是主机、容器的过滤加上策略的选择。拿到一定资源之后,过滤基本上就是健康性的过滤,容器这个节点是死还是活,还有约束条件,就是DockerDeamon打标签。给这些容器打这个标签,它就只能这个范围之内进行容器管理,比如不同的服务池,手机微博的服务池、PC端的服务池啊、不同业务的服务池进行隔离,隔离之后,比如只要找手机微博的服务池进行容器管理。同时还有一些亲和性的管理、依赖性的管理,还有端口的管理。通过这些约束性条件之后,会根据各个节点的CPU或内存运行状况包括它的过滤策略选出来、剔除掉资源不足的主机,然后进行打分,比如对一千个节点进行打分。打分之后,然后进行策略选择。其实就是在同等条件下,是选择资源使用最多的节点,还是选择容器用得多的节点,还是容器用得少的节点,还是随机进行选择,其实整个Swarm调度策略就这么简单。然后调度的粒度基本上就是内存和CPU。

 

20161101215059

 

其实调度代码最核心的不像Mesos那种选举策略或者其他,它的策略比较简单,你可以看使用的资源,占的比例,进行打分。当所有有CPU资源和内存资源都同时满足的时候,那就证明资源是可以用的。它的策略很简单,就是把两个分加起来,这就是它的调度算法。如果大家有更复杂的一些资源调度框架,我不建议用Swarm,它支持得不太好,当然对内存和CPU这种限制,是可以满足我们需求的。还有一个坑就是它的资源创建只与容器create时的配置有关,与运行时实际使用的资源情况无关。比如第一次启动的时候用Swarm配置了8G,但其实只使用了2G,最后的算法是永远认为它用了8G,它在Cgroup文件里面进行了限制,与实际使用时无关,只有容器启动的时候与它分到的资源数有关系。

动态调度那一块,微博整合了Mesos、Swarm包括DockerDeamon直接下发,,现在服务器单机或者是按批次来上线的时候,我们会有Docker deamon下发的策略。对分布式调度框架进行封装,包括SwarmMaster高可用、多机房的自动适配、容器资源评估、容器资源监控,这都是我们的动态调度需要做的东西。

编排与实现

20161101215107

 

简单说一下服务编排,刚才三驾马车底层和主机层讲完之后,然后进入资源调度,上面就是服务的编排。服务之间的依赖、容器之间的依赖很多都在服务编排层去做,当然我们没用Compose或者其它一些组件来用,因为场景更复杂无法满足。我们在编排层自己定义进行解决,用编排层的工具进行解决。内网的共享池加上公有云组成一个共享池,大家从共享池来拿资源。当然,也会按照不同的服务池进行切分。整个流程的发起是在编排层,它会向调度层发起,调度层如果有资源就进行资源调度,如果没有资源的进行资源申请,然后初始化,服务上线。

拿一个现实的例子来说,如何申请阿里云机器。这是阿里云的机房,三个机房,选择哪个交换机,16核16G要一百台,这是刚才定义的VM镜像,就是操作系统镜像。选择16核16G内存,创建100台的机器,这样就有了100台物理机。当然,你可以向内网私有云进行创建。如果没有资源其实要资源申请,向共享池发起申请,申请之后会入到Buffer池,Buffer池进行初始化。这个初始化要实时生成报告来告诉你失败,然后实时重试。一切就是自动的,有一个初始化报告。初始化完成之后,还有一个实用的经验就是大家不要把自己的容器类型或者容器的资源类型切割的力度太散,微博基本上是定一个通用的标准,运维的复杂度一下子降低了,比如dP01、dP02、dP03、dP04,基本上按照业务来分四到五种类型就可以了。容器的类型越复杂,资源管理就越复杂。我们也很简单,这是微博的RPC服务,这是Web服务,后面还有一个类型是缓存服务,按照不同的业务进行容器的划分。你的业务通过调度下发给我,我就知道要的是这种容器类型,我给你编排,尽量减少用户自定义的数量,减少用户使用复杂度。对每个任务来说,我们会有一个整体的任务监控,然后实施成功、失败都可以提示,包括刚才说的整个初始化、包括服务发现,都会有任务框管理。任务的耗时,也会进行监控。

 

20161101215117

 

这个图是整个流程,一键扩容,管理员向混合云平台发起,第一步进行资源的评估,然后根据你的配额,向公有云和内网的私有云进行拉资源。如果资源获取到进行初始化,初始化完毕发起容器调度,通过Swarm或者通过我们自己的调度框架进行调度。调度完之后进行容器的启动、服务的部署,服务的部署之后进行服务发现。我们在每个容器里面还有一个运维,业务上分为两个容器,一个是业务容器,一个是运维容器,运维容器的组件就是把监控的组件进行推送,推送到日志中心,生成一些监控数据。同时要机器进行创建,你的业务监控随时可以马上监控到。

 

20161101215125

 

现在说一下比较重要的服务发现,容器启动的流量怎么过的,就是容器编排。容器编排其实是一个大的概念,因为怎么样跨IDC、跨机房,不同的服务池你怎么样更快更便捷的进行服务发现。这是微博的,当然微博是有内网机房和阿里云的机房,有不同的服务,如何快速的服务发现。简单说一点业界比较通用的就是NginxReload,当然你在大机房情况下可以验证一下,它会有10%的性能损耗。大家可以看这个开源地址https://github.com/weibocom/nginx-upsync-module,是基于Consul的自动服务发现。因为使用容器,你的变更肯定会非常频繁,降低它的性能损耗上,服务发现也是很重要的一个方面。还有一个特点是公有云上它会有20%的性能差,同样内网是16核16G或者你的容器资源是16核16G,但是如果你用阿里云或者你用公有云资源的话,它会有20%的性能差,尽量让你在服务化进行配置的时候把你的权重调低。比如公有云上整体权重为20,权重调为16,这样才能达到你的性能和内网是一致的,和你自己的宿主机是一致的权重。

RPC服务大家也知道了,这是Motan的RPC框架,它是支持跨IDC的服务发现,也支持按权重、按机房来自动调配。

 

20161101215134

 

春晚要保证整个体系没有问题,还得从整体的运维架构上包括监控体系、容量评估、干预手段,微博都有一个完整手段进行解决。监控基本上分为四类,一个是作战类监控,就是云上的服务器数,包括你的容器数量、专线带宽、实时容量。实时报警类的是接口监控,超过阈值就会报警。监控类,我们会有QPS监控、平均耗时、4XX和5XX。问题节点监控有单机的slow、资源slow、分布耗时,这些基本上都是可以认为单机和单容器的一个slow,是对容器进行单机和整体的监控。整体的一个监控体系,微博是把一些业务日志进行挂载到硬盘,然后通过logtailer推到一个日志中心,日志中心进行收敛计算之后通过Graphite的展示,没有特别针对容器监控组件,是把业务日志进行落地,推动监控中心进行监控,生成监控页面。

很重要的几点,大家一定要对单机容器或者是总体监控,因为在公有云的时候,它会有一些超买问题,你不确定哪个容器会发生问题的,所以你可能开一百台有二十台容器莫名会有问题,单机性能的恶化也会很严重的,大家一定要把监控做到这种力度,这样方便问题排查。错误响应是多少,超过一个阈值,我们会把这个容器进行自动摘掉。容量评估系统,就是根据你单容器的平均系统指标包括你的QPS业务指标,这都可以自动进行设置进行,看你的线上,比如说你可缩容多少台、可扩容多少台。我刚才提到的这些缩容和扩容,如果缩容就进入共享池,扩容就从共享池里面进行容器的弹性调度,会有一个容量评估的决策。整体的干预手段基本上也有重启、回滚、紧急上线、服务降级、封杀,包括流量切换,流量切换有跨IDC、跨服务池的,还有限流的一些数据修复,等等这些干预手段。这些干预手段其实有一些是带容器级别的操作。

 

20161101215142

 

春晚实战&总结

这些做完之后,再看一下春晚的整个实战,基本流程是三分钟机器创建,然后Ansible进行初始化,Registry进行拉镜像,然后是预热镜像,进行容器调度,包括服务发现。整个完成之后,大概是十分钟。

 

20161101215151

 

这是一个微博内部阿里云多机房的架构,可能大家可以了解一点,这是微博内网标准的一个前端机、队列机,然后消息队列、缓存、数据库,然后在阿里云上同步有一个类似的架构。

 

20161101215159

 

微博常规部署会在阿里云上部署、缓存。在正常情况下阿里云上=只有十到二十台机器,但是在峰值流量的情况下我们立马扩到一千到两千+的容器。容器进行扩容,主要是web服务器或者是RPC服务,然后我通过服务发现把流量引入。

 

20161101215206

 

大家可以看一下这个作战图,刚才我提到一个监控数量,包括服务池水位,包括服务池容量承载倍数、专项带宽、各业务方占用带宽、各服务池用的容器数量都会有一个实时的监控进行监控。

 

20161101215213

 

最后说一下微博遇到的一些问题,比如阿里云部署,在公有云上部署缓存服务器的时候,会发现它的PPS经常被打满。阿里云的北京A区7W,C区10W+,当你的PPS打满之后,你的缓存或者服务会急剧下降。我们通过扩容缓存来解决。还有一些莫名的机器性能差,这就依赖大流量高并发服务的时候你的单机监控,要随时发现,自动把性能差服务平滑摘掉。还有一个刚才提到的在公有云上使用阿里云SLB负载均衡的时候,当大流量大概4、5G的时候,大流量下肯定会把SLB打垮。此外,就是专线带宽的时候,跨机房的时候要注意这些专线带宽。

刚才讲了整个DCP扩容的一个流程,自动扩容、云平台服务管理,DCP平台优势可能是高并发、大流量的场景实际场景应用,微博也会把我刚才所有讲到的东西进行开源,就是DCP开源项目,12月份也会开源,到时候大家也可以一块把它建得更好。

分享到:更多 ()