政采云可观测性建设实践

云杉 世纪 | 2024-02-05

政采云可观测平台背景与规划
首先第一个就是我们构建平台的一个背景。
我们之前是为了去观测业务的运行状态,或者说帮助我们去做故障排查的时候,其实是引入了三个工具的,比如 Prometheus 帮助我们去告诉我们有没有出现问题, Pinpoint 是做链路追踪的,他就是去告诉我们问题在哪。日志的 ELK SLS 是我们直接去定位问题是什么,但是有一个问题是什么呢?这三个工具对于我们去观测业务状态,或者说故障排查的话越来越吃力了。那为什么说越来越吃力了?这个其实基本上也是我们传统监控方案去往可观测去转的时候,基本上都会面临的一些问题。
比如说我们非常依赖人力去关联数据,因为我们这些工具引入的时候其实是垂直引入的。怎么理解垂直引入呢?也就是说我用什么工具,我就看什么数据,这些数据之间没有关联,那怎么去做关联?这个时候就依赖人去把数据给关联起来了。那比如说我们如果说出现了故障的话,我们能够给到使用者的东西,就是我所有的环境所能提供各个维度的数据都在这里了,你去查一下。

这个对人的负担其实挺大的,因为我这么多数据我要从何去查起?另外一个就是依赖经验去分析原因,这个怎么理解呢?就是我们目前能够给到用户的能力,都是我们之前故障处理的沉淀的经验。事实上我们针对于这些数据没有任何的处理,只是数据的堆彻,所以这个时候我们越来越觉得我们传统的观测方式或者说监控方式已经不足以帮助我们去更好地观察业务的运行状态了,这也是基本上各家公司去往可观测性去转的话,都会都想解决的一个痛点。

那另外一个问题是什么呢?还是人的问题,我们的业务越来越复杂,比如说某一个链路的话,它可能涉及到应用特别的多。当我们有一个业务故障的时候,谁能够告诉我这个业务故障影响的范围?在我们场景下观测到的一个现象,比如说我们出了一个故障,我们一般会拉一个群,然后看到的这个现象就是这个群的人数会越来越多,直到这个故障解决。

本质上的原因是什么呢?就是我们为了去降低我们个故障的排查时间,就只能去靠人海战术了。这样的话我们付出的成本其实就是比较大的。所以我们在这个背景下,我们在想我们之前的观测方式是不是有问题了?或者说基本上是没有办法产生更大的价值了?

建设符合 OpenTelemetry 标准的可观测平台
在这个背景下我们想着是时候拿出一套完整的解决方案了。主要的短期目标就是这五点。首先我们要去构建一个标准化的数据,另外一个就是关联可以关联的数据,还有一点就是我们的数据的覆盖面一定要全,在这个基础之上我们去做统一观测和多维度分析。
是标准化,目前可观测性存在的标准其实挺多的,比如说有的用 Skywalking、 Zipkin 之类的。在我们去调研的时候,我们应该去选怎样的标准呢?我们选择了 OpenTelemetry,为什么选择这个标准(OpenTelemetry)呢?主要原因是我们去调研的时候发现在可观测性生态里面,大家都支持将 OTEL 的数据导入进来,或者说导出或者说处理,那这样的话我们就能够享受可观测性生态的便捷,就比如说我们已经享受到了 DeepFlow 给我们带来的便捷。另外一点就是 OTEL 在我们的场景里面它可以支持多个语言的SDK,同时而且是同一套 OTEL 的 API 标准,所以我们选择了OpenTelemetry。
另外一个就是数据可关联,这个可能有一点奇怪的是什么呢?我们如果说我们遵守可观测性的标准的话,数据其实已经关联上了,那为什么还要强调一下数据可关联呢?因为其实我们在去排查故障的时候,如果说纯靠 Trace Metrics Log 的话,其实还不一定能够找到问题,我们可以关联一些更多的数据,比如说我们可以关联我们 Paas 平台的数据,当前这个链路关联的应用近期有没有做过发布?

因为 80% 的故障基本上都是业务变更导致的嘛,然后还有一点就是我们可以去关联一下指标相关的数据,因为我们如果纯粹通过 TraceID 去找指标数据的话,其实是不太全的。比如说某一个链路慢的话,我们可能要关注某个节点、某个环境、某个应用的线程池的负载情况。总之一点就是我们关联一切可以关联的数据,然后目的的话就是方便我们顺藤摸瓜找根因。
然后还有一个就是数据覆盖全,其实刚一开始我是没想过覆盖全这个问题的,是接触到 DeepFlow 以后,我们才发现我们的观测好像有盲区,然后这个时候我又打开了 OTEL 的官网,我发现它喊出的口号是高质量无处不在的便携式遥测技术。我这里提的一个关键字就是无处不在。为什么要强调一下无处不在呢?

因为事实上如果说你的观测没有覆盖全的话,用 DeepFlow 的话讲就是你的观测存在盲区,所以我们尽可能的就是想我们对于观测的对象做到全面的覆盖,也就是全栈追踪。
这里引用一个经典的老图,大家如果参加可观测性的会的话,基本上都可以看到这个图。这里想提的一点是什么呢?就是我们首先关注的是业务,然后关注业务,关注承载业务的应用,但是想要让这个应用正常稳定的运行的话,其实它有一些底层的一些依赖,比如说它依赖的上下游,以及上下游之间的网络通信、数据库中间件等等之类的。这些也都是我们可观测性需要覆盖的维度。
另外一个其实是针对我们我们公司的一个场景专门去弄的,因为在我们的场景里面其实是有很多个环境,我们有一个云端的环境,以及我们在各个省份,比如说有江西环境、上海环境、山西环境等等之类的。我们之前碰到的一个问题是什么呢?就是我们想要去找数据,还需要先确定它在哪个环境,以及每个环境可能因为人的原因,它配置的采集规则不一样,告警规则不一样,分析规则也不一样。所以我们在构建可观测性平台的时候,第一个就是我们要做一个统一的入口,所有的观测行为、观测操作、观测分析都可以通过一个入口来去解决。
另外想要达到统一观测的目的是什么呢?就是我们想要通过一种方式去观测多个维度的数据,像比如说我们去查指标的时候,一般是通过PromQL,那如果说去查日志的话,就是通过 LogQL,或者说就直接搜关键字,那在这种情况下,如果交给研发的话,其实是还有一点学习成本,那我们希望能够通过一种统一的查询方式,比如说 SQL 为什么说选择 SQL?因为其实在数据分析的场景的话, SQL 是一个很通用的语言。另外一点的话,我们通过 SQL 来去查询数据的话,还可以去实现一个实时的统计和分析的能力,也就说实现一个 ETL 的功能,那具体怎么做的呢?
其实这个主要是依赖 Flink 的功能,那通过 Flink 将我们从 Kafka 拿到的观测数据把它转成一个表格,那这样的话我们之前预定义好的一些 SQL,在这个过程当中可以去执行,然后拿到分析结果,我们直接写到数仓里面去,那后面的逻辑我们就可以直接交给我们的业务研发,去分析一下我们业务目前是一个什么样的情况。或者说交给我们的大数据平台去统计一下报表,看一下当前业务某一段时间的情况。
然后按照我们之前的需求,我们是构建了这么一套架构。主要下面三层的话,主要就是数据采集和数据计算的能力了。在这个能力的基础之上我们去提供数据服务。因为我们在数据计算阶段通过对 Trace Log Metrics,我们又做了进一步的加工处理,提出我们认为更有价值的数据。

这个时候在数据服务阶段的话我们就很好做了,比如说我们可以很简单的去构建一个可视化,去实现可视化以及监控大盘。然后这个时候我们还可以去做根因分析、智能预测。那再更上一层的话,其实就是我们观测平台的管控面了。像前面提到的应用管理主要是面向用户的。

比如说在应用管理里面,我们可以去做比如说应用的诊断、应用的拓扑管理等等之类的。然后后面的规则管理、 SQL 管理、告警管理,主要就是在数据计算阶段去注入计算的逻辑,然后告警就不多说了。然后云岛协同也是我刚刚提到的一个痛点,就是统一观测。
建设过程中面临的问题与挑战
我们现在相当于一个房子的基础架构去构建好了以后,然后想在公司内部去做推广。但是我们刚一开始想着,如果说我们遵守了 OTEL 的标准的话,是不是我们的推广其实是一个很丝滑的一件事情,但是现实给了我们狠狠的一巴掌。
主要的原因是什么呢?就是更换探针的成本高和链路不全。首先说一下更换探针的成本高,事实上如果说我们直接用 OTEL 的探针,其实是可以做到自动注入的,但是有一个问题是什么呢?就是我们之前是用了 Pinpoint Agent 的,然后的话我们还对 Pinpoint Agent 做了一些改造,如果说我们想直接换成 OTEL 的 Agent 的话,这个时候还需要手动插桩才能说我们现在拿到的数据可以覆盖之前 Pinpoint 的数据,那如果说涉及到手动插桩的话,这个时候其实让研发去做适配,这个周期会拉得比较长,因为研发可能更关注就是我业务相关的需求要准时上线。

那还有一点的原因是什么呢?就是我们之前已经注入了 Pinpoint Agent 的,也就是说如果说我们要换探针的话,要么就全换,要么就不换,否则的话我们如果只换一部分的话,就会导致我 Pinpoint 里面数据不是全的,我们自己的观测平台数据也不是全的,整体是一种不可用的状态,又要继续靠人去拿到全部数据。

还有一种情况就是有一些应用它承载的业务已经进入了一个稳定的状态,其实它不怎么迭代的,这个时候如果说你要去换探针的话,可能还需要再重新走一遍测试的流程而且如果不是业务需求驱动的应用更新的话,想要去重新发版的话,其实是很难去推的。再有一点就是链路不全,这个也就是我之前提到的,就是我们之前的观测是存在盲区的,存在什么盲区呢?

我们在 Pinpoint 上面,如果说观测到了某一个 Span 的耗时比较长,但是我们不知道它的耗时主要是花在哪里的,因为事实上当请求从应用 A 到应用 B 之间还有一个很长的网络链路,而这个链路在云原生的环境下往往是比较复杂的,在这种情况下的话我们现有的观测能力其实是不能告诉我到底卡在哪个点上的。

针对这两个问题的话,我们刚一开始就是想的就是能不能通过 DeepFlow 直接全部解决这两个问题。我不换探针了,我直接用 DeepFlow 的数据,链路不全的话,这个也是 DeepFlow 的看家本领。

但是我们实际测下来有一个问题是什么呢?就是不是所有的链路 DeepFlow 都能全部的构建出来,这个时候它可能还需要我们手动去找业务相关的一些字段,去构建一个完整的链路。而且与此同时就是我们刚刚开始想着就是如果说 DeepFlow 的数据能不能直接踢掉 APM 的数据,后面发现下来其实也很难。
这种方式最好的结合方式其实是 DeepFlow 和 APM 一起结合,这样的话我们 APM 层面的数据也有了,然后存在的一些盲区 DeepFlow 也帮我们补全了。然后当时的话我们和 DeepFlow 其实是有一个讨论的,就是说我们该去怎么解决这个问题,然后 DeepFlow 同学给了我们一个思路,什么思路呢?就是既然我们现在已经有了 Pinpoint 接入了,那其实就相当于是我们可以拿到 APM 层面的数据了,只是说它不符合你们之前预想的数据标准,那把它转成你们想要的数据标准不就可以了吗?然后当时讨论下来,发现确实可行。为什么说确实可行?因为 DeepFlow 他之前干过这事,他是过来人,之前 DeepFlow 的同学就将 Skywalking 的链路信息转成 OTEL 标准的。那我们在想我们按照这个思路去实践的话,其实也是可行的。
所以我们一个我们构建的一个想法就是我们直接去把 Pinpoint 的数据转成 OTEL 标准的就可以了。但是接下来碰到的另一个问题是什么呢?就是 Pinpoint 的数据不支持导出,也就是说它对我们来说它就是一个信息孤岛,那我们怎么样才能把这部分数据给拿下来,并转换成我们想要的数据标准呢?那我们想到的第一个方案就是我们直接在 pinpoint-gent 和 pinpoint-collector 通信的时候,我们直接拦一道,我们通过 eBPF 采集,把 Pinpoint 的数据拿过来,然后去做一下转换,再发给 OTEL 的 collector 就可以了。