14. 使用 Linkerd 进行分布式跟踪

在实践中使用分布式跟踪可能很复杂, 为了从高层次解释您得到了什么以及它是如何完成的, 请查看服务网格中的分布式跟踪:四个误区

本指南将引导您完成 emojivoto配置启用跟踪。关于使用 Linkerd 使用分布式跟踪的最佳方式的一些建议,请跳到最后。

要使用分布式跟踪,您需要:

  • 安装 Linkerd-Jaeger 扩展。
  • 修改您的应用程序以发出跨度。

emojivoto 中,一旦所有这些步骤都完成,就会有一个看起来像这样的拓扑:

Topology
Topology

前提条件

  • 要使用本指南,您需要在集群上安装 Linkerd。 如果您还没有这样做,请按照安装 Linkerd 指南进行操作。

安装 Linkerd-Jaeger 扩展

获取分布式跟踪设置的第一步是将 Linkerd-Jaeger 扩展安装到您的集群上。 这个扩展由一个收集器(collector)、一个 Jaeger 后端和一个 Jaeger-injector 组成。 收集器消费从网格和您的应用程序发出的跨度, 并将它们发送到 Jaeger 后端,后者存储它们并提供 dashboard 以查看它们。 Jaeger-injector 负责配置 Linkerd 代理以发出 span

要安装 Linkerd-Jaeger 扩展,请运行以下命令:

linkerd jaeger install | kubectl apply -f -

您可以通过运行以下命令来验证 Linkerd-Jaeger 扩展是否已正确安装:

linkerd jaeger check

安装 Emojivoto

emojivoto 添加到您的集群并使用 Linkerd proxy 注入它:

 linkerd inject https://run.linkerd.io/emojivoto.yml | kubectl apply -f -

在进入下一步之前,请确保一切都已启动并使用 kubectl 运行以下命令:

kubectl -n emojivoto rollout status deploy/web

修改应用

服务网格的大多数功能不同,分布式跟踪需要修改应用程序的源。 跟踪需要某种方式将传入的请求与您的应用程序与传出的请求绑定到相关服务。 为此,将向每个请求添加一些 header,其中包含跟踪的唯一IDLinkerd 使用 b3 propagation 传播格式将这些东西联系在一起。

我们已经修改了 emojivoto 以使用此信息检测其请求,此 commit 显示了这是如何完成的。 对于大多数编程语言,它只需要添加一个客户端库来处理这个问题。 Emojivoto 使用 OpenCensus 客户端,但也可以使用其他客户端。

要在 emojivoto 中启用跟踪,请运行:

kubectl -n emojivoto set env --all deploy OC_AGENT_HOST=collector.linkerd-jaeger:55678

此命令将添加一个环境变量,使应用程序能够传播上下文并发出跨度

探索 Jaeger

随着 vote-bot 开始跟踪每个请求,跨度现在应该出现在 Jaeger。要进入 UI,运行:

linkerd jaeger dashboard
Jaeger
Jaeger

您可以在下拉列表中搜索任何服务,然后单击 Find Tracesvote-bot 是一个很好的入门方式。

Search
Search

单击特定跟踪将提供所有详细信息,您将能够看到每个代理的跨度!

Search
Search

该输出中肯定有很多 linkerd-proxy 跨度。 在内部,代理具有服务器端客户端。 当请求通过代理时,由服务器接收,然后由客户端发出。 对于在两个网格 Pod 之间传递的单个请求,总共会有 4 个跨度。 当请求遍历该代理时,两个将在端,当远程代理接收到请求时,两个将在目标端。

集成 Dashboard

设置好 Linkerd-Jaeger 扩展后, 由于代理添加了应用元数据作为 trace 属性, 用户可以通过点击 Metrics Table 中的 Jaeger 图标, 直接从 linkerd-web 仪表板直接跳转到相关资源 trace,如下图 :

Linkerd-Jaeger
Linkerd-Jaeger

要获得该功能,您需要安装(或升级)Linkerd-Viz 扩展,指定暴露 Jaeger UI 的服务。 默认情况下,这将是这样的:

linkerd viz install --set jaegerUrl=jaeger.linkerd-jaeger:16686

清理

要进行清理,请通过运行以下命令卸载 Linkerd-Jaeger 扩展emojivoto

linkerd jaeger uninstall | kubectl delete -f -
kubectl delete ns emojivoto

带上你自己的 Jaeger

如果您有一个现有的 Jaeger 安装, 您可以配置 OpenCensus 收集器向它发送跟踪, 而不是 Linkerd-Jaeger 扩展中内置的 Jaeger 实例。

创建以下 YAML 文件,该文件禁用内置 Jaeger 实例并指定 OpenCensus 收集器的配置。

cat <<EOF > jaeger-linkerd.yaml
jaeger:
  enabled: false

collector:
  config: |
    receivers:
      otlp:
        protocols:
          grpc:
          http:
      opencensus:
      zipkin:
      jaeger:
        protocols:
          grpc:
          thrift_http:
          thrift_compact:
          thrift_binary:
    processors:
      batch:
    extensions:
      health_check:
    exporters:
      jaeger:
        endpoint: my-jaeger-collector.my-jaeger-ns:14250
        insecure: true
    service:
      extensions: [health_check]
      pipelines:
        traces:
          receivers: [otlp,opencensus,zipkin,jaeger]
          processors: [batch]
          exporters: [jaeger]
EOF
linkerd jaeger install --values ./jaeger-linkerd.yaml | kubectl apply -f -

您需要确保将本示例中的 my-jaeger-collector.my-jaeger-ns:14250exporters.jager.endpoint 设置为适合您环境的值。 这应该指向端口 14250 上的 Jaeger Collector

YAML 文件与 Helm values.yaml 合并,后者显示了可以配置的其他可能值。

也可以手动编辑 OpenCensus 配置以将其导出到它支持的任何后端。 有关完整列表,请参阅 OpenCensus 文档

故障排除

我没有看到代理的任何跨度

Linkerd proxy 使用 b3 propagation 传播格式。 一些客户端库,例如 Jaeger,默认使用不同的格式。 您需要将客户端库配置为使用 b3 格式让代理参与跟踪。

建议

Ingress

ingress 是分布式跟踪的一个特别重要的组件,因为它创建每个跟踪的跨度, 并负责决定是否应该对该跟踪进行采样。 让 ingress 做出所有采样决策可确保对整个轨迹进行采样不采样, 并避免创建“部分轨迹(partial traces)”

分布式跟踪系统都依赖于服务来传播有关从接收到的请求到发送的请求的当前跟踪的元数据。 这一元数据称为跟踪上下文,通常编码在一个或多个请求 header 中。 有许多不同的跟踪上下文 header格式,虽然我们希望生态系统最终会收敛于像 W3C tracecontext 跟踪上下文这样的开放标准, 但我们今天只使用 b3 format。 作为最早广泛使用的格式之一,它具有最广泛的支持,尤其是在 Nginx 等入口中。

此参考架构包括一个简单的 Nginx 配置,该配置对 50% 的跟踪进行采样并将跟踪数据发送到 收集器(使用 Zipkin 协议)。任何入口控制器都可以在这里代替 Nginx 使用,只要它:

  • 支持概率采样
  • 以 b3 格式编码跟踪上下文
  • OpenCensus collector 支持的协议中发出 span

如果使用 helm 安装 ingress-nginx,您可以使用以下命令配置跟踪:

controller:
  config:
    enable-opentracing: "true"
    zipkin-collector-host: linkerd-collector.linkerd

客户端库

虽然服务可以手动传播跟踪传播header,但使用执行以下三件事的库通常要容易得多:

  • 将跟踪上下文从传入请求头传播到传出请求头
  • 修改跟踪上下文(即开始一个新的跨度)
  • 将此数据传输到跟踪收集器(trace collector)

我们建议在您的服务中使用 OpenCensus 并使用以下内容对其进行配置:

OpenCensus agent exporter 将通过 gRPC API 将跟踪数据导出到 OpenCensus collector。 如何配置 OpenCensus 的详细信息会因语言而异,但有许多流行语言的指南。 您还可以使用我们的示例应用程序 EmojivotoGo 中查看端到端示例。

您可能会注意到 OpenCensus 项目存在维护模式并且将成为 OpenTelemetry 的一部分。 不幸的是,OpenTelemetry 尚未准备好生产,因此 OpenCensus 仍然是我们目前的建议。

也可以使用许多其他跟踪客户端库。只需确保正在使用 b3 传播格式, 并且客户端库可以以 collector 已配置为接收的格式导出其跨度

收集器: OpenCensus

OpenCensus collectorOpenCensus agent exporter 接收跟踪数据, 并可能在将该数据发送到 Jaeger 之前进行转换过滤。 将 OpenCensus exporter 发送到 OpenCensus collector 为我们提供了很大的灵活性: 我们可以切换到 OpenCensus 支持的任何后端,而无需中断应用程序。

后端: Jaeger

Jaeger 是使用最广泛的跟踪后端之一,并且有充分的理由:它易于使用并且在可视化跟踪方面做得很好。 但是,可以改用 OpenCensus 支持的任何后端

Linkerd

如果您的应用程序注入了 LinkerdLinkerd proxy 将 参与跟踪并将跟踪数据发送到 OpenCensus collector。 这丰富了跟踪数据,并允许您准确查看请求在代理和线路上花费的时间。

虽然 Linkerd 只能主动参与使用 b3 传播格式的 trace, 但 Linkerd将始终透明地转发未知的请求头, 这意味着它永远不会干扰使用其他传播格式的跟踪。