最近在搭建 istio 环境,正好调研到服务治理的链路追踪这一层,istio 所支持的有 jaeger、zipkin 以及 lightstep,本篇探索一下生产环境下 jaeger 的部署。
Jaeger 简介
Jaeger 是Uber推出的一款开源分布式追踪系统,兼容OpenTracing API。分布式追踪系统用于记录请求范围内的信息,包括一次调用的服务链路以及每个服务的延时,能够帮助我们很好的分析微服务间链路调用的错误及瓶颈。
OpenTracing api 及其原理将在下一篇 blog 中介绍。由于 istio 默认支持 Jaeger,因此准备测试下 Jaeger与Istio的集成。
Jaeger 整体架构如下图,主要包括3个组件: agent,collector以及query(UI)
- agent: 用于监听应用传来的链路信息,并传递给collector,
- collector:收集链路信息,并持久化。 其支持的后端存储为 Cassandra、ElasticSearch。此外也支持对接 Kafka,以进行后续的流式处理(可连入 spark、flink 以进一步分析)
- query:提供查询的 api 接口及 UI 界面
Jaeger vs Zipkin vs Skywalk
//TODO
Jaeger 部署
在 K8s 环境中,Jaeger 支持两种模式部署:
- all-in-one
- 生产模式
all-in-one
all-in-one 模式是 istio 默认支持的模式,只需要在使用 helm 部署 istio 时,修改 values.yml 中 tracing: enabled: true
即可。这样无需其他操作。
由于 all-in-one 模式是用于测试的demo,因此所有的链路信息默认存储在内存中,无法用于生产环境。
若单独在 K8s 平台中, Jaeger 官方推荐使用 Jaeger Operator 部署。Operator 部署相对来说比较简单,参考连接https://www.jaegertracing.io/docs/1.14/operator/,此处不再赘述。
Operator 是 K8s 平台提供的一种可自定义 Controller 的方式,此外仍需定义一系列的 CRD,自定义 Operator 通过监听 CRD 的状态更新,实现一系列的逻辑,比如创建 deployment 等。
生产环境部署
Jaeger 在生产环境,需要独立部署三个组件,这样可以提高软件的扩展性和稳定性。
在 K8s 平台部署,可以参考 jaeger-on-k8s。其中collector 以及 query 均以 deployment 的形式部署;agent 可以选择 daemonSet 或以 sidecar 注入的方式部署。若 agent 选择 daemonSet 的方式,意味着每个节点中的所有pod 都可以向 Jaeger 发送链路信息。但在特定场景中,我们并不想收集所有服务的链路信息,因此可以选用 sidecar 的形式。
sidecar 具体形式如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
spec:
selector:
matchLabels:
app.kubernetes.io/name: myapp
template:
metadata:
labels:
app.kubernetes.io/name: myapp
spec:
containers:
- image: mynamespace/hello-myimage
name: myapp
ports:
- containerPort: 8080
- image: jaegertracing/jaeger-agent
name: jaeger-agent
ports:
- containerPort: 5775
protocol: UDP
- containerPort: 6831
protocol: UDP
- containerPort: 6832
protocol: UDP
- containerPort: 5778
protocol: TCP
args: ["--collector.host-port=jaeger-collector.jaeger-infra.svc:14267"]
若使用 Jaeger Operator 部署的Jaeger, 仅需要在 Deployment 中加入注解
sidecar.jaegertracing.io/inject: true
,以sidecar 的形式注入,则需要给应用客户端配置JAEGER_AGENT_HOST
来告诉服务 agent 在哪。
Isito & Jaeger
在 istio 中,我们可以不部署 agent 组件。因为在 istio 中,若在 mixer 组件配置 zipkin-address-url
参数,则会默认为服务网格中的服务创建调用链路信息,并发送到配置的地址中。
这里的
zipkin-address-url
并非真正部署的 zipkin, 而是这个地址可以兼容 zipkin 所使用的数据格式。
因此,我们利用上述方法部署 jaeger collecor 和 query ui。首先创建 config.yml 用于配置 Jaeger,
apiVersion: v1
kind: ConfigMap
metadata:
name: jaeger-configuration
labels:
app: jaeger
app.kubernetes.io/name: jaeger
data:
span-storage-type: elasticsearch
collector: |
es:
server-urls: http://elasticsearch-logging.kube-system:9200
collector:
zipkin:
http-port: 9411
query: |
es:
server-urls: http://elasticsearch-logging.kube-system:9200
agent: |
collector:
host-port: "jaeger-collector:14267"
然后获取生产模式的 Jaeger 部署文件并进行部署。
$ wget https://raw.githubusercontent.com/jaegertracing/jaeger-kubernetes/master/jaeger-production-template.yml
部署好之后,环境如下所示。
# pod
NAME READY STATUS RESTARTS AGE
jaeger-collector-b9bf6d75b-gvg7r 1/1 Running 0 25h
jaeger-query-5fd6c9dcff-wvm82 1/1 Running 0 25h
# service
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
jaeger-collector ClusterIP 10.233.20.50 <none> 14267/TCP,14268/TCP,9411/TCP
jaeger-query LoadBalancer 10.233.4.232 10.7.13.201 80:40000/TCP
zipkin ClusterIP 10.233.4.179 <none> 9411/TCP
对于已经部署好的 istio,需要修改 istio-system namespace 下的 名为 istio 的 configmap,更替其中的 zipkin: address: xxx
为 Jaeger collector的 9411端口的服务。并重启应用所在的pod,以使该配置生效。
可以检查 应用pod中的 envoy 配置是否已修改。在 istio-proxy container中的 /etc/istio/proxy/recvx.json中可以找到。
若还未部署istio,则只需在helm 安装时,增加 --set gloable.zipkin.address=xxxx
参数。
注意 这里有一个坑! istio 的 policy 组件默认设置的链路追踪采样率为 1%,因此在配置好 Jaeger 以后可能访问好几次服务都无法获取链路信息(这个地方困了我一天,一直以为是哪个地方配错了。。。哎),可以在部署 istio的时候,添加参数
--set pilot.traceSampling=10
修改为 10% 或其他数字。
总结
其实 Jaeger 官方特别推荐使用 Operator 来部署 Jaeger,毕竟 Operator 是未来 K8s 使用的主流趋势,并且确实方便快捷。此外还有一种流式模式,即部署 Jaeger 对接 Kafka 的方式本文中并未列出,详情可参考 Jaeger 官方文档。本文只简单记录下平台层面上 Jaeger 的部署,并未涉及业务逻辑和业务场景,毕竟大规模的业务场景下,也需要更复杂的配置,包括 jaeger 采样策略,对接ES 或 Kafka 进行流式处理及分析等。