Apache APISIX 集成 OpenTelemetry 以收集跟踪数据
博客文章在发布后不会更新。这篇文章已经发布一年多了,其内容可能已过时,部分链接可能无效。在依赖任何信息之前,请务必核实。
本文介绍了 Apache APISIX 的 opentelemetry 插件概念以及如何启用和部署该插件。
背景信息
OpenTelemetry 是一个开源遥测数据采集和处理系统。它不仅提供了各种用于应用程序端遥测数据收集和报告的 SDK,还提供了用于数据接收、处理和导出的数据收集端。您可以将数据导出到任何一个或多个 OpenTelemetry 后端,例如 Jaeger、Zipkin 和 OpenCensus。您可以在注册表中查看已适配 OpenTelemetry Collector 的插件列表。

插件介绍
Apache APISIX 的 opentelemetry 插件实现了跟踪数据收集,并通过 HTTP 协议将其发送到 OpenTelemetry Collector。Apache APISIX 从 v2.13.0 版本开始支持此功能。
OpenTelemetry 的一个特殊之处在于,OpenTelemetry 的 agent/SDK 不与后端实现锁定,这使用户在选择自己的后端服务时具有灵活性。换句话说,用户可以选择他们想要的后端服务,例如 Zipkin 和 Jaeger,而不会影响应用程序端。
opentelemetry 插件位于 agent 端。它集成了 OpenTelemetry agent/SDK,并在 Apache APISIX 中采用了其功能。它可以收集被跟踪的请求,生成 trace,并将其转发到 OpenTelemetry Collector。它支持 trace 协议,并将在下一个版本中支持 OpenTelemetry 的 logs 和 metrics 协议。
启用插件
您需要在 conf/config.yaml 配置文件中启用 opentelemetry 插件并修改 collector 配置。
我们假设您已经在 APISIX 节点上部署了 OpenTelemetry Collector,并启用了 OTLP HTTP Receiver。
需要帮助完成 OpenTelemetry Collector 的部署吗?请参阅下面的 示例场景。
OTLP HTTP Receiver 的默认端口是 4318,collector 的地址是 OpenTelemetry Collector 的 HTTP Receiver 地址。相关字段请参阅 Apache APISIX 文档。
典型的配置可能如下所示
plugins:
... # Other plugins that have been enabled
- opentelemetry
plugin_attr:
...
opentelemetry:
trace_id_source: x-request-id
resource:
service.name: APISIX
collector:
address: 127.0.0.1:4318 # OTLP HTTP Receiver address
request_timeout: 3
方法一:为特定路由启用插件
为了更方便地展示测试效果,示例中暂时将 sampler 设置为全采样,以确保每次请求被跟踪后都能生成 trace 数据,从而您可以在 Web UI 上查看 trace 相关数据。您也可以根据实际情况设置相关参数。
curl http://127.0.0.1:9080/apisix/admin/routes/1 \
-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' \
-X PUT -d '
{
"uri": "/get",
"plugins": {
"opentelemetry": {
"sampler": {
"name": "always_on"
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
方法二:全局启用插件
您也可以通过 Apache APISIX 插件功能启用 opentelemetry 插件。完成全局配置后,仍然需要创建路由,否则将无法进行测试。
curl 'http://127.0.0.1:9080/apisix/admin/global_rules/1' \
-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' \
-X PUT -d '{
"plugins": {
"opentelemetry": {
"sampler": {
"name": "always_on"
}
}
}
}'
方法三:通过 additional_attributes 自定义 Span 标签
有关 sampler 和 additional_attributes 的配置,请参阅 Apache APISIX 文档,其中 additional_attributes 是一系列 Key:Value 对,您可以使用它来自定义 Span 的标签,并可以随着 Span 显示在 Web UI 上。通过 additional_attributes 为路由的 span 添加 route_id 和 http_x-custom-ot-key,请参阅以下配置
curl http://127.0.0.1:9080/apisix/admin/routes/1001 \
-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' \
-X PUT -d '
{
"uri": "/put",
"plugins": {
"opentelemetry": {
"sampler": {
"name": "always_on"
},
"additional_attributes":[
"route_id",
"http_x-custom-ot-key"
]
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}'
测试和验证插件
您可以通过以上三种方法中的任意一种来启用 opentelemetry 插件。以下示例使用方法三的示例创建一个路由。创建成功后,请参阅以下命令来访问该路由
curl -X PUT -H `x-custom-ot-key: test-ot-val` http://127.0.0.1:9080/put
访问成功后,您可以在 Jaeger UI 中看到类似于 /put 的 span 详情,并且可以看到路由中的自定义标签显示在 Tags 列表中:http_x-custom-ot-key 和 route_id。

您需要注意的是,additional_attributes 配置设置为从 Apache APISIX 和 NGINX 变量中获取值作为 attribute 值,因此 additional_attributes 必须是有效的 Apache APISIX 或 NGINX 变量。它还包括 HTTP Header,但在获取 http*header 时,需要添加 http* 作为变量名的前缀。如果变量不存在,则该 tag 不会显示。
示例
此场景示例通过修改 OpenTelemetry Collector 示例,部署 Collector、Jaeger 和 Zipkin 作为后端服务,并启动两个示例应用程序(Client 和 Server)。其中 Server 提供 HTTP 服务,Client 将周期性地调用 Server 提供的 HTTP 接口,从而产生由两个 span 组成的调用链。
步骤一:部署 OpenTelemetry
以下以 docker compose 为例。其他部署方式请参阅 快速入门。
您可以看到以下命令进行部署1
git clone https://github.com/open-telemetry/opentelemetry-collector-contrib.git
cd opentelemetry-collector-contrib/examples/demo
docker compose up -d
在浏览器中访问 http://127.0.0.1:16886 (Jaeger UI) 或 http://127.0.0.1:9411/zipkin (Zipkin UI)。如果能够正常访问,则表示部署成功。
以下截图展示了成功访问的示例。


步骤二:配置测试环境
引入 Apache APISIX 服务,最终应用程序拓扑如下图所示。

Trace 数据上报流程如下。其中,由于 Apache APISIX 是独立部署,不在 docker-compose 的网络中,因此 Apache APISIX 通过本地映射端口(127.0.0.1:4138)访问 OpenTelemetry Collector 的 OTLP HTTP Receiver。

您需要确保已启用 opentelemetry 插件并重载 Apache APISIX。
您可以看到以下示例,创建了一个路由并为采样启用了 opentelemetry 插件
curl http://127.0.0.1:9080/apisix/admin/routes/1 \
-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' \
-X PUT -d '
{
"uri": "/hello",
"plugins": {
"opentelemetry": {
"sampler": {
"name": "always_on"
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:7080": 1
}
}
}'
修改 ./examples/demo/otel-collector-config.yaml 文件,添加 OTLP HTTP Receiver。
receivers:
otlp:
protocols:
grpc:
http: ${ip:port} # add OTLP HTTP Receiver,default port is 4318
修改 docker-compose.yaml 文件。
您需要修改配置文件,将 Client 调用 Server 的接口地址改为 Apache APISIX 的地址,并将 OTLP HTTP Receiver 和 Server 服务的端口映射到本地。
以下示例为修改配置后的完整 docker-compose.yaml
version: '2'
services:
# Jaeger
jaeger-all-in-one:
image: jaegertracing/all-in-one:latest
ports:
- '16686:16686' # jaeger ui port
- '14268'
- '14250'
# Zipkin
zipkin-all-in-one:
image: openzipkin/zipkin:latest
ports:
- '9411:9411'
# Collector
otel-collector:
image: ${OTELCOL_IMG}
command: ['--config=/etc/otel-collector-config.yaml', '${OTELCOL_ARGS}']
volumes:
- ./otel-collector-config.yaml:/etc/otel-collector-config.yaml
ports:
- '1888:1888' # pprof extension
- '8888:8888' # Prometheus metrics exposed by the collector
- '8889:8889' # Prometheus exporter metrics
- '13133:13133' # health_check extension
- '4317' # OTLP gRPC receiver
- '4318:4318' # Add OTLP HTTP Receiver port mapping
- '55670:55679' # zpages extension
depends_on:
- jaeger-all-in-one
- zipkin-all-in-one
demo-client:
build:
dockerfile: Dockerfile
context: ./client
environment:
- OTEL_EXPORTER_OTLP_ENDPOINT=otel-collector:4317
- DEMO_SERVER_ENDPOINT=http://172.17.0.1:9080/hello # APISIX address
depends_on:
- demo-server
demo-server:
build:
dockerfile: Dockerfile
context: ./server
environment:
- OTEL_EXPORTER_OTLP_ENDPOINT=otel-collector:4317
ports:
- '7080:7080' # Map the Server port to the host
depends_on:
- otel-collector
prometheus:
container_name: prometheus
image: prom/prometheus:latest
volumes:
- ./prometheus.yaml:/etc/prometheus/prometheus.yml
ports:
- '9090:9090'
需要注意的是,demo-client.environment.DEMO_SERVER_ENDPOINT 需要更改为您的 Apache APISIX 地址,并确保在容器中能够正常访问。
当然,您也可以通过 docker-compose.yaml 部署 Apache APISIX。详情请参阅 通过 Docker 安装。
步骤三:验证输出
重新部署完成后,您可以访问 Jaeger UI 或 Zipkin UI,看到 APISIX 的 Span 已包含在 Trace 中,如下所示


当 demo-server 未被 instrumented 时,通过启用此插件,您仍然可以获得 demo-server 行为的可视化。虽然这不是典型情况,但它是一种对 demo-server 进行真实 instrumentation 的简易替代方案,并提供了很多价值。

当请求未到达 demo-server 时,输出将不包括 demo-server 的 span。

禁用插件
如果您暂时不需要某个路由的跟踪数据收集,只需修改路由配置,删除配置中 plugins 下的 opentelemetry 部分即可。
如果您通过绑定全局规则全局启用了 opentelemetry,则可以移除 opentelemetry 全局插件的配置。
请注意,禁用 opentelemetry 插件只会导致 APISIX span 的断开,客户端和服务器 span 将保持连接。
摘要
Apache APISIX 集成 OpenTelemetry 后,可以轻松连接市面上众多的 Trace 系统。Apache APISIX 也在积极与社区合作,构建更强大的生态系统。
Apache APISIX 目前还在开发更多插件以支持与更多服务的集成,如果您有兴趣,请随时在 GitHub 上 发起讨论,或通过 邮件列表进行沟通。
本文的一个版本 最初发布于 Apache APISIX 博客。
docker-compose已弃用。有关详细信息,请参阅迁移到 Compose V2。 ↩︎