一、云原生运维转型之道
1、业务背景
如果大家有玩过游戏的话,对这个界面应该不陌生。我们团队主要负责腾讯内部游戏营销活动的运维支撑,在线营销活动除了为玩家提升游戏体验以外,也为游戏项目组在拉新、活跃,甚至是购买道具,都提供相关的营销活动、运营事件等商业化的支持。
2、微服务架构
这是我们的一个技术架构。从这个技术架构里我们可以看出,云原生已经变成一个大趋势了,我们团队95%以上都实现了微服务化。微服务化改变了开发的交付模式,同时也给运维带来了很大的变化,我个人的感受是挑战大于变化。以下6点是我认为现阶段我们面临的最大的挑战:
1)微服务调用链错综复杂,难于理解
尤其是一些大型活动,需要多个团队协同开发,会涉及到几百个微服务化的相互调用,整个微服务拓扑非常庞大,理解框架的难度加大。
2)追踪、指标、日志数据上报标准不一
每个团队都自建了不少监控平台或方案,这也是由于一些历史遗留原因导致。
3)无法快速定位服务问题以及根因
由于多个团队协同研发一个大型营销活动,当问题发生时,需拉通整个项目链条涉及的所有开发与运维团队各自排查,每个团队根据自己构建的指标监控体系逐步定位问题,势必会拉长问题整个的排查、解决的周期。
4)很难在上线前发现服务性能瓶颈点
问题的发现与处理相对滞后,通常是上线之后才发现服务被打爆,如计算资源不足、存储节点IO过高、调用下游接口延时过大等一系列问题。
5)无法判断节点间强弱依赖关系
比如A模块访问B模块,当B模块出现异常,给主调方A模块造成了影响,但是无法判断影响面到底有多大?
6)新上线业务容量评估无法精准计算
业务上线时我们无法判断应该给予多大的服务容量,通常产品运营策划为了稳妥起见报得虚高,导致运营成本也会被同等拉高。
3、环境的改变
前面提到我们面临的几大问题,接下来讲讲大环境的改变:腾讯2018年930变革后,公司明确了内部业务自研上云,历经4年多,团队面临两个较大的变化:
第一是作为公司内部第一批上云的团队,我们已经完成95%的流量切云,在云原生的环境下,运维的模式也发生了改变,与以往传统运维模式的区别具体表现在以下6点:
1)资源→资产
在传统的资源管理中,我们通常把一个设备的IP、性能配置、设备责任人等元数据信息记录在CMDB里,但到云端的资产化的模式下,它的范围和边界被扩大了,不仅仅是单台设备的信息,它可以是负载均衡器、MySQL实例、也可能是一个云上任一PaaS服务,我们都把它当成资产来看待与治理。
2)单体→微服务
单体服务微服务化,让服务的治理更加精细化。
3)管理→治理
我认为管理是一维的,治理是多维多元的,模式上发生了很大的改革。
4)事件驱动→流水线
以前通常是开发提交一个变更单,运维跟进并发起变更,出现异常则快速回滚。而在DevOps流水线之后,处处实现了自动化,让谁开发谁运维的理念得以实现,开发可以随意发起变更,一项目一天可能会发起几十次的变更任务,非常高效,而不再由事件去驱动。
5)DO分离→DO融合
以前开发和运维互不干涉,因为有“墙”的保护,也不需要给彼此背锅,在云原生的背景下,我们要求开发和运维要尽可能地融合,也是遵循了DevOps的思想。
6)业务运维→SRE
对传统业务运维的能力也提出了更高的要求,除了具备基础运维能力外,还需拓展包括对业务的理解、工具研发、数据分析、甚至是AIOps等能力,这也是我们所理解的SRE。
第二个变化是业务研发在整个云原生浪潮中的蜕变,包括采用云原生架构来实现版本的交付,基于一站式的DevOps平台,打通了研发线全生命周期管理,贯穿服务在开发、编译、构建、部署等全流程,实现服务交付的全闭环。除此之外,还会涉及版本所需的质量监控、配置与容量管理、日志检索等研发刚需功能,能力非常全面完整。
4、触发转型
从前面的提到的两大变化,作为运维团队的负责人,客观而言对我与团队带来的冲击还是非常大的,因为我们第一批在腾讯内部完成自研上云,当前98%的业务已经在云端跑,在这个过程中,我发现过去我们构建非常完备的传统运维能力,很大一部分已经不适用,包括业务版本的发布、变更、配置管理、流量调度、监控模式等等;可以看出运维的职能跟价值很大一部分被稀释了,具体体现在上云后系统运维的职能,基础设施管理、平台Paas服务的维护等等;也逼得我们必须做转型,也就是蜕变成云原生SRE,下面会重点提到为什么做这个选型,总结起来就是更加贴近业务、理解业务,实施高可靠性保障、提升用户体验,做更加专业的运维,如智能运维。
那么应该如何转型,以及转型之后要做什么事情,就是接下来我们要去思考和实践的。我大概在2015~2016年开始接触SRE,也了解到SRE的一些思想和具体的实践,在国内应该算是比较早的一批,2020年我们就完成全部业务上云,在这个阶段我发现SRE的思想与我们面临的困惑很契合,反复琢磨,不少思路确实能够解决我们很多问题,因此确定SRE是我们转型的方向。
以下是个人总结未来运维职能演变及转型的路径。随着云原生技术和架构的不断成熟,势必会带动IaaS、PaaS和DevOps的生态圈,往成熟度方向发展。但这几个方向的发展势必会对传统运维,包括系统运维、平台运维和业务运维产生很大的冲击,这三个岗位会被弱化,即使没有被弱化,一定程度上大部分职能也会转嫁给运维外包或业务研发身上。在这样的一个背景之下,我们运维要如何自救?
我这里给出了一个转型的路径,个人判断总共会经历三个阶段:
1)第一个阶段:CloudOps(云端运维)
云端运维实际上与传统运维没有太大区别,只是把传统运维搬到云上,也负责云端的资产的采购、环境的部署,以及日常的运营跟运维,同时也会关注成本,比如FinOps就是要关注云端的成本。
2)第二个阶段:SRE
在SRE里会保留两种职能:
- 一是资深运维,最专业的和能力较强的运维职能会被留下来。
- 二是工具开发,很大一部分运维做转型时,具备一定开发能力的运维会转至SRE工具研发的职能上来。
3)第三个阶段:ServiceOps(运维服务化)
在这个阶段,会把更加专业的运维能力打包成服务,交付给企业内部的其他职能团队,专业性服务包含了SRE即服务,安全即服务,数据即服务等,而且这些平台或服务都带有一定智能化属性,这是最基本的要求。
然后在企业内部跨团队地实施赋能,比如会给研发团队、测试团队,甚至是财务团队做增值赋能,我判断不少企业会在3~5年内陆续进入这个周期。
5、目标设定
前面提到运维转型的路径,可以看出目前我们处于第二阶段,即云原生SRE,我们给自己设定了几个核心目标,在团队的规划里,我要求把以下5点做好即可:
1)具备服务全链路质量覆盖,定义可量化的SLI与SLO,不能出现任何一个盲点。
2)提升 MTBF(平均故障时间间隔)、降低 MTTR(故障平均修复时间)
3)DevOps升级至DevSecOps,关注云成本(FinOps)
4)具备多云多级的资产编排与治理的能力
- 一是能够提升效率;
- 二是让交付更加标准化,比如业务出海,可以快速复用国内的交付能力,这些能力可以沉淀在各种编排模板、脚本,并且可以结合版本管理来追踪变化的明细。
5)具备一定的故障预警、根因分析、问题定位能力
通过智能化的水平提升我们质量方面能力的要求。
提炼中心思想就是云端一切皆可编排,加上我们“三位一体”的可靠性保障体系,这两个方向构成了我们第一期的整体目标。
6、SRE 8 准则
有了目标之后,我们还需要一些指导的原则,告诉我们应该怎么做。这里我也提炼总结出了8点,我们内部叫SRE 8 准则,今天我会重点把核心三点(蓝色框)提出来讲,其它更多准则说明可以扫描右下角的二维码查看。
二、SRE工具链建设思路
1、SRE体系全景
这是我们第一期的能力全景图,SRE能力主要集中在中间这层,包括了多级事件编排,MTBF及MTTR这三大块能力,内部我们把它称为“玄图SRE”体系,具体说明:
1)事件编排
- 事件编排的最底层要求是多云支持,因为我们的业务是跨云的,很多业务部署在北美、东南亚,所以我们要求跨云支持编排。
- 资产编排要求我们能够跨云实现资产的交付和自动化。
- 容器编排主要是k8s workflow这套机制。
- 作业编排就是任务编排,针对某个容器、虚拟机或云主机进行一系列功能性操作。
2)MTBF
即平均故障时间间隔,如何提升MTBF?
针对MTBF,我们希望是越长越好,要达到这个目标,以往我们在业务上线之前,这部分前置工作做得很少,通常是等发生问题后才被动地去做定位,所以我们尽可能地把很多能力前置,根据当前我们面临的实际情况,我们认为现阶段混沌实验&全链路压测是首要建设的能力。
3)MTTR
即故障平均修复时间,如何降低MTTR?
MTTR追求的目标当然是越短越好,这里我们拆解成了故障的发现、响应、定位、解决及验证五个环节,同时分析了团队过去一年上百个故障案例,发现导致MTTR被拉长最多的环节是故障定位上,因此,现阶段我们集中精力放在这个环节上做文章,这也是我们着重建设可观测性能力的缘由。
2、底层组织逻辑
接下来讲一讲我们实现这些能力的底层逻辑。
首先说明最底层部分,我们会定义SRE里面的标准规范、方法与目标,相当于我们在做好上层平台化之前,首先要把整个理论体系的底座梳理清楚,平台化只是将这套理论体系的实例化。
中间层的平台化,大家看到的可能是三个独立的平台能力,但我们把它看成一个整体,相当于把这三个能力当成一个能力体系来建设。因为我们在实践的过程中发现,三个不同能力的任意组合都可以延伸出不同的玩法:
- 可观测性+全链路压测,能够做资源的精准评估。
- 可观测性+混沌实验,能够做强弱依赖分析。
- 全链路压测可以作为混沌实验压测的原子。
因此可观测性、混沌实验和全链路压测三者并不是割裂和独立存在的,而是一个整体,它们之间可以相互发生关系,能够产生一些我们意想不到的应用场景,还有很多有意思的点等待着我们去挖掘。
三、SRE工具链建设实践
1、可观测性实践
接下来我们讲的第一个应用是可观测性,举一个很简单的例子,就是我们运维经常碰到处理故障的一个典型过程。通常我们收到告警,第一步肯定是要去看Dashboard里是哪个曲线和图表出现了明显的异常,然后找出某个时间段异常发生的具体表现,是否有周期性,是哪个指标发生了异常,再切换到下一步链路追踪,分解出这个时间段,某个接口和方法是否延迟拉高了或报错了,通过追踪的方式定位。最后一步则是通过日志分析导致这个函数方法出现异常的根因,定位出来后即可解决这个问题。作为一个普通运维人员,经常按这个套路去定位与解决某个问题,在整个过程当中用到了指标、日志和追踪三个能力,实际上这三个能力就构成了可观测性的三大支柱。
- 指标:提供服务性能、业务及运营等指标,用于异常告警及可视化报表。
- 追踪:分布式链路跟踪,记录请求跟踪路径,用于定位到具体服务或方法。
- 日志:服务日志,提供精确全面的系统记录,用于最终定位问题根源。
很多团队将这三个能力分开建设,比如指标通常是搭建一个Prometheus采集指标,日志则搭建一些日志采取的组件,到ELK里进行检索,追踪则用Skywalking或Jaeger之类的工具搭建,再检索整条链路拓扑等。但是可观测性要求将这三者融合,即通过一定的符号、特定的ID,把这三种能力串联起来变成一个整体,这是可观测性追求的目标。
1)系统架构
这是我们的可观测性体系技术架构,这个架构可能与其他行业方案存在一定差异,共同点是我们也基于Opentelemetry完成业务端、采集、上报、传输、计算、存储和应用等一系列过程,但是我们会重点聚焦在综合治理,后面也会提到我们会支持很多治理的能力,因为我认为任何一种服务都需要实施治理,缺乏治理则无法很好地使用及发挥它的效能。
2)平台能力
接下来是我们的一些平台能力,有基础能力,也有我们认为比较满意的一些高级能力。
- 综合管控治理
我们当前服务的日PV是7000多亿,如果我们全量上报,可能与业务访问的流量是1:1的,甚至更大,我们最终目的是通过可观测性的手段来提升高可靠性,但是如果它带来的额外的成本抵消了我们带来的价值,那么就不合理了。所以我们会做一些管控,如一定比例的采样,同时我们也会做一些运营干预,比如当流量达到一定顶峰时,如果此时仍然大量开启采集数据可能会对业务造成很大影响,因此需要采取熔断机制来干预确保业务服务稳定运营。
- ONE-SDK
我们把指标、追踪、日志这三者集成到某个SDK里做上报。目前Opentelemetry的官网里也只是定了规范,还没有完全地实现三者能力的集成上报,局部的开发语言SDK可能已经支持了,比如Golang,更多的还是处于内部联调和测试的阶段。
- 提升采集ROI
我们会开启采集的管控,当出现极端情况时,我们只采集有价值的数据,比如只采集异常的数据,其它的统统不采,因为产生异常的数据可能占比不到1%,量是很小的。
3)综合治理
我们的综合治理分为采样治理和运营治理。
①采样治理
- 头部采样:在入口开启采样,只采样自定义的比例,如2%或10%。
- 尾部采样:数据会先全量上报,通过缓冲池缓存数据,再异常处理,过滤出有异常的数据后入库。
- 数据冷热分离:考虑到后端高昂的存储成本,我们做了分级(三级),比较热的数据存放在ES里,超过一周的数据周期我们采用Clickhouse作为二级存储,存储一个月以上的数据我们存放到离线数仓中,那么成本就越来越低。
②运营治理
更多是一些数据采集干预方面的手段,比如熔断、降级、限速和染色。
染色即为打特定的标签,定义染色数据上报规则。比如我只关注某个玩家的登陆,那么把玩家的ID打进去,它只采集该玩家的整个生命周期产生的日志,其它统统不采。
下面介绍我们如何实现综合治理,我们利用了OpenTelemetry的Collector来实现,Collector内部有 4 个核心组件:
- Receivers:负责接收不同格式的观测数据,包括Zipkin、Jaeger、OpenCensus 以及Opentelemetry格式。
- Processors:负责实施处理逻辑,如打包、过滤、修饰、采样等等。
- Exporters:负责将处理后的观测数据按指定的格式重新输出到后端服务中。
- Extensions:以旁路的模式来作为Collector本身健康心跳探测等。
利用这些组件组装出一个或多个 Pipelines,我们这里分别组装了Agent和Collector两个角色,Agent主要用于接收上报的信息,在processor中使用了比较多的像头部采样、熔断、降级、限速、染色等处理,将处理后再将数据写到kafka中;数据被后台的Collector消费后,我们在collector中则实现了尾部采样、自动补链等逻辑。
4)异常检测
当我们采集大量的数据之后检测出异常点,此时需要定义告警,很多情况下会出现如指标毛刺等带有故障特征但实际上却不是故障的情况,为了减少误告,我们结合AIOps的技术做了一些探索,目前也取得了一定成效,具体的思路如下:
我们采集最新几分钟的Trace与Metric的数据,通过训练好的模型去推理异常权重,识别出的异常Trace再通过告警发出,由此可以看出我们的特征模型非常重要,那么如何确保这个模型的准确性?有一个方案可供大家借鉴,我们分为两个阶段来实施:
第一阶段是测试阶段,结合压测与混沌能力,在源头做流量压测及混沌实验,我们通过模拟CPU爆满、流量异常或丢包等等已知的故障原子,再结合压测的手段,观察服务表现出来的各类指标数据,这就是我们想要的特征,通过平台自动化给特征打标签,可以释放大量人力参与此类工作。
但是再完备的测试环境也无法模拟线上所有问题,比如一些未知的问题我们历史上从未碰到过。所以会在第二阶段(即将上线),我们会去采集现网真实的数据做验证,不断地扩充跟修正特征模型,使模型越来越精准,但是生产环境时则不可避免地需要依赖人工去打标签。
我们采用的是Matrix Profile的算法,在此之前我们也盘点了行业内十几个针对Trace的异常检测算法,从推理速度、准确性和参数调整的变异性等维度进行选型,我们发现Matrix Profile这个算法是最接近我们需求的。Matrix Profile 的值表示子序列间的距离,距离越小的表示序列相似度高,而距离越大表示越异常,异常则对接我们的告警,我们当前这套的准确性能够达到大约83%。
2、混沌工程实践
混沌实验不少企业都已经在引入并积极建设,更多是通过模拟真实现网的故障注入,发现服务是否存在异常或弱点,但我个人觉得它的好处不仅限于此,对于SRE而言,它的价值在于一句古话说的:平时多流汗,战时少流血。我们平时模拟了大量的故障案例,在真正面临故障时则能够坦然面对,心里不会慌,包括在预防、发现、响应、定位方面都给我们积累了大量的经验,使我们能够快速处理和解决问题,我认为混沌的意义应该在于此。
1)平台架构
这是我们的整体架构,这部分我们跟社区合作的比较多,比如PingCAP的Chaos Mesh,我们也参与了共建,所以很多原子是开放的,平台能力也很成熟,基本上用于做一些能力的封装,比如上面的编排、演练、模板,官方也带了一个简单的管理端,如果要求不高可以直接用。
2)平台能力
这是我们的平台能力,分为基础和高级。我们平时做得最多的是红蓝对抗,红蓝对抗就是通过攻防不断验证可靠性是否达到要求,达不到则持续修改迭代,发布过后再进入下一轮攻防,还是比较有趣的,同时可以做一些依赖分析等能力。
我认为服务强弱依赖分析是很有价值的,可以轻松感知如A调B服务,B出现问题对A是否造成影响,我们分为三步来实施:
- 首先,基于可观测性技术,追踪到服务间的上下游依赖关系。
- 然后,对下游服务注入故障,如丢包、超时、响应慢等。
- 最后,观察主调方的稳态指标,如QPS、延时是否受影响,如果受影响则存在强弱依赖关系,从而要求开发进行改造,比如在主调方做一些访问DB的缓存等策略,达到要求后才能够上线。
3、全链路压测实践
最后一个是全链路压测,我认为它的意义主要是两点:
- 一是能够发现上线之后的性能瓶颈点,因为导致性能瓶颈的因素很多,如环境、参数配置不当、数据库、网络等,逐个排查成本过高,可以通过压测发现。
- 二是重大节点的运营保障,容量与负载没有线性关系,无法精准判断容量够不够,压测一下便知道。
1)平台架构
这是我们压测的架构,与传统的压测不同在于:传统的压测只是制造压力源,但是当被压服务出现问题时,无法定位具体是哪个接口、方法、调用出现了问题,因为被压服务对于压测平台是一个黑盒子,需要研发自己去定位,这是传统压测面临的问题。我们的方案兼容传统的压测能力,即流量压力的制造,同时结合可观测性能力,将整个拓扑里所有环节中的每一条链路、每个接口、方法和函数出现的性能瓶颈,我们都能够快速定位并告警,开发进一步跟进,从而快速定位出具体的性能瓶颈点,并且具备针对异常做根因下钻分析等能力。
2)平台能力
3)服务压测链路拓扑
接下来我想讲全链路压测其中的一个应用,即服务压测链路拓扑。我们在源头施压,平台能够完整地呈现整个观测链路,展示微服务间的调用关系链,同时能够实时计算出每一层微服务黄金指标,即A调用B的耗时、QPS、延迟、放大倍数等都能计算出来。
放大倍数能够用于服务上线前的资源评估,比如链路中的某个节点B,它被放大了5倍,那么就可以得知存量是20000核的资源需要做5倍+的扩容,才能满足未来版本上线时的资源需求。
4、总结
最后总结SRE实践里的几个过程。我们从立项到结项,通过技术与文化两个层面落地。
1)立项:我们会组建一个FT的临时团队,团队里有运维、开发、测试、产品等,运维也会参加技术方案的讨论,同时定制可观测性上报的规范。
2)开发:开发需要落实运维制定的规范,做好指标埋点的上报,同时SRE会参与技术架构的评审。
3)测试:我们会在这个阶段大量地做混沌实验和全链路压测。
4)上线:更多关注SLI、SLO等指标和它的错误预算,以及OnCall的机制是否完备,提前准备好故障预案。
5)结项:对整个项目从立项到下线整个过程中,做得好的和不足的点进行复盘和总结,沉淀的经验以便复制到下一个项目当中,同时我们会不断完善整个SRE工具链的全景图。
Q&A
Q:如何在全量采集和采样采集之间找到平衡?
A:全量采集和采样采集没有好坏之分,与业务场景有关。实际上我们也有一个项目要求必须要全量,因为对账要求全部都要采样。但除了这种以外,基本上都是按一定的比例去做的,一方面可能与业务要去谈适合的采样比例值,因为我们无法判断是5%还是10%,是没有标准的,可能前期我们在与研发做项目评审时,实际上这个比例已经谈下来了。
另一方面我们在入口做全量,后端做尾部的情况占的比例也比较高,大约是40%,就是入口都放过来,但是真正到后端不会全部数据落地,只落地1%或不到。我认为尾部采样才是有价值的,因为它只过滤有异常的、错误的或断链的等,捕捉到这个标签并把它存下来,那么数据量就很小。但是另外一种情况是项目刚上线时或不同类型的活动和项目,要求要拿到其特征,那么就相当于要求前期要全量,后期关注成本再慢慢压下来,所以我们分不同的阶段和诉求做不同的策略。