前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Istio多集群链路追踪实践

Istio多集群链路追踪实践

作者头像
CNCF
发布2022-11-28 17:29:56
9910
发布2022-11-28 17:29:56
举报
文章被收录于专栏:CNCF

为了实现多集群的流量治理,我们采用Istio官方提供的多主集群进行Istio的部署,这样就出现一个问题,对于多主集群的Istio治理,如何进行跨集群的流量监控,实现跨集群的服务链路追踪。

Istio作为服务网格在云原生下服务网格的事实标准,宣称有三大功能:流量管理、可观测、安全能力,可观测独占一席,可见可观测对于Istio本身的重要程度。可观测主要包含三个方面:指标、日志、全链路追踪。

作者:李运田, 中国移动云能力中心软件开发工程师,专注于云原生、Istio、微服务、Spring Cloud 等领域。

01

单集群链路追踪

在分布式链路跟踪中有两个重要的概念:Trace和Span。Trace是请求在分布式系统中的整个链路视图,Span则代表整个链路中不同服务内部的视图,Span组合在一起就是整个Trace的视图。在整个请求的调用链中,请求会一直携带TraceId往下游服务传递,每个服务内部也会生成自己的SpanId用于生成自己的内部调用视图,并和TraceId一起传递给下游服务。TraceId在请求的整个调用链中始终保持不变,所以在日志中可以通过TraceId查询到整个请求期间系统记录下来的所有日志。请求到达每个服务后,服务都会为请求生成SpanId,而随请求一起从上游传过来的上游服务的 SpanId会被记录成parent-SpanId。当前服务生成的SpanId随着请求一起再传到下游服务时,这个SpanId又会被下游服务当做 parent-SpanId记录。

Istio 通过Envoy完成全链路追踪所需的数据生成。也就是说Istio中实现链路追踪功能的是通过Envoy实现,Envoy 会为其所代理的程序自动地生成全链路追踪中的Span,但是要想自己的服务实现全链路追踪并不止是通过在服务中注入Sidecar就可以实现,也依赖于服务把生成的Header传递给流出的请求。在开始我们使用Springboot框架进行多个服务之间的调用,服务注入Sidecar后,通过观察发现Jaeger展示的链路追踪中每个服务都生成了一个TraceId,后来发现没有把生成的Header进行传递,通过在服务中添加一个拦截器实现Header的传递,这样在Jaeger的链路中即可看到整个链路信息。

02

多集群链路追踪

Istio中多集群的链路追踪是基于Istio的多集群能力实现,部署服务到多个集群,通过Istio的能力进行多集群统一服务治理,Istio只是在上层进行配置的修改,在部署的时候每个集群会单独部署Jaeger和ES,为实现多集群链路追踪,需要修改配置。

1、修改每个集群的Istio configmap

Istio的链路追踪通过zipkin直接传输到Jaeger-collector,Jaeger-collector将数据发送到自己现有的ES集群进行存储,Jaeger-query直接去现有ES集群查询。链路追踪发送到Jaeger-collector,如果不在同个namespace下,需要修改zipkin地址为Jaeger的zipkin收集地址。Envoy这个proxy会默认使用环境变量来设置zipkinAddress地址,默认地址是zipkin.istio-system:9411,可在yaml下查找zipkinAddress来修改。

2、修改链路追踪存储

Istio的链路追踪通过zipkin直接传输到Jaeger-collector,Jaeger-collector将数据发送到自己现有的ES集群进行存储,Jaeger-query直接去现有ES集群查询,修改每个集群的Jaeger-collector、Jaeger-query中的es.server-urls为同一个ES地址,使得所有集群中的链路追踪信息进行统一保存。

3、在每个集群中通过Jaeger-query查询到的多集群链路追踪信息即为全链路追踪信息

当client:8070调用provider:8090时,整个链路中会使用同一个TraceId,并把链路信息保存到同一个ES中,最后Jaeger从每个集群中都可以获取到整个服务链路的调用信息。

03

多集群链路追踪结果

在我们的测试中,使用client:8070调用provider:8090,通过上述配置后,可以在Jaeger中得到正常的多集群链路追踪信息,并且每个集群中的Jaeger得到的链路追踪信息一致。

打开每个Span可以看到具体的服务链路调用信息。

在我们探索之初,每个集群的Jaeger使用的ES都是各个集群中单独部署的,虽然Istio是多主模式部署,但是并不会在每个集群中汇总服务的链路追踪信息,这样每个集群中的Jaeger获取的链路追踪都是各个集群中的服务信息,如果服务出现了跨集群调用,那么服务的链路追踪就不完整。

有的链路有一个Span,有的链路有两个Span,可以打开链路追踪查看详细的内容

04

实现原理

服务网格就像微服务的通信层,服务之间的所有通信都是通过网格进行的。它可以实现负载均衡、服务发现、流量转移、速率限制、指标(metrics)收集等功能,Envoy就是这样的一个服务网格。在我们的例子中,Envoy将帮助我们生成唯一根请求id (x-request-id),生成子请求id,并将它们发送到Jaeger或Zipkin这样的追踪系统,这些系统存储、聚合追踪数据并为其提供可视化的能力。

Envoy主要用三个功能来支撑系统范围内的跟踪

1)生成Request ID: envoy会在需要的时候生成UUID,并操作名为[x-request-id]的HTTP Header。应用可以转发这个Header用于统一的记录和追踪。

2)集成外部追踪服务: envoy支持可插件的外部跟踪可视化服务。目前支持LightStep、zipkin或者Zipkin兼容的后端(例如:jaeger).另外可自己添加其它的追踪服务。

3)客户端跟踪ID连接:x-client-trace-id Header可以用来把不信任的请求ID连接到受信的x-request-id Header上。

当我们调用client:8070后,注入到client:8070的Envoy会根据请求生成TraceId和SpanId。

Envoy的全链路追踪的实现,主要是三部分,一部分是通过Tracing driver抽象类实现的各种对接Tracing系统的驱动,一部分是负责管理根据配置创建的各种Tracer的TracerManager,还有一部分则主要在HTTP Connection Manager实现上,用于在不同的阶段生成、补充、提交相关的Span。

1.在HTTPConnectionManager的配置对象初始化时,会根据配置从TracerManager中获取Tracer实例。

代码语言:javascript
复制
if (config.has_tracing()) {
http_tracer_ = http_tracer_manager.getOrCreateHttpTracer(getPerFilterTracerConfig(config));
const auto& tracing_config = config.tracing();
Tracing::OperationName tracing_operation_name;
...
}

2.当HTTP Connection Manager解码请求的Header完成时,会通过Tracer实例的startSpan函数创建Span,这个Span将存在于当前Manager实例的active_span_字段上,随后HTTP Connection Manager的流程中,会根据active_span_的存在与否选择性地向 Span 上记录信息。

代码语言:javascript
复制
if (connection_manager_.config_.tracingConfig()) {
traceRequest();
}
filter_manager_.decodeHeaders(*request_headers_, end_stream);
resetIdleTimer();
}
void ConnectionManagerImpl::ActiveStream::traceRequest() {
const Tracing::Decision tracing_decision =
Tracing::HttpTracerUtility::shouldTraceRequest(filter_manager_.streamInfo());
ConnectionManagerImpl::chargeTracingStats(tracing_decision.reason, connection_manager_.config_.tracingStats());
active_span_ = connection_manager_.tracer().startSpan(
*this, *request_headers_, filter_manager_.streamInfo(), tracing_decision);
if (!active_span_) {
return;
}
...
}

3.Envoy生成完相关TraceId和SpanId后,能够自动发送Span,但是用户自己的业务代码需要处理如下HTTP请求头信息,这样才能把多个Span正确的关联到同一个追踪上,我们使用的是Zipkin,Envoy 要传播的是如下B3 Header。

代码语言:javascript
复制
• x-request-id
• x-b3-traceid
• x-b3-spanid
• x-b3-parentspanid
• x-b3-sampled
• x-b3-flags
• x-ot-span-context

比如我们的代码里通过Springboot拦截器进行Header的传递,Bookinfo中review在调用rating时通过如下方式处理Header。

05

总结

Istio服务网格在入口流量和出口流量上都做了代理,Istio中实现链路追踪功能的是通过Envoy实现,Envoy 会为其所代理的程序自动地生成全链路追踪中的Span,但是要想自己的服务实现全链路追踪并不止是通过在服务中注入Sidecar就可以实现,也依赖于服务把生成的Header传递给流出的请求,通过在多集群中进行配置,即可实现多集群链路追踪。

参考链接:

[1]https://istio.io/latest/docs/setup/install/multicluster/multi-primary/

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-11-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CNCF 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
服务网格
服务网格(Tencent Cloud Mesh, TCM),一致、可靠、透明的云原生应用通信网络管控基础平台。全面兼容 Istio,集成腾讯云基础设施,提供全托管服务化的支撑能力保障网格生命周期管理。IaaS 组网与监控组件开箱即用,跨集群、异构应用一致发现管理加速云原生迁移。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档