Jaeger 持久化存储

all-in-one 包含 Jaeger UI(query)、收集器(collector)、查询(query)和代理(agent), 它将收集到的追踪数据存储在内存中,因此,重启容器后会丢失所有的数据。

为了便于后续的数据分析,需要将追踪数据进行持久化存储,Jaeger 支持 cassandra、elasticsearch、kafka(缓存)、grpc-plugin、badger(仅适用 all-in-one)、memory(仅适用 all-in-one)。对于大规模的生产部署,Jaeger 团队推荐 Elasticsearch 后端,而不是 Cassandra 。

根据 Jaeger 架构,没有缓存的情况下收集器(collector)直接将数据写入存储。

也可以将 kafka 作为初始缓存区,这个之后再加。

这里使用 elasticsearch(+kibana) 作为存储后端:

  1. 直接使用 all-in-one 容器部署
  2. 单独部署 Jaeger 的各个组件
    • agent:Jaeger 客户端要求 jaeger-agent 进程在每个主机上本地运行。
    • collector:收集器是无状态的,可以并行运行多个 jaeger-collector 实例。
    • query:jaeger-query 服务于 API 端点和 React/Javascript UI。该服务是无状态的,通常运行在负载均衡器之后,比如 NGINX。
    • ingester:jaeger-ingester 能够从 Kafka 读取数据,然后将其写入存储后端(Elasticsearch/Cassandra)。

使用 docker 容器运行,并挂载卷(将数据存储到本机而不是容器内);从 elasticsearch 获取数据,使用 kibana 查看数据情况。

all-in-one

按顺序创建容器,使用 --link 进行链接,非常容易构建。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# elasticsearch
docker run -d --name=elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e "xpack.security.enabled=false" docker.elastic.co/elasticsearch/elasticsearch:7.12.1

# kibana
docker run -d --name=kibana --link=elasticsearch -p 5601:5601
docker.elastic.co/kibana/kibana:7.12.1

# all-in-one
docker run -d --name jaeger \
--link=elasticsearch \
-e SPAN_STORAGE_TYPE=elasticsearch \
-e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \
-e ES_SERVER_URLS=http://elasticsearch:9200 \
-e ES_TAGS_AS_FIELDS_ALL=true \
-p 5775:5775/udp \
-p 6831:6831/udp \
-p 6832:6832/udp \
-p 5778:5778 \
-p 16686:16686 \
-p 14268:14268 \
-p 14250:14250 \
-p 9411:9411 \
jaegertracing/all-in-one

挂载

查看容器内目录

1
docker exec -it elasticsearch bash

1. 挂载本地目录

本地的空目录会覆盖容器内有数据的目录,导致容器无法正常启动。

1
2
3
4
5
6
7
8
9
10
11
# 创建目录
sudo mkdir -p /usr/share/elasticsearch/config /usr/share/elasticsearch/data /usr/share/elasticsearch/logs

# 挂载
docker run -d --name=test \
-e "discovery.type=single-node" \
-e "xpack.security.enabled=false" \
--mount type=bind,source=/usr/share/elasticsearch/config,target=/usr/share/elasticsearch/config \
--mount type=bind,source=/usr/share/elasticsearch/data,target=/usr/share/elasticsearch/data \
--mount type=bind,source=/usr/share/elasticsearch/logs,target=/usr/share/elasticsearch/logs \
docker.elastic.co/elasticsearch/elasticsearch:7.12.1
  1. 挂载卷

卷空时不会覆盖掉容器内原有的数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 创建卷
docker volume create my-vol

# 查看卷
docker inspect my-vol

# 删除卷
docker volume rm my-vol

# 挂载卷
docker volume create es-config
docker volume create es-data
docker volume create es-logs

docker run -d --name=test \
-p 9201:9200 -p 9301:9300 \
-e "discovery.type=single-node" \
-e "xpack.security.enabled=false" \
--mount source=es-config,target=/usr/share/elasticsearch/config \
--mount source=es-data,target=/usr/share/elasticsearch/data \
--mount source=es-logs,target=/usr/share/elasticsearch/logs \
docker.elastic.co/elasticsearch/elasticsearch:7.12.1

# 测试
curl -X GET "localhost:9201/_cat/nodes?v=true&pretty"

挂载后,容器内的数据直接写到本地的卷中。

单独部署组件

问题

使用启动容器名称 elasticsearch 或 localhost 作为访问地址,无法启动 jaeger-collector

  • 提示无法访问 Elasticsearch ,但是本地使用 curl 语句正常访问
1
2
3
4
5
6
7
2021/05/09 10:58:46 maxprocs: Leaving GOMAXPROCS=4: CPU quota undefined
{"level":"info","ts":1620557926.8695443,"caller":"flags/service.go:117","msg":"Mounting metrics handler on admin server","route":"/metrics"}
{"level":"info","ts":1620557926.8699071,"caller":"flags/service.go:123","msg":"Mounting expvar handler on admin server","route":"/debug/vars"}
{"level":"info","ts":1620557926.8716085,"caller":"flags/admin.go:105","msg":"Mounting health check on admin server","route":"/"}
{"level":"info","ts":1620557926.8717675,"caller":"flags/admin.go:111","msg":"Starting admin HTTP server","http-addr":":14269"}
{"level":"info","ts":1620557926.8733315,"caller":"flags/admin.go:97","msg":"Admin server started","http.host-port":"[::]:14269","health-status":"unavailable"}
{"level":"fatal","ts":1620557932.8956766,"caller":"command-line-arguments/main.go:75","msg":"Failed to init storage factory","error":"failed to create primary Elasticsearch client: Head \"http://elasticsearch2:9200\": context deadline exceeded","stacktrace":"main.main.func1\n\tcommand-line-arguments/main.go:75\ngithub.com/spf13/cobra.(*Command).execute\n\tgithub.com/spf13/cobra@v0.0.7/command.go:838\ngithub.com/spf13/cobra.(*Command).ExecuteC\n\tgithub.com/spf13/cobra@v0.0.7/command.go:943\ngithub.com/spf13/cobra.(*Command).Execute\n\tgithub.com/spf13/cobra@v0.0.7/command.go:883\nmain.main\n\tcommand-line-arguments/main.go:137\nruntime.main\n\truntime/proc.go:225"}

解决方法

使用 publish_address 作为访问地址

1
2
# 查看 publish_address
curl -XGET '0.0.0.0:9200/_nodes/http?pretty' | grep publish_address

部署

根据 Jaeger 提供的标志,转换为 大写+下划线 的形式,使用环境变量进行设置。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# elasticsearch
docker run -d --name=elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e "xpack.security.enabled=false" -e ES_JAVA_OPTS="-Xms512m -Xmx512m" docker.elastic.co/elasticsearch/elasticsearch:7.12.1

# jaeger-collector 注意地址
docker run -d --name=jaeger-collector --link elasticsearch2 -p 9411:9411 -p 14250:14250 -p 14268:14268 -p 14269:14269 -e SPAN_STORAGE_TYPE=elasticsearch -e ES_SERVER_URLS=http://172.17.0.2:9200 jaegertracing/jaeger-collector

# jaeger-agent
docker run -d --name=jaeger-agent -p 6831:6831/udp -p 6832:6832/udp -p 5778:5778/tcp -p 5775:5775/udp -e REPORTER_GRPC_HOST_PORT=172.17.0.3:14250 -e LOG_LEVEL=debug jaegertracing/jaeger-agent

# jaeger-query 注意地址
docker run -d --name=jaeger-query --link elasticsearch2 -p 16686:16686 -p 16687:16687 -e SPAN_STORAGE_TYPE=elasticsearch -e ES_SERVER_URLS=http://172.17.0.2:9200 jaegertracing/jaeger-query

# 列出容器
docker container ls

openstack user list

# 调试日志
docker inspect jaeger-agent | grep LogPath

# 停止并删除容器
docker container stop jaeger-collector jaeger-agent jaeger-query
docker container rm jaeger-collector jaeger-agent jaeger-query

查询数据

Jaeger UI

直接使用 Jaeger UI 查询,可以自定义日期范围。

curl

用 curl 查询 elasticsearch ,可以使用不同的参数过滤查询数据。

1
2
3
4
5
6
7
8
9
10
11
# 返回索引信息
curl -X GET "localhost:9200/_cat/indices?v"

# 查询索引包含 jaeger 的信息
curl -X GET "localhost:9200/jaeger*/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"match_all": {}
}
}
'

elasticdump

使用 elasticdump 导出数据,并保存为 json 格式的文件。

1
2
3
4
5
6
7
8
9
10
# 安装 elasticdump
curl -fsSL https://deb.nodesource.com/setup_14.x | sudo -E bash -
sudo apt-get install -y nodejs
sudo npm install elasticdump -g
elasticdump

# 以 json 格式导出数据
elasticdump --input="http://localhost:9200/jaeger-service-05-08" --output=service.json

elasticdump --input="http://localhost:9200/jaeger-span-05-08" --output=span.json

kibana

用 kibana 可视化查询数据。

将数据进行可视化后,可以整理在一个面板中。

参阅