生产中的 Istio 和 Kubernetes。 第 2 部分. 追踪

在最后 文章 我们研究了 Service Mesh Istio 的基本组件,熟悉了该系统并回答了开始使用 Istio 时通常出现的主要问题。 在这一部分中,我们将了解如何通过网络组织跟踪信息的收集。

生产中的 Istio 和 Kubernetes。 第 2 部分. 追踪

当许多开发人员和系统管理员听到 Service Mesh 这个词时,他们首先想到的就是跟踪。 事实上,我们向每个网络节点添加了一个特殊的代理服务器,所有 TCP 流量都经过该网络节点。 看来现在可以轻松地发送有关网络上所有网络交互的信息。 不幸的是,实际上有许多细微差别需要考虑。 让我们看看它们。

误解一:我们可以免费获得在线徒步数据。

事实上,为了相对自由,我们只能得到我们系统中通过箭头连接的节点以及服务之间传递的数据速率(实际上只是单位时间的字节数)。 然而,在大多数情况下,我们的服务是通过某种应用层协议进行通信的,比如 HTTP、gRPC、Redis 等。 当然,我们希望看到专门针对这些协议的跟踪信息;我们希望看到请求速率,而不是数据速率。 我们想要了解使用我们的协议的请求的延迟。 最后,我们希望查看请求从登录系统到接收用户响应的完整路径。 这个问题已经不再那么容易解决了。

首先,让我们从 Istio 架构的角度来看一下发送跟踪跨度是什么样的。 正如我们从第一部分中记得的那样,Istio 有一个名为 Mixer 的独立组件用于收集遥测数据。 然而,在当前版本 1.0.* 中,发送是直接从代理服务器(即 envoy proxy)完成的。 Envoy 代理支持使用开箱即用的 zipkin 协议发送跟踪范围。 可以连接其他协议,但只能通过插件。 通过 Istio,我们立即得到了一个组装并配置好的 envoy 代理,它只支持 zipkin 协议。 例如,如果我们想使用 Jaeger 协议并通过 UDP 发送跟踪范围,那么我们需要构建自己的 istio-proxy 镜像。 istio-proxy 支持自定义插件,但仍处于 alpha 版本。 因此,如果我们不想进行大量自定义设置,则用于存储和接收跟踪跨度的技术范围就会减少。 事实上,在主要系统中,现在您可以使用 Zipkin 本身或 Jaeger,但使用 zipkin 兼容协议将所有内容发送到那里(效率低得多)。 zipkin 协议本身涉及通过 HTTP 协议将所有跟踪信息发送给收集器,这是相当昂贵的。

正如我已经说过的,我们想要跟踪应用程序级协议。 这意味着每个服务旁边的代理服务器必须了解现在正在发生什么类型的交互。 默认情况下,Istio 将所有端口配置为普通 TCP,这意味着不会发送任何跟踪。 为了发送跟踪,您必须首先在主网格配置中启用此选项,并且非常重要的是,根据服务中使用的协议命名 kubernetes 服务实体的所有端口。 也就是说,例如,像这样:

apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  ports:
  - port: 80
    targetPort: 80
    name: http
  selector:
    app: nginx

您还可以使用 http-magic 等复合名称(Istio 将看到 http 并将该端口识别为 http 端点)。 格式为:proto-extra。

为了不修补大量配置来确定协议,您可以使用一种肮脏的解决方法:在 Pilot 组件刚刚运行时修补它 执行协议定义逻辑。 当然,最终,有必要将此逻辑更改为标准,并切换到所有端口的命名约定。

为了了解协议是否真正正确定义,您需要进入任何带有 envoy 代理的 sidecar 容器,并使用位置 /config_dump 向 envoy 接口的管理端口发出请求。 在生成的配置中,您需要查看所需服务的操作字段。 它在 Istio 中用作发出请求的标识符。 为了在 Istio 中自定义此参数的值(然后我们将在跟踪系统中看到它),有必要在启动 sidecar 容器的阶段指定 serviceCluster 标志。 例如,可以从向下的 kubernetes API 获取的变量这样计算:

--serviceCluster ${POD_NAMESPACE}.$(echo ${POD_NAME} | sed -e 's/-[a-z0-9]*-[a-z0-9]*$//g')

了解特使中跟踪如何工作的一个很好的例子是 这里.

用于发送跟踪跨度的端点本身还必须在 Envoy 代理启动标志中指定,例如: --zipkinAddress tracing-collector.tracing:9411

误解二:我们可以通过开箱即用的系统以低廉的成本获得完整的请求跟踪

不幸的是,事实并非如此。 实现的复杂性取决于您已经如何实现服务交互。 这是为什么?

事实上,为了让 istio-proxy 能够理解传入服务请求与离开同一服务的请求的对应关系,仅仅拦截所有流量是不够的。 您需要有某种通信标识符。 HTTP Envoy 代理使用特殊标头,Envoy 通过该标头了解对服务的哪个特定请求会生成对其他服务的特定请求。 此类标头的列表:

  • x-请求-id,
  • x-b3-traceid,
  • x-b3-西班牙,
  • x-b3-parentspanid,
  • x-b3-采样,
  • x-b3-标志,
  • x-ot-span-上下文。

如果你有一个单点,比如一个基本的客户端,你可以在其中添加这样的逻辑,那么一切都很好,你只需要等待这个库为所有客户端更新即可。 但是,如果您有一个非常异构的系统,并且通过网络从一个服务转移到另一个服务没有统一,那么这很可能是一个大问题。 如果不添加这样的逻辑,所有的追踪信息都将只是“单层”。 也就是说,我们将接收所有服务间交互,但它们不会被粘合到通过网络的单个通道链中。

结论

Istio 提供了一个方便的工具来通过网络收集跟踪信息,但您必须了解,为了实现,您需要调整您的系统并考虑 Istio 实现的功能。 因此,需要解决两个要点:定义应用程序级别的协议(必须得到 envoy 代理的支持)和设置从来自服务的请求转发有关请求到服务的连接信息(使用标头) ,对于 HTTP 协议)。 当这些问题得到解决后,我们就有了一个强大的工具,可以让我们透明地从网络收集信息,即使是在用许多不同语言和框架编写的非常异构的系统中。

在下一篇关于 Service Mesh 的文章中,我们将讨论 Istio 的最大问题之一——每个 sidecar 代理容器对 RAM 的大量消耗,并讨论如何处理它。

来源: habr.com

添加评论