使用Elasticsearch、Cassandra和Kafka实行Jaeger持久化存储

2021-03-15 17:01:45 浏览数 (1)

在生产环境中运行系统涉及到对高可用性、弹性和故障恢复的要求。在运行云原生应用程序时,这一点变得更加关键,因为在这种环境中,基本的假设是计算节点会中断,Kubernetes节点会宕机,微服务实例可能会失败,而服务预计会继续运行。

在最近的一篇文章中,我介绍了Jaeger的不同组件和在生产中部署Jaeger[1]的最佳实践。在那篇文章中,我提到Jaeger使用外部服务来摄入和持久化span数据,比如Elasticsearch、Cassandra和Kafka。这是由于Jaeger收集器是一个无状态的服务,你需要将它指向某种存储,它将转发span数据。

在这篇文章中,我将讨论如何在生产中摄入和存储Jaeger追踪数据,以确保弹性和高可用性,以及为此需要设置的外部服务。我将介绍:

  • 使用Elasticsearch和Cassandra的Jaeger标准持久化存储
  • 使用gRPC插件的替代持久化存储
  • 使用Kafka处理高负载追踪数据流
  • 在开发期间使用jaegertracing all-in-one[2]的Jaeger持久化存储

与Elasticsearch、Kafka或其他外部服务一起部署Jaeger

Jaeger的部署可能涉及额外的服务,如Elasticsearch、Cassandra和Kafka。但是这些服务是Jaeger安装的一部分吗?这些服务是如何部署的?

Jaeger操作器和Jaeger的Helm chart(见Jaeger的部署工具的这篇文章[3])提供了一个自配置的Elasticsearch/Cassandra/Kafka集群(Jaeger的部署也部署这些集群)的选项,以及连接到现有集群的选项。

自配置选项提供了一个很好的起点,但你可能更喜欢独立部署这些服务,以便更好地根据你的团队的DevOps实践,对部署、管理、监视、升级和保护这些集群的方式进行更好的灵活性和控制。特别是,如果你已经在运行Kafka或Elasticsearch集群,那么重用这些基础架构组件可能比维护一个单独的集群更有意义。

作为Jaeger后端存储:Elasticsearch vs. Cassandra

对于生产部署,Jaeger目前提供了对两种存储解决方案的内置支持,这两种解决方案都是非常流行的开源NoSQL数据库:Elasticsearch和Cassandra。Jaeger采集器和查询服务需要配置所选择的存储解决方案,以便对其进行写入和查询。你可以通过环境变量传递所需的存储类型和数据库端点。例如,一个基本的Elasticsearch设置将定义以下环境变量:

代码语言:javascript复制
SPAN_STORAGE_TYPE=elasticsearch
ES_SERVER_URLS=<...>

直接到存储架构的说明。来源:jaegertracing.io

那么你应该使用哪一个存储后端:Elasticsearch还是Cassandra?

Jaeger团队明确建议使用Elasticsearch多于Cassandra作为存储后端。他们有很好的理由[4]

  • Cassandra是一个键值数据库,因此通过追踪ID检索追踪更高效,但是它不提供与Elasticsearch相同的强大搜索功能。实际上,Jaeger后端在客户端实现了搜索功能,在k-v存储之上,这是有限的,可能会产生不一致的结果(详见issue-166)。Elasticsearch不受这些问题的困扰,因此具有更好的可用性。Elasticsearch也可以直接查询,例如从Kibana仪表板,并提供有用的分析和聚合。
  • 根据过去的性能实验,我们发现Cassandra的单次写入速度要比Elasticsearch快得多,这可能意味着Cassandra可以维持更高的写入吞吐量。然而,由于Jaeger后端需要在k-v存储器上实现搜索功能,因此将span写入Cassandra实际上会遇到较大的写放大:除了为span本身写一条记录之外,Jaeger还对服务名称和操作名称索引执行额外的写操作,以及每个标签的额外索引写入。相比之下,将span保存到Elasticsearch是一次写入,并且所有索引都在ES节点内进行。结果,Cassandra的总体吞吐量与Elasticsearch相当。

Cassandra后台的一个好处是简化了维护,因为它支持TTL数据。在Elasticsearch中,数据过期是通过索引旋转来管理的,这需要额外的设置(参见Elasticsearch Rollover[5])。

Jaeger的替代持久化存储

除了对Elasticsearch和Cassandra的内置支持外,Jaeger还支持gRPC插件[6](SPAN_STORAGE_TYPE=gRPC-plugin),它可以为其他存储类型开发定制插件。Jaeger社区目前提供了几种持久化存储类型的集成,其中四种类型目前被定义为“可用”:ScyllaDB、fluxdb、Couchbase和Logz.io(免责声明:我在Logz.io工作)。

其他尚未实现的集成包括来自大型云供应商的NoSQL数据存储,如Amazon DynamoDB、Azure CosmosDB和Google BigTable,以及流行的SQL数据库MySQL和PostgreSQL。你可以在这个Jaeger GitHub问题[7]检查额外的存储后端列表和更新状态。

使用Kafka摄入高负荷Jaeger跨度数据

如果你监视许多微服务,如果你有大量的span数据,或者如果你的系统在某些情况下产生数据突发,那么你的外部后端存储可能无法处理负载,并可能成为瓶颈,影响总体性能。在这种情况下,你应该采用我在上一篇文章中提到的流部署策略,即在收集器和存储之间使用Kafka来缓冲Jaeger收集器的span数据。

用Kafka作为中间缓冲区的架构说明。来源:jaegertracing.io

在这种情况下,你配置Kafka作为Jaeger收集器(SPAN_STORAGE_TYPE=Kafka)的目标,以及相关的Kafka broker、主题和其他参数。

我想强调的是,Kafka不是一个可替代的后端存储(虽然设置SPAN_STORAGE_TYPE=Kafka可能会让人困惑)。Jaeger的后端仍然需要一个后端存储,Kafka作为缓冲来消除压力。

为了支持流媒体部署,Jaeger项目还提供了Jaeger Ingester服务,它可以异步读取Kafka主题并写入存储后端(Elasticsearch或Cassandra)。当然,如果需要特定的目标存储或摄入策略,你可以选择实现自己的服务来完成同样的任务。

在开发期间使用jaegertracing all-in-one的Jaeger持久化存储

到目前为止,我讨论了生产部署。然而,如果你正在探索Jaeger或正在做一个小型PoC或开发,那么你可能正在使用Jaeger的一体化安装,你可能想知道这如何适用于你。

All-in-one是一个单节点安装,你不必为非功能性需求(如弹性或可伸缩性)而烦恼。在一体化部署中,Jaeger默认使用内存持久化。另外,你可以选择使用Badger[8],它提供基于文件系统的单节点存储(类似于Prometheus模型)。你可以在这里[9]找到更多关于使用Badger的细节。

请记住,内存和Badger都只适用于一体化部署,不适合用于生产部署。

总结

在生产环境中部署Jaeger时,你需要解决数据持久化、高可用性和可伸缩性等问题。为了解决这些问题,你需要部署额外的服务。

首先,你应该为span数据部署和配置外部持久化存储。在生产环境中,Jaeger推荐的持久化存储是Elasticsearch。

其次,当处理高负荷的跨度数据时,你应该在存储前部署Kafka来处理摄入和提供反压力。

在生产中运行需要很多其他的考虑,这篇文章没有提到,例如升级Jaeger组件,Elasticsearch、Kafka或部署中的任何附加服务;监控不同的服务,并保护对这些服务的访问。

感谢Juraci Paixão Kröhling和Yuri Shkuro。

参考资料

[1]

生产中部署Jaeger: https://medium.com/jaegertracing/a-guide-to-deploying-jaeger-on-kubernetes-in-production-69afb9a7c8e5

[2]

jaegertracing all-in-one: https://www.jaegertracing.io/docs/1.18/cli/#jaeger-all-in-one

[3]

这篇文章: https://logz.io/blog/jaeger-kubernetes-best-practices/

[4]

理由: https://www.jaegertracing.io/docs/1.18/faq/

[5]

Elasticsearch Rollover: https://logz.io/blog/managing-elasticsearch-indices/#elasticsearch-rollover

[6]

gRPC插件: https://github.com/jaegertracing/jaeger/tree/master/plugin/storage/grpc

[7]

问题: https://github.com/jaegertracing/jaeger/issues/638

[8]

Badger: https://github.com/dgraph-io/badger

[9]

这里: https://www.jaegertracing.io/docs/latest/deployment/#badger---local-storage

0 人点赞