裴泽良 | 腾讯架构平台部运营开发组负责人
本文为腾讯裴泽良老师在 GOPS 2018 · 上海站自动化运维专场演讲全文,社区将速记文字整理发布,以飨读者。
架构平台部提供的服务大家都使用过,微信QQ聊天的图片、朋友圈图片;QQ音乐里面的歌曲,腾讯游戏,应用宝里面的app的下载、腾讯云的COS对象存储、点播、直播,以及腾讯视频的点播、直播等产品。
目前总存储量超过2EB,储备带宽超过100Tb,使用的服务器超过20W台,建设了1000多个OC机房。我们提供的服务总流量占据了腾讯90%以上的出口流量,负责托管的服务本身的运维人员只有50人。
如果用发电站来类比海量服务的基础运维,发电站的日常运维需要具备强有力的监控能力,能够实时监测到各种指标有没有异常。
比如当前总输出电压值、电流值、发电量,日常中还需要对生产环境做各种操作、调整,比如装填各种原料、调整发电量、维修零部件。
我们日常运维同样需要版本配置变更,维修故障机。
安全运维是根基,否则一旦出事,后果不堪设想。
对于发电站来说,下游的工业、居民全停电了,会带来巨大的经济损失;对我们来说,用户数据丢失找不回来,会产生巨大的信任危机。
直观来看,我们的运维挑战就是监控体量大、告警多,对现网变更非常频繁,安全要求高。
在介绍运维体系前,需要先了解下我们的业务平台架构,这样才能理解我们的工作重心,比如生产环境中我们没用常见的web服务器,没有使用MySQL。
因此监控本身不需要集成这类通用服务的性能数据采集功能,跟开源的监控不一样。
我们主要有两大平台:存储与CDN。
简单来说,存储是用户在app上面上传下载图片、文件、视频这类数据;存储分为接入层、逻辑层、分布式存储层。
这里面每层都有容灾、负载均衡,实际结构会比 ppt 中复杂的多。
CDN 是支持用户下载数据或者 VOIP 转发数据的,一般分为多级,最后一公里的边缘OC结点,向上的中间源,再向上的源站。
源站可以是客户自己的,譬如快手、斗鱼的源站,也可以是我们托管的,譬如cos源站。
如果是voip实时通话的,则用户的数据就会从某个边缘结点进来,中间经过最优路径选择之后,由某个边缘结点出到对方用户。
我们的自动化运维体系可以分为三大部分:
1.基础系统,如配置系统、设备资源管理系统、资源预算核算计费系统。
2.通用运维能力的系统,如监控、变更、PAAS运维平台、质量测试、流程。
3.业务专用的运维系统,如相册运维系统、COS运维系统、VOIP运维系统。
今天分享的是中间这块通用运维能力,对于我们来说,所有这些系统的建设就是为了保障业务质量、控制业务成本的。
我们有段时间经常遇到业务或用户投诉“我朋友圈看不到图了,什么情况”,我们的同事一脸迷惑“我没收到告警呢,好像一切正常”,就是监控不全的问题。
当我们在监控系统上面各种查找数据,想分析到底出什么问题了,点“查询”按钮,系统却一直提示“请等候,正在万分努力查询中”,结果就是半天出不来数据,系统性能低。
好不容易看到视图了,随即来了新疑问,总共上千台机器在上报失败数据,到底是哪台机器上报了大量失败数据呢?
又是一脸迷惑“找不到呢”,这就是系统不具备多维下钻分析的能力,找不到来源。我们是怎么解决这个问题呢?
这是监控总览,我会侧重介绍与常见监控系统不一样的地方,主要体现在监控上报、即时计算、异常自动发现、自动分析这几方面。
这是我们的上报模块,上报端通过内网或外网发数据到服务器,监控数据主要分三类:
1.结构化的,也就是时序数据;
2.详细日志的,也就是程序流水数据;
3.自定义数据,业务借助监控上报通道,上报的自己需要的特定的数据。
监控系统最关心的是结构化的时序数据,像流量、请求数、延时都是这类数据。
我们在上报中比较特别的一点就是在上报端,业务逻辑每一次的用户请求处理相关的数据都会调用监控上报API。
比如业务逻辑中每请求一次后端系统,就会把调用延时、主调接口、被调接口、成功还是失败、错误码等数据调用监控上报API上报到监控系统中。
在上报 API 中还会按秒把同一类型的多条数据汇聚成一条,上报给本机的监控Agent守护进程,在Agent中会把秒级数据直接发给监控平台,就形成了秒级监控。
同时Agent也会把同类型的多个秒级数据点汇聚成一个分钟级的数据,然后上报给监控平台,从而形成分钟级告警。
目前每分钟有6亿的分钟级结构化数据上报。
总结一下,我们在同一个上报通道中实现了秒级、分钟级、详细日志、业务自定义数据等多种上报能力。
我们监控系统用结构化的多维度、多指标模型来描述业务的监控。
指标维度这种概念在OLAP中很常见,具体做法是一个软件模块的监控数据分解为多个指标与多个维度。
譬如朋友圈图片下载的download模块,指标有流量、延时、请求数、失败数等;维度有地区、运营商、图片规格等等。
用户的每一次下载请求的监控,都对应了某种维度指标组合的数据。
譬如图中红色的线条是指上海电信大图的流量,监控系统会自动把这种软件上报的维度指标组合映射为一个唯一的特性ID。
特性ID是数字型的,然后把该维度指标组合的时间序列值与该特性ID做为(key, value)存在单独的KV系统中,把特性ID与该维度指标组合的关系做为配置数据存在DB中。
一个(key, value)中的value只保存2小时共120个点的时间序列值,同一个key每天会存在12个value,采用专用压缩算法后,每天的存储量超过350GB。总结下,多维度模型可以有效的描述业务的各种监控数据。
多维度模型好是好,也会带来一些明显问题,软件只会上报最基本的各种维度指标组合的数据,而用户却需要查询各种维度汇聚的数据,譬如前面说的软件上报了上海电信大图的流量,而用户却需要查看电信整体的流量。怎么办呢?
如果数据是存在MySQL中,直接select sum group by就可以了,但这样的海量数据显然不适合存关系数据库,我们是存在KV系统中。
于是采用了实时计算+即时计算的模式来解决汇聚的问题,实时计算用于软件直接上报的最基础的各种维度组合的数据在多台机器之间的汇聚计算,即时计算用于用户查询的数据,不是基础组合时的立即计算。
这样做大家已经看出来,还是会有问题。比如用户查询的维度组合有几十万时,立即汇聚是无法保证能在1秒内返回的,怎么办呢?
这时候就要用到即时计算的索引技术了,类似于MySQL中可以建索引,用于加快select的速度。
这里面的思想类似,做法就是对明显增长查询耗时的维度生成为“索引”,这个索引会在这个维度上做汇总并且与其他维度做组合,这个索引又会自动加入到实时计算中,以保证数据每分钟都会被计算。
大家又会有疑问了,索引这么好,是不是也要像MySQL索引一样需要用户自己维护呢?
我们已经做到了自动化,当系统发现某个业务的维度组合过多可能会影响查询速度时,会自动找到最优的维度来添加索引。
整个思路与apache kylin有些类似,也就是预计算,但又不同,kylin只会预计算用户提前预定义的所有组合,不管实际中会不会被用到,而我们是按需的自动索引+按需的立即计算。
采用这种做法后,即使用户看到的维度组合达到几十万,甚至上百万,系统同样会对用户的查询亚秒级返回结果,同时又保证了预计算的结果数据量不会太大。
通过实时计算+即时计算两种方法,我们解决了多维度模型中面临的速度问题。
但业务体量大了之后,还是会存在各种各样的挑战,譬如某个维度包含的维度子项太多,有几十万,甚至上百万;像CDN的域名,腾讯云直播的房间,这时候即使是即时计算也不是那么有效了,怎么办呢?
仔细分析业务特性会发现大部分都是长尾用户,这部分用户对整体流量贡献很少,有些域名每天就几十、几百次请求,没必要笼统的都做分钟级监控告警。
这样比较浪费监控资源,所以我们提出了重点业务与长尾业务区分监控的概念,在数据上报后的实时分析模块,把长尾业务数据稍做处理写入HBase,再有一个长尾数据分析模块会起一个spark任务,保证每5分钟分析一轮长尾数据,把满足一定条件,譬如流量达到某一阈值的业务转为重点业务,这样做了之后就达到了把有限的资源用来优先保障重点业务,而长尾业务做到5分钟级别发现异常,并且能在5分钟内把达到一定流量的业务自动转为重点业务,从而增强监控能力。
前面在上报部分内容提到了秒级监控,对于我们来说秒级监控最重要的不是用来秒级告警,这样会带来非常多的毛刺骚扰,而是在有异常时能够帮助分析软件分钟内负载不均衡的情况,譬如分钟级数据掩盖真实的高负载问题,以及像直播、红包这种会秒级突发场景的分析。
AIOps非常流行,我们在这方面也有探索,目前在异常的自动发现、告警毛刺的去除上面,都有在实际使用,效果还不错,在异常的自动溯源方面,还在努力探索中。
我想强调的是,对于业务来说,即使上了机器学习版的异常自动发现、告警毛刺的自动分类,但传统的人工干预的阈值波动率告警仍然不可少,比如某些业务近期很受关注,对质量的抖动要求很敏感,这个时候就要人工干预配置传统的阈值、波动率了,所以在我们看来,AIOps并不是由自动来接管一切,传统的阈值这种策略仍然要使用,以防止自动的失效。
在异常的自动发现方面,我们采用了两阶段方式,先用统计分析算法做一次筛选。
统计分析算法目前用了四种:Grubbs,EWMA,最小二乘法,First Hour Average;
输入的曲线数据是今天、昨天、上周同天总共三天的数据,用这四种算法来投票决定当前点是否为异常点,至少要有三个算法认为是异常点才会认为是异常点,然后再用IF算法对这个异常点做一次离散点判断,这样就得出最终的异常点。
这里面用的都是无监督算法,对流量、延时、失败率这种相对还算平滑的数据都比较有效,当然对于有些场景会基本无效,像右边这个图是直播的流量。
大主播一上线流量就会大幅上涨,一下线流量就会大幅下跌,而且大主播的上下线时间对整个业务来说都是不确定的,人工来看都很难断定哪些是异常,哪些又是正常的,算法也必然是一脸迷茫。
我想强调的是,算法还是要结合业务特性,不能只看数据本身,这样才能最终提升准确度,对于直播流量这种情况,我们直接就用传统的阈值就好,把智能化的判定加在卡顿率这种指标上,同样能够达到应有的发现故障的效果。
业务的质量数据偶尔会有一个突起,譬如延时或失败率在短暂的几秒时间内有个比较明显的上升,但随之又立即降下来了。
这类问题对一般业务来说都没什么影响,但如果都告警出来,那运维是受不了的,怎么办呢?我们采用了有监督学习算法来智能化的去毛刺。
既然是有监督,那就是需要人的参与了,我们建设了一套告警送达负责人微信时,负责人可以直接在微信上面认领告警,选择异常的原因,里面有一项就是“毛刺抖动”,这样就获取到了有标签的样本了;
然后根据告警的业务特性来建立样本特征,譬如把时间、地区、运营商等都做为特征,再用RF、GBDT、SVM分别建立毛刺模型,对于之后的告警都会采用这三个模型来投票,至少要有2个认定为毛刺,才会最终判定为毛刺,然后降级发给负责人。
这个模型的训练是在线的,用户不断的认领,模型不断的精准,后面的告警去毛刺会不断的有效。
最终通过智能化的异常发现与去毛刺,来综合提升告警的全面性与准确性。
告警的自动分析处理也是比较有特点的一面,我们建设了完整的自动分析体系。
在异常产生后,如果有相应的自动分析工具,告警就不会直接发给用户,而是会先送到分析工具,分析工具分析出结果后会再推送给用户,同时如果有处理工具,用户还可以在收到分析结果时,直接点击处理。
要说明的是分析、处理工具是放在PAAS运维平台中的,只需要用户手工拖拽、编写一些小脚本就可以完成工具的开发,这才是我们自动分析体系的便利之处。
要强调的是,这里面的自动分析并不是指异常出现后,系统就具备通用的能力可无条件的自动分析出原因,即使是人,如果对业务不熟悉,也做不到通用的分析效果。对于常见的问题,建设专用的分析处理工具,可以极大的提升运维效率。
在告警的自动分析与处理方面,我们最终期望的效果就类似于自动淋水系统,当探测到火灾后,就自动开启喷头来灭火。
在没有更智能、更精准的容量评估前,常常可以看到运维人员与预算管理人员的争论,“我需要200台设备”,“你为什么需要这么多,理由是什么,能不能再减少些”。
容量管理方面,大家常常可以见到docker化,k8s等等,那为什么还需要单独的容量管理呢?我们把模块分为二大类,一类是无状态的模型,这类是可以docker化管理的,另一类是有状态的模块,不适合docker化。
在docker化的容量管理方面,我们具备了秒级CPU、流量监控的能力,来计算容量需求,同时采用了提前把容器部署到母机的方式来达到秒级扩容的效果。
目前我们建设了超过100W核的docker资源池,用于图片压缩、视频转码、AI训练这类场景。在有状态模块的容量管理方面,我们引入了机器学习的算法来自动评估容量,并且做到了与预算、资源系统的联动,直接一键提交设备增长需求。
我们的容量评估原理是这样的,从监控系统中可以获取到软件模块的请求数、流量、CPU值的对应数据,采用回归算法建立起模型,在实际中常常会把业务的关键特征加进来建立模型,譬如图片规格(像大图、小图)、请求类型(像图片、视频、文件),因为很显然,不同图片规格、请求类型下的请求数会有带来明显不同的流量。
当业务自然增长需要报备或活动提前需要报备资源时,就可以很容易的计算出上涨多少请求,会带来多少的流量、CPU的上涨,进而需要多少的设备量。采用了机器学习算法后,容量的评估不再是人工的“大概”式预估,而是精准化评估。
从此运维报备设备时,便不再与预算管理人员有争论了,“根据现有模块的性能如果要支撑未来的这个增长量,系统算出来就需要这么多设备”,“看来需要拉上开发人员 PK 下他们的程序性能是不是可以再优化下了”。
监控是用于发现问题的,监控做的很好了,发现了很多问题,但出问题时却没有得心应手的工具,运维只能手忙脚乱,半天也解决不了问题,效率非常低下,这不是我们想要的。接下来看看我们变更与操作方面的工具化建设。
对现网的变更操作就需要运营系统能够更改生产机,如果整个生产系统只有几十台机器,还可以直接expect ssh的方式,几千台的时候这种办法就不行了,可以使用ansible、saltstack,而几十万台生产机、复杂网络环境下、要求一定安全策略的时候,ansible、saltstack也不可行,所以我们建设了自己的管控平台。
管控平台本身只有两个核心功能:执行命令、传输文件。然后在此基础上会建设了作业流程管理、模板机制、操作范围隔离机制等安全策略。
当然管控平台还需要具备屏蔽各种网络、地域环境差异的能力,给上层用户提供一个统一的使用体验。
在文件传统方面,我们使用了类似P2P的方式,当源与目标机器可以直连的时候就直传,当无法直连的时候,系统会自动计算最优路径,从接入svr上面做中转,这些对于上层调用方都是不可见的,系统会自动完成。
比如变更时的版本文件位于IDC内的服务器,目标机器位于CDN边缘结点,且无外网,这时候就会用到自动中转的文件传输了。
目前管控平台的终端数量超过30W,每天调度的作业数量超过5KW。对于海量的运营来说,管控平台是运营系统操作生产机的唯一途径,绝不允许有人再通过expect直接ssh这种方式来操作生产机,所以管控平台是自动化运营中非常基础与重要的一环。
变更常常是导致现网出现故障的一大原因,是值得花精力做好的环节,变更的基础依赖就是管控平台。
这是我们的变更流程,从开发提交版本,进入自动化构建与测试,接下来进入灰度变更,效果确认后再到批量变更,在整个流程中做到了自动化。
目前每天有50单非通用配置的变更任务,变更机器数量超过1W台,比较有特色的就是在变更阶段的自动化监控,也就是在每台机器变更之后,系统采用机器学习的算法自动发现变更前后机器负载、业务请求量、失败量等这些指标是否出现异常,如果一切正常,就会继续变更下去,一旦发现异常就会暂停变更,通知负责人处理。
还有一个比较有特色的就是变更后的检查,不同业务的变更或扩容会有一些区别,譬如A业务是在外网,并且用了TGW,TGW是腾讯的网关产品,类似于LVS,那么在扩容的时候就要申请防火墙、安装TGW隧道,一旦有某个部署没做正确,就会导致最终出问题。
我们在变更后会对接一个工具化的检查,用来再次确认变更效果,而这个工具化的检查不是在变更系统中做的,因为不同业务可能是不同的、多样的、经常变化的,所以不适合放在变更系统中。
我们是把它放在自己的PASS运维平台中,这个PAAS运维平台可以很方便的创建一些小工具,并且与变更系统对接,从而做到统一变更系统中千人千面的效果。
以前每位运维人员手头都有一些自己写的工具脚本,当需要使用的时候,到处找来找去,就像这堆散乱的工具一样,而且因为自己写自己的,还会导致这些个人专用的工具难以给到其他人使用,难以传承下去,以及安全性不可控,怎么办呢?
我们建设了一个轻量型的PAAS运维平台,运维可以在这个平台里方便的编写各种工具,快速搭建出复杂一些的流程,目标就是通过工具+流程来快速拼凑出需要的功能,平台本身有工具调度引擎、流程执行引擎,采用管控平台做为基础,上层提供给其他运营系统,或者运维人员直接来使用。
右侧是一个新增crontab项的工具示例,目前平台总共有超过1000多个工具与流程,周人工使用量超过5000次。
有了这个PAAS运维平台后,我们再也不需要各自在自己机器上维护一些小脚本了,从而让工具变的更易于维护、安全可控、分享与传承。
当我们监控已经做的很好了,可以做在办公桌前喝着咖啡看着视图,手机没收到告警电话,就一切正常,工具也做的丰富多彩、各种功能都有了,但是如果对生产机不加以专门保护,让运维人员能够经常的接触到生产机,就会像这幅图一样,虽然我们无意搞破坏,但常在危险地带走,也难免会出事,所以一定要建设更安全的操作生产机的道路。
这是携程2015年误删除程序导致的不可用,这是滴滴2015年误删导致的不可用,这是aws s3 2017年误下线导致的不可用,都说明了安全运维的份量,安全无小事。
我们从总体上把生产机的安全划分为两大块,一是人工直接登录到生产机,二是运营系统操作生产机,从原则上来说,直接卡住这两方面的安全运维,就可以保证整体的安全运维。
总结下来就是不要让运营系统能够随意操作生产机,也不要让人能够随意操作生产机,这两方面我们都做了一些具体的管控措施,因为运营系统操作生产机只能通过管控平台,所以就需要卡住管控平台的安全策。
具体做法是高危操作一定要模板化,模板化是指上线这个操作工具前要人工审核,之后的执行使用都不可以再更改该工具的代码,而且高危操作会限定执行频率,譬如每小时限量只能操作100台设备,运营系统限定只能操作相关业务的生产机,不能随便一个运营系统都可以操作到所有生产机。
在直接登录生产机方面,对生产机的权限做了划分,分为普通、root两种,业务进程用root启动,人工正常只具备普通权限,也就是说人工登录进去后可以查看,但无法修改,如果需要root权限,就要走审批流程。
然而即使做了这些之后,就能保证不出现前面说的那些误操作了吗?不存在的,只要是人,只要是有不断改变的需求,就无法保证100%不出错,但我们仍然需要尽力从根基上来保证安全,尽力降低可能的意外发生后带来的损失。
目前我们对现网生产机的操作,97%是通过各种运营系统来做的,像变更系统、PAAS运维平台、业务专用运营系统,2%会通过管控平台来操作,只有大约1%是直接登录生产机来修改的,这部分一般是紧急故障处理时才会用到的。
就像这个倒三角,越向下风险越高,效率越低。采用这种三层的体系结构,来综合平衡运维效率与安全。总之就是尽力避免直接操作生产机,尽力避免当场匆忙写工具运维,尽量使用提前做好的工具,这样才能远离危险。