您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
   
 
 
     
   
 订阅
  捐助
DockOne技术总结整理(五)
 
作者:CMGS 来源:DockOne.io 发布于 2015-8-26
   次浏览      
 

DockOne技术分享(十四):腾讯蓝鲸数据平台之告警系统

蓝鲸是互娱运营管理中心自主研发的一套具有多项探索式创新的运维平台。本文是我参与蓝鲸数据平台的建设过程中的一些心得体会,关于整个蓝鲸平台的更多内容,可以阅读另外的这篇文章。

很多人在搞ELK,很多人也在搞Storm。更多人在用传统的Nagios、Zabbix等监控工具。Jason Dixon在2012就意识到这些工具的问题是每个人都想做到大而全,实际上我们更需要的是一对小二精的组件拼装成一个个性化的解决方案。推荐大家去看一下他的演讲视频。

这是Jason Dixon所构想一个组件图。他认为不同的开源方案应该专注于提供好这些组件。

Caskey Dickson 也有同样的设想,并且提出目前的很多组件仍然是缺乏好的提供者的(比如海量metric存储和任意维度聚合):https://www.usenix.org/confere ... oring。

这是他在ppt里画的一个组件图,并且评价了一下主流的开源组件。

受到前辈们的影响,这个是我厂的一个告警平台的数据流图。

下面按照顺序解释一下这个流程图中的各种组件:

采集/收集:数据可能来自于业务的db,可能来自于日志文件,可能是由业务程序内置上报的。通过各种手段采集收集到“原数据库”里。什么是“原数据库”?比如kafka队列。比如logstash上报前把数据汇总到的redis数据库。“原数据库”的存在是为了把分散的数据汇总到一处,方便后续的处理。

索引:索引主要是为了日志存在的。为了让日志可以检索,需要把日志数据进行切分,提取出字段和关键字录入到“检索库”里。这就是著名的ELK最擅长的事情。Logstash负责索引操作,Elasticsearch充当检索库的角色。

统计:指标库最常见的就是给每个ip存放一份cpu使用率的时间序列。对于这种情况,原数据采集了之后直接录入指标库就行了。另外一种比如是nginx的access log,采集到之后需要经过统计才能得出某某url在5分钟内被访问了xx次的数据。统计最简单的形式比如statsd,复杂的可以用storm写自定义的流式计算任务,更复杂的甚至涉及机器学习,比如summo logic。指标库一般使用的是opentsdb等时间序列数据库,但是我强烈推荐Elasticsearch:http://taowen.gitbooks.io/tsdb/content/

异常检测:传统的告警就是比对一个静态的阈值。对于错误率,访问延迟等指标用静态阈值确实是没有问题的。但是对于5分钟内的收入,访问人数等综合的业务指标很难用静态阈值去做检测异常。复杂的异常检测会利用曲线的时间周期性,和相关曲线之间的相关性去定义动态的阈值。etsy的skyline是开源组件里比较著名的一个。

告警:告警和异常检测是两个过程。不是每个异常都值得通知运维跟进处理(起码可以做一个频率收敛),也不是把原始异常以xx小于xx这样的形式告诉给运维就可以了(可以把告警相关的故障一起通知了)。这里个从异常到告警的过程需要做到确认这个异常是一个值得通知的告警,并且能够做一个初步的故障定位。最简单的定位的手段是就把其他部门的告警(比如网络部门的网络质量告警,安全部门的DDoS告警),以及流程单据(发布单)做为事件纳入事件库。通过查询事件库定位原因。

在这样的一个提下下,很多零散的工具做的事情被整合在了一起:

拨测:定时curl一下某个url,有问题就告警。这个是走 原数据=>直接录入为异常=>告警

日志集中检索:ELK的经典用法。走 原数据=>检索库

日志告警:5分钟Error大于xxx次告警。走 原数据=>实时统计出指标=>检测异常=>告警

指标告警:cpu使用率大于xxx告警。走 原数据=>录入到指标库=>检测异常=>告警

把不同的告警和监控策略整合到同一个数据管线的好处是简化了整体的架构,剔除了重复的模块(比如上报和原数据汇总等模块)。而且有利于各司其职,专业化纵深发展。

目前开源组件还比较缺乏的有这么几块:

指标库需要海量存储海量聚合能力,开源的有 Druid.io Elasticsearch Crate.io 等

异常检测,缺乏真正实用的。算法其实不用很复杂

故障定位和收敛,缺乏真正实用的。Flapjack的实现太简单了,Riemann又太小众了

实时统计,缺乏成熟的解决方案。Storm就是一个底层的执行引擎,而Spark还缺少时间窗口等抽象。

日志自动分类,还没有开源工具可以做到 summo logic 那样的效果

自定义曲线和仪表盘:类似kibana的工具还是太少

我厂的监控告警平台当然是把这些都实现了。很多创业公司(比如刚冒出来的jut.io)也整合出了不错的完全解决方案。但是更多的小厂还是在用Nagios和Zabbix等传统的工具,再加上个ELK看日志。开源社区在方面还是大有可为的。说实话,这个东西卖钱不好卖。更多的公司还是会选择拿开源工具自己搭一个凑合用的。

告警的本质

没有多少系统的告警是设计得当的。良好的告警设计是一项非常困难的工作。如何知道你收到的告警是糟糕的?多少次你收到了告警之后,立即就关掉了的?是不是成天被这些然而并没有什么卵用的东西给淹没?最常见的告警设置:cpu使用率超过90%,然后告警。这种设置在大部分场合下是没有办法提供高质量的告警的。

高质量的告警应该是这样的:每次收到之后你可以立即评估影响的范围,并且每一个告警需要你做出分级响应。所谓每个告警都应该是,actionable的。

告警的实质可以用下图表明:

服务器的设计应该是以这样的无人值守为目的的。假设所有的运维全部放假了,服务也能7*24自动运转。

告警的实质就是“把人当服务用”。在一些事情还没有办法做到程序化执行的时候,用告警通知人的方式去干预系统达到修正的目的。一次告警就像一次服务调用一样。如果告警了,但是收到告警的人并不需要做任何处理,那么这就是一种DDoS攻击,攻击的是运维的幸福生活。

很多时候,告警通知人去干的事情是真的可以被自动化掉的。比如服务器挂了,换一台上来。在小一点的系统里,可能就是停机一会,人工来处理换一台冷备的机器上去。大一点的系统,因为服务器多了,天天都挂可不行,必须是热备的,系统自动切换到备机。再大一点的系统,因为切换实在太频繁了,故障机的退库,备机的保有都变成了一种管理负担,那么可以和其他的运维流程打通变成完全自动化的系统。只是因为业务处理不同阶段,选择不同的实现策略而已。业务量小,拿血肉当机器用,有的时候更经济而已。当然对于那个被当成机器人来用的哥们来说,生活确实有点不公平。

告警对象

告警对象可以分为两种:

业务规则监控

系统可靠性监控

对于业务规则监控可以举一个游戏的例子。比如DNF的游戏角色在一定装备的情况下,单次打击的伤害输出应该是有一个上限,如果超过了就说明有作弊的情况。又比如斗地主游戏里一个人的连胜场次是有一定上限的,每天的胜率是有一定上限,如果超出平均值太多就可能是作弊。业务规则监控的不是硬件,也不是软件是否工作正常。而是软件是否按照业务规则实现的,是否有漏洞。也可以理解为对“正确性”的监控。

系统可靠性监控是最常见的监控形式,比如发现是不是服务器挂掉了,服务是不是过载了等等。对于大部分后台服务,系统可以抽象建模成这个样子:

对于这样的系统可以采集什么指标?

请求数,请求到达速率

正常响应数,正常响应占比

错误响应数,错误响应占比

响应延时

队列长度,排队时间

实际的情况是,几乎任何系统都不是孤立运行的。而是这样的:

一个DB会依赖于底层的cpu,内存,磁盘等资源。一个Http服务会依赖于底层的DB服务。一个应用会依赖于数个底层的RPC服务。

于是又多了几个指标

资源A的调用量(比如CPU使用率)

资源B的调用量(比如内存分配和释放)

资源C的调用量(比如网络发送包量)

...

这种层次结构,一般来说简单来说可以分为四层:

产品策略和营销:它们决定了根本的请求到达的速率

应用层(更粗俗一点可以叫web层):最上层的胶水

服务层:db,各种RPC服务,以及层层嵌套的服务

硬件层:cpu,内存,磁盘,网络

因为这样的一个依赖层次。上一层对下一层的资源消耗量变成了下一层的请求数。比如Http服务消耗了多少DB的资源,就对应了DB服务需要处理多少请求数。DB繁忙与否取决于Http服务请求,Http服务请求繁忙与否取决于多少人打开客户端,多少人打开客户端又取决于产品策略和营销活动。这种层次结构决定了单纯跟踪一个指标,比如绝对请求数,很难说明这一层的服务是否出现了故障。

有这么多层次,每层又有很多指标可以采集。那么应该采集什么指标,用什么告警策略去告警呢?最前面已经提到了告警必须是actionable的,但是实际情况下只有这种纲领性要求仍然是不好操作的。

至少可以提几点不应该做的事情:

不应该用采集的难度决定你使用什么指标去告警。很多情况下cpu使用率可能是最好采集的,但是未必是最值得告警的。

不要给运维他们想要的告警,而是要做“真正”想要的告警。大部分情况下,人们告诉你的是一个解决方案。运维告诉你它需要对db进程的cpu使用率超过x%的时候告警,它给你的是一个他认为最优的解决方案。但是他真正想要的是知道db服务是否有异常,cpu使用率超过x%未必是最好的告诉你服务是否出现异常的指标。

盲目地采集那些容易获取的指标,并随意地设定阈值告警是大部分糟糕的告警质量的根源。

监控的指标和策略

那到底应该采集什么指标呢?我认为大部分的系统可靠性监控不外乎三个目标:

is the work getting done?系统是否在持续完成其设定的工作。

is the user having good experience?用户体验是否好。

where is the problem/bottleneck?问题或者瓶颈在哪里。

其中最核心最关键的是第一个问题,is the work getting done。对于数据库来说,我们可以采集:

cpu 使用率

网络带宽大小

db请求数

db响应数

db错误响应数

db请求延迟

显然要回答一个db是否完成了其指定的工作,更应该关注的指标是这两个:

db请求数的绝对量

db正确响应相对请求数的占比

这两个指标相对于采集什么cpu使用率更能说明问题。不仅仅是db,各个层次的服务都可以用请求量和正确响应占比来反映其工作状况。比如http请求数(对比http正确响应数),比如app打开次数(对比服务端记录的在线人数)等等。

为什么cpu使用率不能说明问题?大部分时候,我们并不关心cpu本身,而关心使用cpu为资源的服务。所以cpu使用率只是一种资源的请求数而已。与请求数相关的一个概念是saturation(上限),当上限达到的时候,处理开始排队,延迟开始变长,错误率开始升高。那么cpu使用率是不是能够说明上限呢?cpu使用率的上限以100%记,那么90%开始告警不是很合理吗?毕竟cpu 100%了几乎可以等同于db无法正常处理请求了。

这种利用底层资源调用量,评估其是否达到上限的做法有两个根本缺陷:

你无法知道上层服务可以把底层资源利用到什么程度

底层资源的 saturation 未必可以容易度量

具体来说,db是不是可以真的100%利用cpu是位置的。假如请求里锁,或者sleep,那么也许cpu永远也无法达到100%。90%可能就是极限了。而且现代的cpu是多核的,如果请求处理只能利用单核,处理在多个核之间跳跃,对于一个核来说永远也不会一直保持100%。

对于cpu可能其上限真的有一个100%的值。但是对于很多非硬件的服务,比如你是一个登陆服务,依赖于一个db。那么这个db每秒可以处理的不同sql组合数是很难度量的,绝非和磁盘一样有一个mb/s的极限绝对值可以做为对比。

而且度量底层资源的使用还有一个缺陷是你无法枚举出所有依赖的资源的。所以与其这么绕弯子地通过底层资源来间接监控上层服务是否正常,还不如直接测量work是不是getting done呢。

对于第二个问题,is the user having good experience?可以采集的指标为

平均排队时间,平均总响应延迟

99/95/90 percentile的排队时间,99/95/90 percentile的响应延迟

这里的用户不一定是指人或者玩家,可能是上一层的服务调用方,另外一个系统。

第三个问题就是所谓的故障定位。要是人工来做的话,最常见的做法是收到了告警,然后登陆CRT,开始敲各种命令查找原因。对于系统来说,最合适的做法不是出了问题再去执行一堆命令,而是:

每个层次都对自己做告警

顶层服务出了告警触发自动定位程序

按照服务的依赖关系和大致的时间范围,定位到告警之间的关联,从而找到出问题或者瓶颈的地方

当然实际情况是很复杂的。很多原因和结果是互为因果的。两个告警是两个现象,还是一个原因一个现象实际上很难说得清楚。

从告警算法的角度来讲,对成功请求率,或者平均响应延迟做告警是非常容易的。静态阈值大家看不起,觉得简单。但是大部分告警用静态阈值就可以解决问题。

理论与现实

那告警要不要高难度的算法?我的观点是采集到了正确的指标,是不需要复杂算法的,就是静态阈值都可以搞得定。

但是至少有三种场合需要算法:

无法直接采集到错误数:需要对错误日志的自动分类

无法直接采集到请求成功率:需要对请求数或响应数的绝对值做异常检测

只有总数,无法采集到其中的每个细分构成项的占比:需要对参与的factor进行算法拟合

其实这三项都是一个主题的,当你无法直接获取到告警所需的指标的时候,事情会变得复杂很多。有一个比喻是:最近NASA宣布的地球孪生兄弟Kepler 452b。如果我们的探测器可以跑到1400光年之外,发现他将是非常容易的事情。正式因为直接获得数据非常困难,所以科学家才需要根据行星阻挡恒星时引起的亮度变化(所谓掩星法)来发现这些遥远的星球。

采集所需的指标的困难可能是几方面的因素。一种原因是采集本身是非常消耗资源的事情。比如获取每个mysql查询所消耗的cpu。跟踪每个请求处理过程是不可能的。这个时候就需要算法的帮助了,可以仔细看一下vividcortex的视频。

更多情况是采集指标困难是D/O分离造成的沟通问题,运维需要的指标需要开发去埋点,而开发埋点的地方又需要运维去做告警。很多时候退而求其次就会造成,有什么指标就用什么指标的状况。比如虽然没有请求响应的错误数,但是错误基本上都会有错误日志记录,根据错误日志滚动的快慢可以大致知道是不是出了问题。这就引入了一个非常困难的日志分类问题,什么日志代表了正常,什么日志代表了异常,异常又非了哪些类型?这个方面算法做得好的是summo logic公司:https://www.sumologic.com/ 。为什么这种opsdev(嘲讽devops那)公司如此热衷于算法?对于他们来说好处是显而易见的,客户需要做的改动越少,接入成本越低,客户面就越广。但是拿机器算法去挖掘海量日志真的是回答:is the work getting done?的最佳手段?显然不是。这就是大炮打蚊子。日志的存在是用于解决问题,而不是有了海量日志了,如何用好“它们”变成了问题本身。

第三类情况是没有办法采集到请求成功率,只能对绝对的处理成功的量。只有这类数据要告警,就无法做简单的静态阈值了。对于延迟,一般可以定一个业务上可以接受的延迟上限。对于成功率,也可以定一个可接受的成功率上限。但是对于绝对的处理量,是没有办法简单地比较一个静态阈值就可以判断是正常还是异常的。

在讨论如何实现之前,再强调两点:

处理成功的量不是度量is work getting done的最佳指标。费事费力去搞算法,不如直接把成功率指标给采集了。

处理成功的量,还取决于请求数。而请求数根本上是取决于上层服务了。你是一个dba,发现db的每秒处理的请求数陡降了。这说明是db故障了?还是app故障了?都有可能……最最上层是产品和营销。你发现一个业务的注册量相对前几天变少了,这个是不是说明注册服务出问题了?也需是产品太烂了,游戏根本没有人来玩。也可能是营销手段的营销,不送金币了,玩家没积极性了。

异常检测

只有请求数,没有参考的上限值(saturation),也没有成功率,没有失败率,怎么检测异常?

上图的黄线是昨天的值,绿线是今天的值,大部分服务监控的曲线图都长这样。可以得出四个思路:

曲线平滑:故障一般是对近期趋势的一个破坏,视觉上来说就是不平滑

绝对值的时间周期性:两条曲线几乎重合

波动的时间周期性:假设两个曲线不重合,在相同时间点的波动趋势和振幅也是类似的

有一个长度可观的坑:当曲线开始回升到历史范围的时候,一般可以确认这个时间段是真的故障了

从这四种直觉展开,可以得出各种或复杂或简单的算法。下面要讲的算法都是非常简单的,无需很高深的数学知识。

基于曲线的平滑性的检测

这种检测的根据是在一个最近的时间窗口,比如1个小时。曲线会遵循某种趋势,而新的数据点打破了这种趋势,使得曲线不光滑了。也就是说,这种检测利用的是时间序列的temporal dependency,T对于T-1有很强的趋势依赖性。业务逻辑上来说,8:00 有很多人登陆,8:01 也有很多人来登陆的概率是很高的,因为吸引人来登陆的因素是有很强的惯性的。但是7.1很多人来登陆,8.1也有很多人来登陆的惯性就要差很多。

基于近期趋势做告警,就需要对曲线的趋势进行拟合。拟合有两种方式,moving average 或者 regression。这两种拟合方式有不同的bias(倾向)。

这就是一种moving average的算法图,叫做exponentially weighted moving average。它的计算非常简单

x是实际值,s是ewma计算出来的平均值。也就是下一点的平均值是由上一点的平均值,加上当前点的实际值修正而来。这个修正的比例,就取决月这个alpha的decay factor的大小。视觉上来说就是ewma曲线是否紧跟实际曲线,也就是平滑程度。

有了平均值之后可以计算方差,方差乘以一定的倍数可以得出对于振幅的容忍范围。比较实际的值是否超出了这个范围就可以知道是否可以告警了。超出了上界,可能是突然用户量突然激增了。超出了下届,可能是营销活动结束了,用户快速离开,也可能是光纤断了,玩家掉线了。想要了解更多关于ewma的算法细节:关注Baron Schwartz。

moving average认为曲线是趋向于历史的,如果曲线的势头是上升,那么它认为下一个点应该是开始下降的。regression认为曲线是趋向于未来的,如果曲线的势头是上升,那么它认为下一个点应该是保持这个上升势头。还有更复杂的模型是综合了moving average和regression的。无论是哪种算法,用过去10分钟预测下10分钟是不可能精确的。如果这种预测可以精确,那么股神早就诞生了。使用moving average,可能会掩盖故障产生的下降(因为其bias是下降)。如果使用regression,那么又有可能把没有上升得那么快当成故障了(因为其bias是上升)。

这种基于近期趋势计算方差的算法还有一个缺陷是当前面几个点振动很大的时候,方差值会被搞大。后面的故障就被掩盖了,使得连续的故障点无法被检测到。其实也就是算法对于什么是正常是没有概念的,它认为过去的历史就是正常。如果过去几分钟处于故障中,那么故障的曲线就是正常。

实际使用中发现这种基于曲线平滑度的算法的优点有:

依赖的数据少,只需要近期的历史,不依赖于周期性

非常敏感,历史如果波动很小,方差就很小,容忍的波动范围也会非常小

缺点也是显著的

过于敏感,容易误报。因为方差会随着异常点的引入而变大,所以很难使用连续三点才告警这样的策略

业务曲线可能自身有规律性的陡增和陡降

最佳的使用方式是不用一根曲线做告警。结合几条相关的曲线,如果同时出现平滑度破坏的情况,而且与业务规律的趋势相背离(比如在线人数降低,登陆请求数增高)则可以认定为业务出现故障。

基于绝对值的时间周期性

上图中不同的颜色代表了不同日期的曲线。很多监控曲线都有这样以一天为周期的周期性(早上4点最低,晚上11点最高之类的)。一种利用时间周期性的最简单的算法

min(14 days history) * 0.6

对历史14天的曲线取最小值。怎么个取最小值的方法?对于12:05分,有14天对应的点,取最小值。对于12:06分,有14天对应的点,取最小值。这样可以得出一条一天的曲线。然后对这个曲线整体乘以0.6。如果几天的曲线低于这条参考线则告警。

这其实是一种静态阈值告警的升级版,动态阈值告警。过去静态阈值是一个根据历史经验拍脑袋的产物。用这个算法,其实是把同时间点的历史值做为依据,计算出一个最不可能的下界。同时阈值不是唯一的一个,而是每个时间点有一个。如果1分钟一个点,一天中就有1440个下界阈值。

实际使用中0.6当然还是要酌情调整的。而且一个严重的问题是如果14天历史中有停机发布或者故障,那么最小值会受到影响。也就是说不能把历史当成正常,而是要把历史剔除掉异常值之后再进行计算。一个务实的近似的做法是取第二小的值。

为了让告警更加精确,可以累积计算实际曲线和参考曲线的差值之和。也就是相对于参考曲线下跌的面积。这个面积超过一定的值则告警。对于深度下跌,则累积几个点就可以告警。对于浅度下跌,那么多累几个点也可以告警出来。翻译成人话就是,一下在跌了很多,则很有可能是故障了。或者连续好久都偏离正常值,那么也很有可能是出问题了。

优点:

计算简单

可以确保发现大的故障,出了告警一定是大问题,可以直接打电话

缺点:

依赖周期性的历史数据,计算量大,而且无法对新接入的曲线告警

非常不敏感,小波动无法发现

基于振幅的时间周期性

有些时候曲线是有周期性,但是两个周期的曲线相叠加是不重合的。比如上图这样的,曲线整体的趋势是网上的。两个周期的曲线一叠加,一个会比另外一个高出一头。对于这种情况,利用绝对值告警就会有问题。

比如今天是10.1日,放假第一天。过去14天的历史曲线必然会比今天的曲线低很多。那么今天出了一个小故障,曲线下跌了,相对于过去14天的曲线仍然是高很多的。这样的故障如何能够检测得出来?一个直觉的说法是,两个曲线虽然不一样高,但是“长得差不多”。那么怎么利用这种“长得差不多”呢?那就是振幅了。

与其用x(t)的值,不如用x(t) - x(t-1)的值,也就是把绝对值变成变化速度。可以直接利用这个速度值,也可以是 x(t) - x(t-1) 再除以 x(t-1),也就是一个速度相对于绝对值的比率。比如t时刻的在线900人,t-1时刻的在线是1000人,那么可以计算出掉线人数是10%。这个掉线比率在历史同时刻是高还是低?那么就和前面一样处理了。

实际使用中有两个技巧:可以是x(t) - x(t-1),也可以是x(t) - x(t-5)等值。跨度越大,越可以检测出一些缓慢下降的情况。

另外一个技巧是可以计算x(t) -x(t-2),以及x(t+1) - x(t-1),如果两个值都异常则认为是真的异常,可以避免一个点的数据缺陷问题。

优点:

比绝对值要敏感

利用了时间周期性,规避了业务曲线自身的周期性陡降

缺点:

要求原曲线是光滑的

周期性陡降的时间点必须重合,否则误警

按百分比计算容易在低峰时期误警

陡降不一定代表故障,由上层服务波动引起的冲高再回落的情况时有发生

这种异常告警算法是比较优秀的。缺点也很多。所以可以进行一些修补凑合用。为了避免低峰时期,基于振幅百分比容易误警,可以加入绝对振幅的下限。业务上来说,就是小波动如果相对比率大,但是绝对影响范围小也是没关系的。对于冲高回落的问题,可以判断一下冲高的情况,对于冲高之后屏蔽一段时间。

基于曲线回升的异常判断

当我们看见图2的时候比图1更确认是故障了。为什么?因为图2中有一个明显的回升。算法其实和人眼一样。如果多等几个时间点,发现曲线回升了可以更很准确地判断“曾经”有一个故障。但是这种基于回升的异常检测是没有多少“告警”意义上的机制的。告警的作用就是让人参与干预,去帮助曲线回升。如果曲线已经开始回升,再告警不是事后诸葛了吗?

这种检测的意义在于机器复制告警的确认。当我们需要统计误警率,漏警率的时候。用另外一种视角的算法重新跑一遍可以统计出很多原算法的问题。同时也可以用半自动化的方式建立一个历史故障的样本库。这个样本库可以变成更复杂的机器学习算法的训练集。

总结

Key take away

高质量的告警是actionable的

不应该用采集的难度决定你使用什么指标去告警

不要别人做什么告警,你就做什么,要做“真正”有用的告警:特别是cpu使用率告警

is work getting done:请求数 + 成功率

is the user having good experience:响应延迟

只要采集对了指标,大部分时候告警不需要复杂算法

基于算法的异常检测:算法不难,实在必要也是可以做到的

DockOne技术分享(十五):如何在裸机中自动安装部署CoreOS和Kubernetes

本次分享的主题是:如何在裸机下自动安装部署 CoreOS + Kubernetes。主要从背景、工作原理、具体过程、采过的坑四个方面来分享。

先介绍一下背景

随着光音业务规模的上升,线上业务产品的数量及服务器的采购量也越来越大。当达到一定数量级后,就不能使用常规的维护方法来解决这些问题。

以前,一旦业务量上去,我们就不得不停下手头的开发工作,部署业务所需要的环境及线上调试,到最后,只有特别熟悉业务和代码的同事才能胜任此工作。为了解决这些问题,我们从前年开始就关注了LXC,并试着小规模地使用了一段时间,但是由于LXC本身存在一系列的问题,比如内核版本的限制及二次开发困难,没能大规模地推广。

后来随着Docker的发展及火热,我们也接触到了CoreOS,它的AB分区升级特性特别吸引人。使用后才发现,跟宣传写的不一样,还是需要重启服务器才能升级内核的,但是总的来说,结合Fleet的使用,可以动态地把业务迁到其它服务器,来达到平滑升级的目的,因此还是非常不错的。

我是从开发转到基础平台维护岗位的,所以希望用开发的方式来解决运维的问题,并想通过改变运维的方式的来加快业务研发的速度。但是真正专职做平台开发后,才意识到搭建整个运维体系是多么困难的事。所以,为了更快地构建我们的平台,业务的选型首选开源框架,然后再它的基础上,根据业务的需要做二次开发。借着Google的名气以及相对完善的生态圈,我们最终选择了Kubernetes + CoreOS + Docker,做为整个平台编排调度的基础。

我们每次采购机器,一般都是几百个节点,所以整个平台的部署就非常头疼,特别是CoreOS和Kubernetes,必须借助梯子才能安装和更新,让人非常不爽。前期的大部分时间都浪费在这上面了!

于是,写了一个简单的Yoo-Installer工具来解决这些问题,现在分享给大家。

由于想呈现最简单便捷的安装方式,结果没把握好时间,这次的分享准备不足,所以你们可以多提问,我多分享一些采过的坑。

项目代码我放到GitHub上了,代码还在不断完善中,如果有问题,可以直接在上面提Issue。另外,我们组的一个同事赵文来也贡献Kubernetes-client 的Nodejs版本,一并分享给大家:https://github.com/Goyoo/node-Kubernetes-client,希望能跟大家一起打造美好的Docker生态圈。

下面介绍Yoo-Installer是如何工作的

它共分为DHCP Service、TFTP Service、HTTP Service,其中HTTP Service 里包括了CoreOS的引导,安装到硬盘,Kubernetes的安装及其它服务脚本的初始化。

PXE引导

收到DHCP广播,获取IP

使用TFTP进行通信,传输CoreOS的基础IMGAGE

在内存启动CoreOS系统

系统启动成功后,下载脚本,执行安装Kubernetes及其它相关服务。

在这里需要分享几个点:

服务器的IP。在安装服务器前,应该确定好服务器的IP,因为IP在后面的安装是一个非常重要的变量。比如etcd的service IP,Kubernetes的Master IP都需要写入到配置里的。

我们是这样做的:我们的服务器是高密度刀片服务器,都配有管理模块。通过一些简单的API调用,就可以得到所有的网卡mac信息,与KVM的IP保持一定的逻辑关系,这样就可以保证服务器的IP有序,便于日后的管理与维护。(可以参考Yoo-installer项目的app/utils/IPMI/dhcpMacList.js,通过这段代码得到dhcpd所需要的配置格式,直接使用即可)。

CoreOS集群的安装方式

我们专门做了一个菜单,以满足各种场景部署的需要。

在Yoo-Installer里,我分了6个菜单,适合四种使用场景。

分别对应于官方的CoreOS集群架构

Docker Dev Environment on Laptop

Small Cluster

Easy Development/Testing Cluster

Production Cluster with Central Services

参考:CoreOS Cluster Architectures

第一种,就是开发环境的方式。我们在开发时,可以使用这种方式来开发。

小规模集群的方式。每个节点都安装了etcd服务,任何一个节点故障都不会影响整体服务。

开发测试集群。这种方式的优点是不用额外部署etcd服务,需要几个节点来测试,就加入几个,非常灵活。但是不是高可用的架构。因为如果etcd死了,整体集群就不能工作了。所以,非常适合开发测试使用。

线上生产环境集群架构。这种基本上就可以做到高可用了。不同服务资源之间可以使用Meta信息进行标识。

这些代码是如何实现的呢

主要是通过cloud-config-url参数的设置来改变不同的启动脚本,如cloud-config-url=http://192.168.1.10/config/develop-etcd/pxe.yml

注意,这里面有一个技巧。默认的话,CoreOS是没有密码的。有时安装时会出现一些问题,我会在启动参数里加上coreos.autologin标记,这样引导后,就可以直接进入系统,然后查找问题了。

这样,我们就能顺利启动系统了。

启动后,我们需要安装系统到硬盘,下载并安装Kubernetes,并初始化一些系统环境等等。

这样是怎么做的呢?

先看代码

这里我们在cloud-config-url里自定义了一个服务,叫setup.service。等系统启动后,会下载相应的脚本:pxe.sh。

详见代码。

脚本分为几个部分:

同步系统时间,新机器可能时钟有问题,这样会导致CoreOS不能正常安装,

硬盘分区,这个要根据自己的机器情况进行处理。

系统的安装。

离线下载已经准备好的Kubernetes,并放到相应的系统目录里。

其它脚本。

通知Yoo-Installer已经安装完成并重启。

那么,我们对于Kubernetes是如何自动处理的呢。

在CoreOS里,有一个Cloud-init文件,在每次系统启动时,它便会自动执行。我们利用了这个文件,自动搭建了Kubernetes的服务。

比如这个Central的YAML文件。

在这个配置文件里,有以下几个部分

hostname: 配置后,方便识别。

ssh_authorized_keys: 可以设置一个跳板机的key,方便管理。

update: CoreOS版本更新策略及更新版本设置。

Fleet: Fleet的服务。

units: 具体的systemd units文件配置,这里面包括了etcd、Fleet、Flannel、Docker、kube api server、kube controller manage、kube scheduler、kube-register等服务的配置。

这些服务的配置会自动创建相应的service文件。

我们也可以直接写文件,比如DNS的配置,『search localhost』 ,我在coreos-init里就没找到对应的功能配置key,只有写文件了。

这里有几个需要注意的地方

服务器不建议用DHCP动态分配IP,就算是MAC绑死的也不好。我们出过一次故障,DHCP服务异常,导致业务网络中断。

关于cloud-init文件, CoreOS 提供了coreos-cloudinit的方法,可以做validate 。如果自己修改了init文件,最好检验一下,不然只有重启后才能发现问题。

coreos-cloudinit不加validate参数,还可以执行,像写文件之类的操作,直接就可以看到结果。

关于CoreOS自动下载更新。像我们这样自建机房的,最郁闷了,不像一些国外的公有云那么方便,直接可以下载更新。怎么做呢?首先,你要有个梯子,然后通过专门设置update 的service,加上ALL_PROXY,就可以自动更新了!

为了更便捷的使用Yoo-Installer,我计划做二个版本,一个是VM版本的,下载后,直接可以用,另一个是Docker版本的。由时准备不足,没有做完,但是因为我自己也需用,所以我会继续完善!

这里要吐个嘈。我在封装DHCPD时,因为桥接的问题,Docker里面的广播根本发不出来。如果您有高招,请告诉我,我会请你吃饭哦~

对于Yoo-Installer,为了便于使用,我们专门做了一个UI,功能还不丰富,希望大家能积极提意见,欢迎PR。

   
次浏览       
 
相关文章

云计算的架构
对云计算服务模型
云计算核心技术剖析
了解云计算的漏洞
 
相关文档

云计算简介
云计算简介与云安全
下一代网络计算--云计算
软浅析云计算
 
相关课程

云计算原理与应用
云计算应用与开发
CMMI体系与实践
基于CMMI标准的软件质量保证
最新活动计划
LLM大模型应用与项目构建 12-26[特惠]
QT应用开发 11-21[线上]
C++高级编程 11-27[北京]
业务建模&领域驱动设计 11-15[北京]
用户研究与用户建模 11-21[北京]
SysML和EA进行系统设计建模 11-28[北京]

专家视角看IT与架构
软件架构设计
面向服务体系架构和业务组件的思考
人人网移动开发架构
架构腐化之谜
谈平台即服务PaaS
更多...   
相关培训课程

云计算原理与应用
Windows Azure 云计算应用

摩托罗拉 云平台的构建与应用
通用公司GE Docker原理与实践
某研发中心 Openstack实践
知名电子公司 云平台架构与应用
某电力行业 基于云平台构建云服务
云计算与Windows Azure培训
北京 云计算原理与应用