Istio - DistributedTracing(服务追踪)

官方参考文档:

https://istio.io/docs/tasks/telemetry/distributed-tracing/overview/

https://istio.io/docs/tasks/traffic-management/egress/

https://istio.io/docs/examples/advanced-gateways/egress-gateway/

https://istio.io/help/faq/distributed-tracing/#why-mixer-spans

准备工作

(1)在使用Isito服务追踪之前,需要先开启选项(默认helm安装):

          --set tracing.enabled=true;

(2)其次需要设定traceSampling(追踪百分比,范围0-100):

         方式1:--set pilot.traceSampling=20 

         方式2:修改deployment->istio-pilot中环境变量 PILOT_TRACE_SAMPLING(默认1.0)

(3)暴露Jaeger dashboard:

         可参见官网通过port-forward或k8s-ingress:https://istio.io/docs/tasks/telemetry/distributed-tracing/jaeger/

         在实际使用中,可以直接建立k8s ingress与jaeger servcie对应即可:

kind: Ingress
apiVersion: extensions/v1beta1
metadata:
  name: tracing
spec:
  rules:
  - host: tracing.xxx.com
    http:
      paths:
      - backend:
          serviceName: tracing
          servicePort: 80

Jaeger运行后,效果截图如下:

追踪服务串联

Istio中服务追踪默认只会追踪到2级,

例如A -> B -> C, 在Istio中会出现2条追踪链路:A -> B 和B -> C,而不会出现我们期望的A -> B -> C的形式,

如果想要服务串联起来,需要对服务间调用进行改造,在Istio中应用程序通过传播http header来将span关联到同一个trace;

Istio追踪相关http header如下:

  • x-request-id
  • x-b3-traceid
  • x-b3-spanid
  • x-b3-parentspanid
  • x-b3-sampled
  • x-b3-flags
  • x-ot-span-context

服务间调用有很多方式,例如Spring RestTemplate, Apache HttpClient等,之前在项目中使用的自己封装的基于Apache HttpClient的服务调用工具,关于HttpClient可以通过对HttpClient设置拦截器进行相应reqeust header的提取与设置,具体代码如下:

/**
 * Isito服务追踪 - 请求拦截器
 *
 * @author luohq
 * @date 2019/5/30
 */
public class IstioTraceInterceptor implements HttpRequestInterceptor {

    private static final Logger logger = LogManager.getLogger(IstioTraceInterceptor.class);

    /**
     x-request-id
     x-b3-traceid
     x-b3-spanid
     x-b3-parentspanid
     x-b3-sampled
     x-b3-flags
     x-ot-span-context
     */
    private final List<String> TRACE_HEADER_LIST = Arrays.asList("x-request-id", "x-b3-traceid", "x-b3-spanid", "x-b3-parentspanid", "x-b3-sampled", "x-b3-flags", "x-ot-span-context");

    /**
     * 处理request请求 - 添加服务追踪相关请求header
     *
     * @param httpRequest
     * @param httpContext
     * @throws HttpException
     * @throws IOException
     */
    @Override
    public void process(HttpRequest httpRequest, HttpContext httpContext) throws HttpException, IOException {
        //从请求头中提取trace相关header(x-)
        Map<String, String> istioTraceHeaders = extractTraceHeaders();
        //设置rpc外部调用trace相关header(x-)
        istioTraceHeaders.forEach((headerName, headerVal) -> httpRequest.addHeader(headerName, headerVal));
    }

    /**
     * 从请求头中提取trace相关header(x-)
     *
     * @return
     */
    private Map<String, String> extractTraceHeaders() {
        Map<String, String> traceHeaderMap = new HashMap<>(7);
        try {
            //获取当前SpringMvc上下文中的request对象
            HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
            //获取request请求中的所有header名称
            Enumeration<String> headerNames = request.getHeaderNames();
            //遍历header名称 -> 过滤出Istio追踪的相关的header
            while (headerNames.hasMoreElements()) {
                String headerName = headerNames.nextElement();
                if (TRACE_HEADER_LIST.contains(headerName)) {
                    //提取Istio追踪的相关的header
                    traceHeaderMap.put(headerName, request.getHeader(headerName));
                }
            }
            logger.debug("【ISTIO】cur request istio trace header: {}", traceHeaderMap);
        } catch (Exception e) {
            logger.debug("【ISTIO】extract request istio trace header fail!");
        }
        return traceHeaderMap;
    }
}

...
//构建HttpClient对象
CloseableHttpClient httpClient = HttpClientBuilder.create()
        .setDefaultRequestConfig(requestConfig)
        //设置Isito服务追踪拦截器
        .addInterceptorFirst(new IstioTraceInterceptor())
        .build();
CloseableHttpResponse response = httpClient.execute(httpPost);

在对服务调用工具进行改造后,多服务间调用可以串联到一起(A -> B -> C),实际最终效果图如下:

集群外服务追踪

在Istio1.1.0(实际使用1.1.7)中默认放开了对所有外部服务的访问权限,所以对外部服务的追踪默认是不生效的;

相关设置:global.outboundTrafficPolicy.mode=ALLOW_ANY(默认) | REGISTRY_ONLY

关于设置envoy可以访问外部服务,参见官方文档:https://istio.io/docs/tasks/traffic-management/egress/

若想对集群外服务进行追踪,需要通过egress网关的形式(ServcieEntry + EgressGateway + istio-egressgateway + DestinationRule + VirtualService),具体参见官方文档:https://istio.io/docs/examples/advanced-gateways/egress-gateway/

实际测试过程中只对Http请求进行了追踪而Https并没有生效,下图的测试用例对又拍云相关服务进行了追踪:

注:在进行了egress相关配置后,对外部服务的追踪并没有和downstream(调用方服务)串联起来,需要在调用外部服务的时候同样传播追踪相关的http header才能真正将外部服务与集群内服务的追踪串联起来(如上图效果),否则便会出现单独的追踪链路,如下图:

另外,关于egressgateway的相关配置过于繁琐难懂,如果没有特殊要求,不考虑配置istio-egressgateway出口网关(仅作为探索与学习),默认放开对所有外部服务的访问权限(同时也失去的对外部服务的控制权,无法将外部服务接入istio集群);

禁用【istio-mixer】span追踪

在实际测试过程中,会看到很多和istio-mixer相关的span,如下图:

上述istio-mixer相关调用是Isito执行policy检查时进行的Istio平台级调用,可以通过编辑 istio-policy 的deployment配置,删除命令行参数 --trace_zipkin_url=http://zipkin:9411/api/v1/spans以禁用对istio-mixer的追踪;

官方参考文档:https://istio.io/help/faq/distributed-tracing/#why-mixer-spans

 

另外由于Istio默认关闭了policy检查(global.disablePolicyChecks=true),所以在服务的实际调用过程中是不会去调用istio-mixer相关服务的,之所以会在上述服务追踪中多次出现istio-mixer相关span,是由于之前在进行rateLimits相关测试时开启了policy检查机制;

kiali集成Jaeger

可以在kiali中集成Jaeger,集成方式如下:
   (1)修改isttio-system -> configmap -> kiali -> jaeger.url:
      jaeger:
        url: http://tracing.xxx.com/jaeger
      grafana:
        url: 
    (2)重启istio-system -> deployment -> kiali即可

配置成功后会在kiali左侧菜单最下方出现【Distributed Tracing】菜单项,单击此菜单项则跳转到相应Jaeger页面;

同时在Services中的具体服务中,也可以单击【Traces】按钮弹出当前服务的追踪信息; 

Jaeger存储

在Isito中的默认安装中,Jaeger默认使用内存来存储追踪记录,重启Jaeger后所有之前的追踪记录就都没有了,若真正想在生产环境使用Jaeger,需要集成自定义的Jaeger(可外接Cassandra, ES存储等);

Supported storage backends:

具体集成自定义Jaeger,继续探索......

Envoy | Mixer追踪

Isito支持Envoy追踪(默认)和Mixer追踪,继续探索......;

发布了56 篇原创文章 · 获赞 6 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/luo15242208310/article/details/90903411