可观测性建设从去年开始在国内非常的火热,大家谈的越来越多。随着云原生、微服务的发展落地,可观测性建设逐渐成为了一个必不可少的工程手段。开发者通常需要去思考建设可观测性的方方面面:如何在不同的Dev Stack和Infra Stack中埋点、如何插码、如何传递追踪上下文、如何生成指标/追踪/日志数据并进行关联,需要考虑的问题太多太杂,导致应用开发团队花了一半的时间用于可观测性的建设。
# 一、可观测性建设的痛点
1 )建设可观测性平台耗时长
在业务流的整个链条过程中,从RUM到Service、到Serverless、到DB,会遇到Dev Stack的多样性,包括前端框架和后端开发语言的多样性;以及也会遇到Infra Stack的多样性和黑盒问题。开发者直接面对的是自己负责的微服务,可以在自己的代码里面做埋点、插码、可观测性建设。但是当遇到Infra组件的时候就无能为力了,这里面包括网络的四七层网关,存储的数据库、消息队列,计算的Linux、Windows以及现在一些loT设备(比如智能汽车)上运行的Android操作系统。除此之外,应用运行的基础设施形态也非常丰富,包括公有云、国内更多的有专有云、K8s容器、Serverless等。
Epsagon做过一个调研,链接( https://thenewstack.io/observability-takes-too-much-developer-time-so-automate-it/ ),结论是开发者有30%的时间在建设可观测性,做埋点、插码生成Metrics、Tracing、Logging数据。除此之外开发者还有高达20%的时间在做Debug,而这些Debug之所以耗费了那么多时间,通常大部分是因为可观测性建设的欠缺导致。
2 )建设可观测性平台难
另一个方面,就是建设可观测性平台这件事本身就非常困难,其中有着很多技术挑战。要想实现可观测性,就需要去观察软件内部的状态,不能将开发者辛勤埋点、插码标记的标签剥离掉。
上图中,排名第一的时序数据库InfluxDB会在文档里面告诉使用者怎样去消除Tag的高基数(High Cardinality)问题。中间图片是一篇腾讯云监控的文章,里面分析了很多链路追踪的采样办法,这是在猖獗的数据之下,大家无可奈何选择的一些做法。左下角的图片是字节跳动在构建可观测性SaaS平台的一个JD。从这些都可以看出建设可观测性平台其实是非常困难的。
Trace采样,分布式链路追踪的鼻祖—— Google Dapper论文的作者Ben Sigelman创立了一家可观测性SaaS公司Lightstep,他们的用户分享了大量Tracing的最佳实践,其中很多用户都谈论到不希望Tracing数据有任何的采样,因为越是长尾的数据,越能反映问题,越可能发掘出更大的价值。而且这部分长尾的用户可能碰到问题以后直接就走掉了,它相比一些经常高频使用你产品的用户,受到这些低频故障的影响会更大。
二、开源的高度自动化可观测性平台
开源的可观测性方案非常多,比如 OpenTelemetry、 SkyWalking、Elasticsearch、Prometheus等,每一种可观测性解决方案都有最擅长的地方,都有聚焦的地方。接下来以MetaFlow为例讲解如何构建高度自动化可观测性平台。
首先简单了解一下孕育MetaFlow出生的土壤。2016年开始,云杉网络自研了一款云网监控产品DeepFlow,最初用于私有云环境下的云网络性能监控,得到了金融、能源、运营商等行业客户的高度认可。随着容器技术越来越多的应用到企业IT建设中,DeepFlow也从2020年开始逐步从云网监控走向了云原生应用可观测性。MetaFlow作为DeepFlow核心的可观测性数据引擎,希望可以带给开发者更好的可观测性体验。
在可观测性建设中MetaFlow面向 Metrics、Tracing、Logging各种可观测性的数据源,并且创新的使用eBPF、OpenTelemetry等新技术提升数据采集的自动化程度。同时MetaFlow有一个开放的数据库接口,可以通过组合或替换的方式,选择最适合的数据库来存储观测数据。向上MetaFlow提供一个统一的SQL接口,使得开发者能快速将MetaFlow融入到已有的可观测性平台中。
MetaFlow的GitHub地址:https://github.com/metaflowys/metaflow。
代码还在整理中,目前里面只有一个README文件,文档中阐述了MetaFlow的设计理念、关键特性、解决的问题、软件架构等,供大家学习了解。预计6月底会将全部代码推到GitHub中。
01 集成并丰富Metrics/Tracing/Logging
MetaFlow可以将任意的Metrics、Tracing、Logging数据都集成进来,并且这不是一个简单的集成,它会将所有的数据进行统一的增强处理,使得使用者能关联各种不同数据源的观测数据,彻底消除数据孤岛,同时也赋予数据更强大的切分、下钻能力,让数据得以流动。
02 MetaFlow的Agent和Server
MetaFlow的架构其实非常简单,简单到只有一个Agent和一个Server,分别是数据采集组件和数据存储查询组件。
MetaFlow Agent可能是可观测性领域第一个使用Rust来实现的高性能、内存安全的Agent,同时支持通过WebAssembly技术提供灵活的可编程能力。它的核心能力得益于eBPF技术,通过创新使用eBPF实现了对任意开发技术栈、任意基础设施的全自动应用性能指标数据采集(AutoMetrics),以及自动化的分布式链路追踪(AutoTracing),这两项是MetaFlow Agent独有的能力,能极大降低开发者建设可观测性的工作量。
MetaFlow Agent支持集成广泛的开源Agent和SDK的观测数据。MetaFlow拒绝造轮子,因此对于Telegraf、Prometheus、SkyWalking、OpenTelemetry、Sentry、Loki等开源社区优秀的可观测性数据源,MetaFlow都能集成进来。
MetaFlow Server进程包含了4个内部模块:1)Controller面向采集器Agent的管理,能纳管多资源池的10万量级的Agent;2)Labeler面向标签数据的自动注入,提供AutoTagging的能力;3)Querier面向数据查询,提供统一的SQL接口;4)Ingester面向数据存储,提供插件化的、可替换可组合的数据库接口。
一个Server进程囊括4个模块,是因为我们希望将复杂度隐藏在MetaFlow内部,展现给使用者的是一个干净的使用界面。它支持水平扩展,而且完全不依赖外部的消息队列或负载均衡,就能够去实现对多个Region、多个资源池中Agent的负载均摊。
同时MetaFlow Server也有两个非常核心的技术,AutoTagging和SmartEncoding。通过AutoTagging能为Agent采集到的所有观测数据自动注入统一的资源、实例和API标签,消除不同数据类型之间的隔阂,增强所有数据的关联、切分、下钻能力。而SmartEncoding是一个非常创新的、高性能的标签编码机制,通过这个机制,能将标签注入的存储性能提升10倍。
三、MetaFlow的全栈、全链路、高性能
01 全栈 AutoMetrics & AutoTagging
云原生应用的运行环境是非常复杂的。一方面,开发者使用的Dev Stack之多,包括各种前端程序的框架、后端程序的语言,而且一直在快速的迭代发展。另一方面,应用程序运行的Infra环境非常复杂,应用以进程形态运行在Pod中,可能会有Sidecar为他提供服务,而Pod可能在虚拟机中。除此之外两个宿主机之间还会有各种复杂的四七层网关。MetaFlow首先能做到的能力就是利用eBPF和BPF技术,实现真正的Any Stack的应用性能指标数据采集,即它的AutoMetrics能力。
MetaFlow完整的使用了eBPF的kprobe、uprobe、tracepoints能力,也完整的使用了eBPF的前身——已经有三十年历史的BPF的能力,与AF_PACKET、Winpcap等机制结合,实现面向任何操作系统、任意内核版本的全自动的数据采集。也就是说,不管一个调用是发生在Application这一侧的客户端或服务端,或者一个加密之后的HTTPS调用、编码之后的HTTP2调用,还是普通明文的HTTP、Dubbo、MySQL、Redis调用,都能自动的获取到它的每一个调用的事件详情及RED(Request、Error、Delay)性能指标。
无论这个调用流经的是Pod的虚拟网卡、VM的虚拟网卡、宿主机的物理网卡,还是中间的NFV虚拟网关,或者七层API网关,只要有MetaFlow Agent部署到的地方,都可以通过eBPF/BPF技术从内核中获取到调用数据,并生成应用层面的RED指标、网络层面的吞吐、时延、异常、重传等指标。这样的指标采集是完全自动化的,它不需要开发者手动做任何的埋点或插码,所有这些能力通过部署MetaFlow Agent即可自动获取到。
同时观测数据来自系统中不同的层面,有来自应用程序函数的(uprobe)、有来自系统调用函数的(kprobe),也有来自虚拟机、宿主机、中间网关网卡流量的(BPF)。那么怎样把这些数据关联起来,使得我们能完整的观测一个调用的全栈性能?
可以依赖于MetaFlow的AutoTagging技术。MetaFlow Agent通过同步K8s、服务注册中心的大量的资源、服务、API属性信息,然后由Server进程汇总并统一插入到所有的可观测性数据上,可以无缝的、在所有数据之间关联切换,呈现应用调用的全栈性能。
对于AutoMetrics机制获取到的指标数据,基于SQL接口开发了相应的Grafana DataSource和Pannel,这张图里展示的是通过Grafana呈现的从应用到网络,包括HTTP、TCP、DNS协议、各个K8s工作负载和微服务的性能指标,以及K8s服务之间的应用调用关系——Universal Service Map。
02 全链路 AutoTracing
现在我们所看到的追踪图是残缺的、有盲点的,是一组用Java和Python构建的微服务。右上角是它的一部分调用拓扑,它的右侧是完成业务的Java微服务,左侧是完成权限验证的Python微服务。实际上他们应该是一个完整的Trace,最顶端使用Nginx等API网关将两组服务连接起来,但目前我们所能使用的手动插码技术可能由于各种各样的原因无法追踪完整。
缺少Infra层面的Span,以及可能由于不同服务团队使用不同的Tracer使得火焰图无法展现完整,亦或是缺乏对某些语言、某些RPC框架的插码导致追踪断裂。这些盲点会使我们在排查问题的时候经常找不到答案,导致团队之间相互推诿。
而这是MetaFlow自动追踪能力的一个示意图,依靠创新使用eBPF的能力,能自动化的、高度完整的展示出微服务调用链。在这张火焰图中,红色的部分是eBPF已经点亮的地方,eBPF追踪的是每个Request相关的TCP/UDP通信函数,通过挂载到这些系统调用函数中实现自动追踪。
这里面还是有一部分蓝色的地方没有点亮,这些缺失是未来云杉网络工作的方向。幸运的是现在已经有了非常好的思路,有望将AutoTracing的能力延展到异步调用场景、协程调度场景中。
当我们的观测性没有任何盲点的时候,就能回答一些以前完全回答不了的问题。比如业务开发人员抱怨SQL慢,从Java进程中输出的Span看到的时延是3秒,但是DBA跑到 MySQL的日志里面找了很久就是找不到慢日志,这个事怎么说?通过MetaFlow的全链路追踪能力,可以精确定位到根因,能直接告知到底是Java微服务和MySQL哪一方、以及中间链路的哪一跳出现了问题。
03 高性能 SmartEncoding
在可观测性领域 Telegraf、Prometheus等基本都使用Golang实现,MetaFlow为什么选择Rust呢?这其实和他所处理的数据量有关。Telegraf采集频率是一分钟一次,或者说十秒一次。但 MetaFlow采集的数据是精细到毫秒、微秒甚至到纳秒的,因为要去采集每一个请求,每一个网络上的TCP会话,因此Agent的资源消耗至关重要。
DeepFlow从2016年开始用Golang开发了第一代采集器Trident,再基于原生的Golang数据结构做了大量的优化,例如开发了自己的高性能hmap、高性能内存池hpool,这些现在都已经开源,大家可以上GitHub上查看。
这些非常细节的优化使得在Golang语言下,我们积累了诸多的10x性能提升点,但并没有满足这样的性能表现,从去年开始决定将采集器升级到Rust版本。使用Rust可以解决Golang中高频数据处理带来的GC问题、内存消耗问题。
左图是在一个极限环境下的压测,可以看到MetaFlow对CPU的影响。通过eBPF获取到所有的应用调用数据,对 CPU的影响增加只有3%(注意:测试的是一个非常简单的Hello World的Nginx web page)。通过从Golang到Rust的升级重构,获得了非常显著的性能提升,同时也打开了更多应用场景的大门。右图展示了MetaFlow Agent在智能汽车的loT环境中的使用。
第二方面的高性能还体现在Server端,从数据中可以看出资源开销相当于业务开销的1%,这是在大量的商业客户生产环境下验证的。
第三个方面是SmartEncoding智能标签编码技术。MetaFlow会为所有观测数据自动注入大量的Tag,比如在容器环境中,从客户端去访问服务端这样的双端数据,可能要注入上百个维度的标签,这些标签有是非常长的字符串,给后端存储造成了非常大的压力。
MetaFlow创新的使用SmartEncoding机制,在Agent上独立采集标签和观测数据,同步到Server端后对标签进行独立的整形编码,并将整形编码注入到观测数据中存储下来。创新的SmartEncoding机制可以使得整个标签的注入开销降低10倍。另外由于存储的标签都是Int编码之后的,有助于降低查询过程中的数据检索量,也能显著提升查询性能。
而对于一些衍生的Tag则完全没必要存储在数据库中,MetaFlow Server通过SQL接口抽象出来底层的一个大宽表。比如在底层存储了40个标签,通过Server的抽象,把它延展成100个标签的虚拟大宽表。上层应用在虚拟大宽表之上进行查询,完全感受不到标签是否存储在数据中、是以Int还是String的形式存储。
四、结语
在存储方面,作为第一个MetaFlow的开源版本,默认提供ClickHouse的选项,开发者也可以组合、扩展更多的数据库选项。因为MetaFlow Agent采集了各种类型的可观测数据,不同类型的数据,可以由擅长的数据库来存储。
MetaFlow向上提供统一的SQL查询接口,用于查询底层任何数据库中、任何类型的可观测性数据。作为一个可观测性平台,希望为开发者提供最标准的、最易于使用的查询接口,所以我们基于SQL开发了MetaFlow的Grafana DataSource和交互式的查询条件编辑器,开发者可基于SQL快速将MetaFlow融入到自己的可观测性平台中,同时也可基于SQL开发自己喜欢的QL方言。
MetaFlow未来的规划,就像攀登珠峰一样,目前不是从海平面开始攀登的,它站在DeepFlow六年的积累之上,已经有了非常酷的AutoMetrics,AutoTracing、AutoTagging、SmartEncoding等创新能力,这些能力会随着6月底的第一个版本出现在GitHub上,提供大家直接下载使用。希望MetaFlow的开源,能够帮助开发者构建一个自动化的可观测性平台,彻底释放开发者的生产力,带来自由。