生产环境里的Istio和Kubernetes(二):Tracing

在上一篇博文里,我们介绍了Service Mesh(服务网格)Istio的组成部分,并回答了Istio新手经常会问的问题。本文会研究如何整理这些在网络上收集到的tracing信息。 在听到Service Mesh这个新概念的时候,开发人员和系统管理员首先考虑的事情是tracing。我们会为每个微服务添加特定的代理服务器来处理所有TCP流量。你可能会自然地认为很容易收集所有网络事件的信息。但不幸的是,实际需要考虑很多细节。让我们一起研究一下。 #一大误解是可以轻松得到网络流量上的网络交互数据 实际上,相对容易的仅仅是得到由箭头连接的系统节点图,以及服务间的数据速率(实际上,仅仅是单位时间内的比特数)。但是,绝大多数情况下,服务通过应用层协议来通信,比如HTTP,gRPC,Redis等。当然,我们想看到这些协议的tracing信息,想看到应用级别请求的速率,而不是单纯的数据速率。另外,我们想知道协议的请求延时。最终,则想看到从用户输入触发的请求到收到回复这之间的全路径。不过这可不是一件容易的事情。 首先,从Istio的架构角度看怎么发送tracing信息。上文提到,Istio有一个特定的组件收集Telemetry,称为Mixer。但是,在当前的1.1.*的版本里,代理服务器,也就是Envoy代理,直接发送tracing span。Envoy代理支持使用Zipkin协议发送tracing span。其他协议则要求单独的插件。Istio自带预编译并且预先配置好的Envoy代理,仅支持Zipkin协议。比如,如果用户想使用Jaeger协议并通过UDP发送tracing span,那么他需要构建自定义的istio-proxy镜像。Istio-proxy的确支持自定义插件,但是,还仅仅有alpha版本。因此,如果想避免多个自定义的设置,那么接受并存储tracing span的方案里并没有太多的选择。可以使用最受欢迎的协议,Zipkin或者Jaeger,但是如果使用后者,所有东西都需要使用Zipkin兼容的协议(性能会差一些)来上传。Zipkin协议通过HTTP协议将所有tracing信息发送给收集器,消耗更大。 如上文所说,我们需要跟踪应用层协议。这意味着每个服务旁的代理服务器必须理解当时发生的网络事件。Istio默认所有端口使用plain TCP,这意味着不会发送trace。要发送trace,首先需要在main mesh config里启用相关的配置,然后依据服务内协议的实现来命名所有Kubernetes服务实体的所有端口。比如:
apiVersion: v1
kind: Service
metadata:
  name: nginx
spec:
  ports:
  - port: 80
    targetPort: 80
    name: http
  selector:
    app: nginx
还可以使用组合名称,比如http-magic(Istio能够识别http并且将端口识别为http端口)。 为了避免修补多个配置来定义协议,有如下workaround:在Pilot组件执行协议决策逻辑的时候修改它的配置。然后,当然需要切回标准逻辑并且切换所有端口的命名惯例。 为了理解协议是否定义正确,可以从Envoy代理进入任意Sidecar容器,从location/config_dump发送请求给Envoy接口的admin端口。在最终的配置里,检查相应服务的Operation字段。在Istio里,它就相当于请求目的地的标识。在Istio里自定义这个参数(之后可以在tracing系统里看到),启动Sidecar容器的时候设置serviceCluster标记。比如,它可以从Kubernetes API得到的变量里计算出来:
--serviceCluster ${POD_NAMESPACE}.$(echo ${POD_NAME} | sed -e 's/-[a-z0-9][i]-[a-z0-9][/i]$//g')
这里很好地解释了Envoy的trace是如何工作的。 在Envoy代理的启动标记里必须指定发送tracing span的端口,比如:`—-zipkinAddress tracing-collector.tracing:9411`。 #另一个误解是用户可以轻松获取系统内请求的所有trace 不幸的是事实并非如此。实现的复杂度取决于服务是如何交互的。为什么是这样呢? 问题在于要让Istio代理理解服务的入站和出站请求的匹配关系,仅仅截获所有流量是不够的。你需要某种匹配标识符。HTTP Envoy代理使用特别的header,这样Envoy能够准确理解服务的哪个请求生成对其他服务的特定请求。这些header包括: - x-request-id - x-b3-spanid - x-b3-parentspanid - x-b3-sampled - x-b3-flags - x-ot-span-context 如果你只有一个单点,比如,一个基础的客户端,这里可以加入逻辑,然后需要做的就是等待library在所有客户端里更新完毕。但是如果你面对的是一个复杂的异构系统,没有统一的服务-服务的网络流量,那么很可能就会有问题。不加这样的逻辑,所有的tracing信息都是单层级的。你可以得到所有服务-服务的交互,但是却无法形成网络流量链。 #结论 Istio提供了方便的工具收集网络上的所有tracing信息,但是它的实现要求系统的变更,要考虑到Istio的实现的独特性。这是要解决的两大问题:定义应用层的协议(Envoy代理必须支持)以及设置转发信息,匹配入站和出站请求(如果是HTTP协议的话,使用header)。如果这两大问题都解决了,那么你就有了强大的工具,可以从网络上透明地收集信息,即使这是个高度异构的系统,可能由多种语言使用多种架构组成。 下一篇博文里,我们会讨论Istio最大的挑战之一——每个Sidecar代理容器所带来的高RAM使用率的问题——并且讨论如何解决这个问题。 原文链接:Istio and Kubernetes in production. Part 2. Tracing(翻译:崔婧雯) =========================== 译者介绍 崔婧雯,现就职于IBM,高级软件工程师,负责IBM WebSphere业务流程管理软件的系统测试工作。曾就职于VMware从事桌面虚拟化产品的质量保证工作。对虚拟化,中间件技术,业务流程管理有浓厚的兴趣。

0 个评论

要回复文章请先登录注册