分享一下可观测体系的实现

现在的业务系统具有很高的复杂性,为了能够追踪请求的完整流程,通常会实现一种叫做分布式追踪(Distributed Tracing)的机制。

而接入"分布式追踪"的方式或者说标准有很多, 比如:OpenTracing 、Zipkin 、SkyWalking等等。 本文的内容是基于"新星" - OpenTelemetry的。

选择OpenTelemetry的原因是:

  1. 它由CNCF托管, 并且提供了一套统一的 API,用于追踪和度量,这意味着开发者可以编写一次代码,然后将其导出到多个后端系统,而无需针对每个系统进行特定的适配。
  2. 支持多种编程语言,设计上支持扩展,允许开发者添加自定义的追踪器、度量收集器和导出器。
  3. 也支持接收Zipkin、Jaeger、Prometheus等格式的数据,拥有很高的集成度。

分布式追踪是可观测性的一个重要方面,而可观测性是一个更全面的概念,它结合了日志、度量和追踪来提供一个全面的系统视图,帮助团队确保系统可靠、高效和可维护。

OpenTelemetry 是 OpenTracing 和 OpenCensus 的继承者,旨在提供一种统一的框架和标准,用于观测性数据的收集、转换和导出。

它提供了一系列的 API 和 SDK,用于自动收集应用程序的指标(Metrics)、日志(Logs)和追踪(Traces)数据。

与服务网格的关系

个人认为服务网格与可观测是相辅相成的,但不是必须的。

我们的环境是存在服务网格的, 并且大多数应用都在网格中。 先抛开网格的治理能力, 在可观测的场景下,网格也为丰富数据做出了很多贡献~

OpenTelemetry基本架构

OpenTelemetry可以接收trace、metric、log数据, 这些数据可以是服务上报,也可从诸如kafka之类的中间件中获取。

服务数据可以使用官方提供的sdk,在代码中进行打桩上报。如果是java、dotnet这样的开发语言,官方也提供了代码注入的途径;go这种不支持注入的(也有编译时插桩的方案),官方提供了EBPF的内核hook。

阿里云编译插桩: https://github.com/alibaba/opentelemetry-go-auto-instrumentation

OpenTelemetry: https://github.com/open-telemetry/opentelemetry-go-instrumentation

Collector可以分为三个角色:

  • 接收器。 接收支持多种数据源或者数据格式, 所以了老的系统如zipkin等也可以无缝迁移; 也可以接入消息队列等进行削峰
  • 处理器。 接收到的数据可以进行清洗处理。如在trace场景下,正常的链路实际没有太大的价值, 所以可以使用尾部采样策略,只采错误的链路。
  • 导出器。 将处理后的数据导入到对应的中间件服务中。 如写入到ck、es等存储中间件, 也可以写入到kafka等消息队列削峰, 再由其他的导出器订阅数据并写入存储。
  • 连接器。 连接器其实是一个导出器和接收器的整合(所以我没有将它算到角色中),用于在collector内部进行数据处理和流转。

监控指标

在我们的平台中,可观测项目产生的指标大概可以分为两个来源:

  • 服务接入网格后, 由sidecar、gateway暴露的istio指标
  • 服务接入OpenTelemetry后,由sdk生产的源站指标和程序堆栈指标

网格指标采集

网格中的指标采集涉及到pod的发现,而pod发现又涉及到k8s权限问题(跨部门的权限沟通真的很头痛),所以是沿用已经存在的监控系统: serviceMonitor+prometheus进行采集,然后remotewrite到vm集群中。

网格的指标我们主要用两个istio_requests_totalistio_request_duration_milliseconds_*。 因为涉及到流量方向、请求path、状态码等信息存在label中,所以数据量比较大, 每天大概有2亿左右Series。

有尝试过对网格指标的label在prometheus推送时进行删减, 结果是数据乱掉了(因为删掉了一些标识性的label),精简label这个事情就暂时搁置了。

服务指标采集

服务接入OpenTelemetry后,由sdk生产的源站指标和程序堆栈指标采集方式有两种:

  • serviceMonitor+prometheus进行采集,然后remotewrite到vm集群中。 这个逻辑和网格指标是一样的。由prom采集的好处是可以将一部分压力分摊到业务的pod上, 坏处就是prom的单点采集瓶颈会比较大,我们也在探索使用vmagent替代prom的方案。
  • 远程写入到OpenTelemetry Collector, 由collector写入到vm集群中。

OpenTelemetry Collector目前对于metric的processor支持不是太好,实际使用下来性能和功能上都差强人意,好在我们目前没有太多对指标进行处理的需求,这一块后期还是有很大的探索和优化空间的

指标存储方案

指标存储对比过thanosvm,最终选择了vm进行存储, prometheus更多的是采集的角色。

存在多套集群、多套prometheus的环境下, thanos的查询效率实在太低了。举个例子来说,对于实时查询来说,thanos查询时对于每个后端的prom节点发送的都是全量查询数据, 如果涉及到历史数据,还需要加载bucket,不仅查询效率慢,而且对后端prom的压力很大。

相对来说vm本身实现了时序数据的存储机制, 集群模式更是可以将采集、查询、插入等模块分开, 不论从性能和架构上都更加清晰,也更容易横向扩展。

我们目前是6台48c512g的物理机裸跑, 承载每天10亿的Series。 这个vm集群即支持了监控报警,又支持了内部观测平台上的查询功能。

全链路trace数据

trace数据是整个可观测体系的核心, 也是最大的数据来源。

我们每天大概有1200亿 的span数据被发送到collector中, 最终根据各种采样策略后, 会有250亿 的span数据存在数据库中, 并且保留7天。 这个数据量还在随着用户接入逐步提升。

我们的trace处理体系是脱胎于signoz的,后面根据内部的业务情况和数据使用又诞生了自己的collector处理体系。

trace来源

从上报方式来分有两种:

  • 程序直接上报trace/span到collector
  • 从日志中解析trace,清洗后转换为trace/span信息,上报到collector

对于trace处理的优化主要集中在以下几点:

  1. 如何提高向clickhouse写入的效率
  2. 要对trace进行尾部采样处理,需要预先对同一个trace链路的span进行整合, 如何高效进行
  3. 日志数据因为存在延迟, 所以会导致trace链路不完整

我们在对这几点进行对应的处理后, ck的吞吐量提升30%以上, 处理所占的资源也有20%左右的下降。 后面的文章会分享这一部分的优化。

相关推荐
ITPUB-微风6 小时前
58同城深度学习推理平台:基于Istio的云原生网关实践解析
深度学习·云原生·istio
野猪佩挤9 小时前
minio作为K8S后端存储
云原生·容器·kubernetes
福大大架构师每日一题15 小时前
6.4 k8s的informer机制
云原生·容器·kubernetes
炸鸡物料库16 小时前
Kubernetes 使用 Kube-Prometheus 构建指标监控 +飞书告警
运维·云原生·kubernetes·飞书·prometheus·devops
ITPUB-微风16 小时前
云原生DevOps:Zadig架构设计与企业实践分析
运维·云原生·devops
IT闫17 小时前
【Dubbo+Zookeeper】——SpringBoot+Dubbo+Zookeeper知识整合
分布式·zookeeper·云原生·dubbo
桂月二二18 小时前
基于eBPF的零信任API网关:重塑云原生时代的安全通信范式
安全·云原生
Karoku06618 小时前
【CI/CD】持续集成及 Jenkins
运维·ci/cd·docker·云原生·容器·kubernetes·jenkins
KTKong1 天前
kubeadm拉起的k8s集群证书过期的做法集群已奔溃也可以解决
云原生·容器·kubernetes
呱牛do it1 天前
【系列专栏】银行IT的云原生架构-混合云弹性架构 13
微服务·云原生·金融·架构