实例 | 当Istio遇见Jaeger,如何解决端到端分布式追踪问题?

Posted ServiceMesh中文网

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实例 | 当Istio遇见Jaeger,如何解决端到端分布式追踪问题?相关的知识,希望对你有一定的参考价值。

译者:王晓轩

原文:When Istio Meets Jaeger — An Example of End-to-end Distributed Tracing


译者话:


       本文从微服务架构为何引入开始,介绍了程序设计在使用微服务架构后存在的一些问题,以及用 service mesh 的方式如何去解决它们。


       作者从 Kuberentes 集群的安装开始,到配置 Istio 和 Jaeger,图文并茂的展示了部署结果,文章的最后部分以源码和讲解结合的方式,说明了 Istio 的大致工作原理。深入浅出,既有理论价值又有实际经验可以借鉴。





众所周知,Kubernetes 很厉害!因为它能帮助很多工程师团队去实现 SOA(面向服务的架构体系)的梦想。在过去很长一段时间里,我们一直围绕 monolith mindset 的概念来构建我们的应用程序,也就是说,我们会在一个很牛X的计算机上运行一个应用的所有组件。像帐户管理、结算、报告生成等这些工作,都是在一个机器上用共享资源的方式运行。这种模式一直很OK,直到 SOA 的出现。它通过将应用程序拆分成一个个相对小的组件,让它们之间使用 REST 或 gRPC 进行通信。我们这么做,是希望应用程序比以前的管理方式更加容易,但后来发现,迎接我们的是一堆新的挑战(所谓愿望是丰满的,现实是骨感的)。跨服务之间的访问如何通信?如何去 observe 两个 microservices 之间的通信(如日志或 tracing)?本文演示如何在 Kubernetes 集群内部设置 OpenTracing,以便在服务之间进行 end-to-end 的 tracing,并在服务内部使用正确的工具进行 tracing。



创建kubernetes集群

首先,我们需要有一个可用的 Kubernetes 集群。我在 AWS 上使用 kops(注1),因为它提供了一系列 K8S 集群自动化操作命令,如 upgrade,scaling up/down 和多个 instance group。除了方便的集群操作之外,kops 团队还随着 Kubernetes 版本升级而升级,以支持 Kubernetes 的最新版本。我觉得这东西很酷,很有用!

按照这个步骤(注2)可以安装和使用 kops。



创建集群

kops create cluster  
--name steven.buffer-k8s.com
--cloud aws
--master-size t2.medium
--master-zones=us-east-1b
--node-size m5.large
--zones=us-east-1a,us-east-1b,us-east-1c,us-east-1d,us-east-1e,us-east-1f
--node-count=2
--kubernetes-version=1.8.6
--vpc=vpc-1234567a
--network-cidr=10.0.0.0/16
--networking=flannel
--authorization=RBAC
--ssh-public-key="~/.ssh/kube_aws_rsa.pub"
--yes

这个命令会告诉 AWS 在 us-east-1上创建一个 VPC 1234456a,会有 1个 master 节点和 2个 worker(minion)节点,它的 CIDR (无类别域间路由,Classless Inter-Domain Routing)是10.0.0.0/16。大约10分钟后,你的集群就可以使用了。当然在此过程中,你也可以用 watch kubectl get nodes 去查看整个创建的过程。


一旦 Kubernetes 集群安装完成,你就可以在上面去安装 Istio (注3)了。它是管理一个集群内部服务之间流量的服务网格。由于它的这种特性,使得 Istio 能够很轻松的实现在两个服务之间进行 trace。



安装Istio

从 GitHub repo(注4)下载 Istio。

在你下载的 Istio 目录中可以找到 istio.yaml 文件,运行: 


kubectl apply -f install/kubernetes/istio.yaml

现在你的 Istio 应该已经运行在 Kubernetes 集群里了。而且它应该同时创建了一个 Nignx 的 Ingress Controller,这个东西是用来接收外面对集群内资源的访问的。我们一会儿会介绍如何设置 IP。



安装Jaeger

Jaeger 和 Istio 一起协同工作,可以实现跨服务的 tracing。你可以用这个命令安装 Jaege。


kubectl create -n istio-system -fhttps://raw.githubusercontent.com/jaegertracing/jaeger-kubernetes/master/all-in-one/jaeger-all-in-one-template.yml


完成之后,你可以通过 Jaeger 的 UI 访问它 

实例 | 当Istio遇见Jaeger,如何解决端到端分布式追踪问题?



Instrument Code

Jaeger 和 Istio 安装成功以后,你就可以看到跨服务的 traces 了。这是因为 Istio 注入了 Envoy sidecars 来处理服务间通信,而被部署的应用程序只与指定的 sidecar 进行通信。 从我的 GitHub (注5)你可以找到一个简单的应用程序例子。


main.go


package main import ( "fmt" "log" "net/http" "runtime" "time" "github.com/opentracing-contrib/go-stdlib/nethttp" opentracing "github.com/opentracing/opentracing-go" jaeger "github.com/uber/jaeger-client-go" "github.com/uber/jaeger-client-go/zipkin" ) func indexHandler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "hello world, I'm running on %s with an %s CPU ", runtime.GOOS, runtime.GOARCH) } func getTimeHandler(w http.ResponseWriter, r *http.Request) { log.Print("Received getTime request") t := time.Now() ts := t.Format("Mon Jan _2 15:04:05 2006") fmt.Fprintf(w, "The time is %s", ts) } func main() { zipkinPropagator := zipkin.NewZipkinB3HTTPHeaderPropagator() injector := jaeger.TracerOptions.Injector(opentracing.HTTPHeaders, zipkinPropagator) extractor := jaeger.TracerOptions.Extractor(opentracing.HTTPHeaders, zipkinPropagator) // Zipkin shares span ID between client and server spans; it must be enabled via the following option. zipkinSharedRPCSpan := jaeger.TracerOptions.ZipkinSharedRPCSpan(true) sender, _ := jaeger.NewUDPTransport("jaeger-agent.istio-system:5775", 0) tracer, closer := jaeger.NewTracer( "myhelloworld", jaeger.NewConstSampler(true), jaeger.NewRemoteReporter( sender, jaeger.ReporterOptions.BufferFlushInterval(1*time.Second)), injector, extractor, zipkinSharedRPCSpan, ) defer closer.Close() http.HandleFunc("/", indexHandler) http.HandleFunc("/gettime", getTimeHandler) http.ListenAndServe( ":8080", nethttp.Middleware(tracer, http.DefaultServeMux))


从第28-30行开始,我们创建了一个 Zipkin propagator,告诉 Jaeger 从 OpenZipkin 的 request header 中捕捉上下文(context)。你可能会问,这些 header 是怎么被放到 request 开始部分的?还记得吗,当我说 Istio 用 sidecar 处理服务间的通信,并且应用程序只与它交互。对!你可能已经猜到了。为了让 Istio 跟踪服务之间的 request,当有 request 进入集群时,Istio 的 Ingress Controller 将注入一组 header。然后,它通过 Envoy sidecars 进行传播,并且每个都会将相关的 associated span 上报给 Jaeger。它会让 spana 对应到每一个 trace。我们的应用程序代码利用这些 header来收集内部服务之间的 spans。


下面是一个被 Istio 的 Ingress Controller 注入到 OpenZipkin 中 header的列表


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


可以用下面这个 yaml 文件去部署一个简单的应用程序


apiVersion: extensions/v1beta1 kind: Deployment metadata:  labels:    app: myhelloworld  name: myhelloworld spec:  replicas: 1  template:    metadata:      labels:        app: myhelloworld    spec:      containers:      - image: stevenc81/jaeger-tracing-example:0.1        imagePullPolicy: Always        name: myhelloworld        ports:        - containerPort: 8080      restartPolicy: Always --- apiVersion: v1 kind: Service metadata:  name: myhelloworld  labels:    app: myhelloworld spec:  type: NodePort  ports:  - port: 80    targetPort: 8080    name: http  selector:    app: myhelloworld --- apiVersion: extensions/v1beta1 kind: Ingress metadata:  name: myhelloworld  annotations:    kubernetes.io/ingress.class: "istio" spec:  rules:  - http:      paths:      - path: /        backend:          serviceName: myhelloworld          servicePort: 80      - path: /gettime        backend:          serviceName: myhelloworld

         servicePort: 80




部署

kubectl apply -f <(istioctl kube-inject -f myhelloword.yaml)

请注意,可以从 Istio 的 bin 目录下找到命令istioctl

现在是收获的时候了,当我们向 Istio Ingress Controller 发送请求时,它将在服务以及应用程序之间进行 trace。从截图中我们可以看到从不同地方报告的3个spans

  • Ingress Controller

  • Envoy sidecar for application 

  • Application code 

    实例 | 当Istio遇见Jaeger,如何解决端到端分布式追踪问题?


    展开 trace(看到3个spans)就可以看到 end-to-end 的 tracing




结束语

  • SOA 带来了一些待解决问题,特别是在如何 observe 服务之间的通信上。

  • Istio+Jager 的集成解决方案可以从 servcie 到 service 的这个层面解决这个问题。

  • 使用 OpenZipkin prapagator 配合 Jaeger,可以在 end-to-end 上 tracing。



注:

1、 https://github.com/kubernetes/kops

2、https://github.com/kubernetes/kops/blob/master/docs/aws.md

3、https://istio.io/

4、 https://github.com/istio/istio/releases/tag/0.4.0

5、https://github.com/stevenc81/jaeger-tracing-example






推荐阅读

倍道而进:Conduit 0.3 正式从 experimental 升级到 alpha,实现生产指日可待?


收藏篇 | 20篇精选干货,Service Mesh内容一应俱全


专题 | A Service Mesh for Kubernetes第4期:轻松预发微服务


实测 | 转型微服务,这4大工具谁是API网关性能最优?





ServiceMesh中文社区:

ServiceMesh中文社区(servicemesh.cn)已上线,Istio、Conduit官方文档翻译版已在社区发布,欢迎大家登录浏览。点击阅读原文即可浏览!社区翻译小组志愿者招募中,有兴趣的私信小数即可~


ServiceMesh微信交流群:



以上是关于实例 | 当Istio遇见Jaeger,如何解决端到端分布式追踪问题?的主要内容,如果未能解决你的问题,请参考以下文章

六、跨语言微服务框架 - Istio日志采集EFK

idou老师教你学Istio 20 : Istio全景监控与拓扑

微服务全链路跟踪:jaeger集成grpc

将 JDBC 查询信息添加到 opentracing/Jaeger 跨度

idou老师教你学Istio 17 : 通过HTTPS进行双向TLS传输

Istio Service Mesh 教程——一文了解 Istio 全部功能,示例见 GitHub