内容来源:2017 年 12 月 3 日,小米资深架构师孙寅在“IAS2017互联网架构峰会”进行《小米弹性调度平台Ocean——从PaaS带DCOS》演讲分享。IT 大咖说(微信id:itdakashuo)做为独家视频合做方,经主办方、演讲者以及微信公众号——小米运维(微信id:MI-SRE)审阅受权发布。
docker
阅读字数:3244 | 9分钟阅读数据库
本次将为你们分享小米的弹性调度平台Ocean以及想过的体系建设历程。缓存
Ocean起源于2015年年末,当时小米的第一代运维基础平台已经成熟,拥有包括监控、发布、域名、服务器流转等一系列核心组件。可是咱们不只仅知足于工具型的平台,还但愿平台拥有PaaS 的能力,进而能够演进成为DCOS,甚至是DCBrain。安全
图中绿色的部分表示建设完成,橙黄色是正在建设,灰蓝色则是尚未建设或者未完成。服务器
左侧部分为所依赖的基础架构的组件,右侧是但愿得到的功能,中间是主要的基础架构。微信
Ocean相比其余的PaaS平台有两点不一样,首先Ocean很注重与基础设施的联合设计,保障基础设施的总体性。其次不一样于其余将无状态做为主要目标的PaaS平台,Ocean更重视有状态服务的PaaS与在此之上建设的SaaS系统与其所带来的能力。数据结构
前四项是全部的PaaS平台都具有的能力,后两项则须要和基础设施配合共同联合设计才能完成的功能。架构
服务树是很是重要核心的基础组件,主要定义组件和服务之间的关系。数据结构很简单,就是为服务器打TAG,再经过定义这些TAG的顺序来展示整个树的结构。负载均衡
服务是服务树内以8个TAG一组定义的全局惟一的服务标识,做为整个运维基础设施全部组件的统一串联的粒度。Ocean每启一个容器都会在容器内植入docker init进程,把本容器的IP经过打TAG的方式注册进服务树,而后经过注册的动做联动其它基础设施组件产生效果。框架
免密安全登陆基于服务树节点受权,同时每次登陆都须要进行双因素的认证。Ocean在启用容器后,同时也会在容器内植入免密安全登陆的服务端,这样当任意用户的帐号拥有了某一个服务树节点的权限后,就能在登陆时完成认证和受权,从而使得物理机和容器的登陆效果一致。
咱们的监控系统叫作Open Falcon,目前已被开源。而全Push采集是Falcon比较重要的设计,全部的监控数据都是经过Falcon-agent推到serever端。这有两方面的优势,一方面和弹性环境更加亲和, 由于Agent会从部署的位置自动采集数据而后上报。另外一方面使设备具备策略自发现能力。
自动扩缩经过与Open Falcon对接完成。Falcon会自动采集CUP IDLE、MEM FREE、PROC QPS、PROC DELAY这四个基础指标,以此来提供自动扩缩的能力。
当某个用户要基于某个指标进行扩缩,就会自动的为该条指标添加一条集群监控策略。当监控策略知足预值要求时会自动经过HooK方式回调Marathon API完成自动扩缩。目前咱们最短5s触发伸缩。
云原生环境与物理机运行不一样,在物理机不管出现什么问题均可以在原先的位置查看日志,而在弹性环境中容器挂掉后,要从整个资源池找回已经挂掉的容器的日志是比较麻烦的,即使找到了也很难暴露给用户查看。
所以咱们采用了ELK的解决方案,并将其中的L改为更轻量的客户端FileBeat。若是FileBeat运行在容器上,一旦容器挂掉后,FileBeat的一些日志就会来不及传输,因此咱们将FileBeat运行在物理机上,同时在容器退出后延迟清除容器。
咱们还制定了用户日志目录规范,经过修改FileBeat让它与目录的规范相配合,自动为日志添加标签数据。
云原生若是没有服务发现整个弹性环境就没法动态起来,对于服务发现,不一样类型的服务获得的最佳实践也不一样。通常业务的程序会使用比较成熟的RPC框架,而对于第三方开源组件每一个都会有不一样的最佳实践。
不少时候有些业务的数据或接口有很强的敏感性,在物理环境下咱们会使用IP白名单的方式进行认证受权以及保障安全。可是这种方法在动态环境下并不适用,因此要提供一种在动态环境下的动态安全的解决方案。
假设在模型中客户端被部署在Ocean平台内,Docker init会把这些运行在Ocean平台的Job对应的IP和Job信息注册进集群 ,这时服务端就仅需嵌入白名单SDK和配置客服端的JobName,还能够经过IP加JobName共同防护ZK故障。
MySQL方面也存在动态安全问题,一般状况下咱们会对库和IP进行受权,而动态环境下则要考虑如何进行动态IP受权。 与以前不一样,数据库并不须要用户去植入SDK,可是要新增数据库实例受权的过程。咱们这里是将Docker init和AppA Proc做为认证信任源,Docker init会向MySQL Auth宣告本身所属的Job,接着MySQL Auth会到Marathon内查询来源IP与JobName匹配状况,匹配成功认证经过。
建立ELB时须要绑定Ocean的中一个Job,当Job部署到Ocean后不管实例IP发生任何变化,咱们都要作到LVS相应的RS都要跟随变动。
所以咱们每建立一个ELB其实都会同时建立一个域名,而且按照运营商自动划分线路,这样就能让用户在使用时不感知的获得最佳实践,同时节省带宽资源。另外docker-init和ELB服务都会动态更新LVS配置,这主要是为了让ELB服务的可用性依赖降低。
在弹性环境下无状态服务都相对简单,改造也很是容易。可是有状态服务就存在不少麻烦的地方,例如数据状态须要迁移、服务发现的最佳实践也要植入。所以咱们将这些有状态的服务抽象成服务化组件的形态,让用户能够方便运行一个服务集群。
当用户经过提交参数建立MySQL集群时,会由Manger模块提供所要建立的数据库原信息数据给Marathon,而后在Marathon内建立DB APP Group,这个Group中会有DB Proxy 和DB 两种App。
在启动时候DB APP内会经过抢锁的方式产生三种角色,这些角色再经由所提供的配置运行起来。
DB Proxy APP在运行的时候会自动感知到抢锁获得的角色,并接收流量和配置。最后经过Mesos-Dns将 DB Proxy的域名暴露给用户。
整个流程中会使用Zookeeper自动恢复数据包括主库切换等一系列的事。
缓存服务通常使用分片方式,可是每一个分片保存一个实例的话,当前实例挂了就会形成缓存失效,还会穿透到数据库,对业务产生影响。
理想的解决方案是每分片多副本。而咱们提供了Memcached和Redis两种缓存服务,因为Memcached自己不支持每分片多副本,因此要在此之上引入Memcached Router。Redis则能够直接使用Redis cluster。
故障自愈用到了开源框架StackStorm,它是事件触发自动化处理的框架。
整个过程当中由Sensors收集信息源,Rules完成须要统计计算或者判断触发的逻辑定义,当触发时随之启动一个Workflows,每一个Workflows对应一组Actions。另外中心还有着能够贯穿全部模块的Audit模块,可以知道整个生命周期内所发生的状况。
在实际的建设时咱们会将内部可以产生信息的基础设施做为输入对接到StackStorm中,StackStorm内的触发组件则对接到咱们内部的控制系统。