OpenTelemetry
opentelemetry 插件对 APISIX 进行插桩,并根据 OpenTelemetry 规范,以二进制编码的 OTLP over HTTP 将追踪信息发送到 OpenTelemetry 收集器。
示例
下面的示例展示了如何在不同场景下使用 opentelemetry 插件。
启用 opentelemetry 插件
在 API7 网关中,opentelemetry 默认可通过 Dashboard 和 Admin API 使用。对于 APISIX 部署,在配置使用该插件的路由前,请先在网关静态配置中加载该插件。
- Host or Docker
- Kubernetes (Helm)
对于 APISIX 宿主机或 Docker 部署,请保留 config.yaml 中现有插件列表,并加入 opentelemetry:
plugins:
# 保留当前网关使用的完整插件列表。
- opentelemetry
重新加载网关以使更改生效。
对于 APISIX Helm Chart,apisix.plugins 会替换已加载插件列表。请从当前网关使用的完整插件列表开始,并加入 opentelemetry:
apisix:
plugins:
# 保留当前网关使用的完整插件列表。
- opentelemetry
API7 网关 Helm 部署在本节不需要修改 Helm values,可继续配置插件元数据和路由。
使用 APISIX Helm Chart 应用 values 文件:
helm upgrade <release-name> <chart-name> -n <namespace> -f values.yaml
发送追踪到 OpenTelemetry
以下示例展示了如何追踪对路由的请求并将追踪信息发送到 OpenTelemetry。
在 Docker 中启动一个 OpenTelemetry 收集器实例:
- Docker
- Kubernetes
docker run -d --name otel-collector -p 4318:4318 otel/opentelemetry-collector-contrib
apiVersion: v1
kind: ConfigMap
metadata:
namespace: aic
name: otel-collector-config
data:
config.yaml: |
receivers:
otlp:
protocols:
http:
endpoint: 0.0.0.0:4318
exporters:
debug:
verbosity: detailed
service:
pipelines:
traces:
receivers: [otlp]
exporters: [debug]
---
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: aic
name: otel-collector
spec:
replicas: 1
selector:
matchLabels:
app: otel-collector
template:
metadata:
labels:
app: otel-collector
spec:
containers:
- name: otel-collector
image: otel/opentelemetry-collector-contrib
args:
- "--config=/conf/config.yaml"
ports:
- containerPort: 4318
volumeMounts:
- name: config
mountPath: /conf
volumes:
- name: config
configMap:
name: otel-collector-config
---
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: otel-collector
spec:
selector:
app: otel-collector
ports:
- name: otlp-http
port: 4318
targetPort: 4318
type: ClusterIP
应用清单:
kubectl apply -f otel-collector.yaml
收集器应开始监听 127.0.0.1:4318(Docker)或 otel-collector.aic.svc.cluster.local:4318(Kubernetes)。配置插件元数据以设置收集器地址:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/plugin_metadata/opentelemetry" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"collector": {
"address": "127.0.0.1:4318"
}
}'
plugin_metadata:
- name: opentelemetry
collector:
address: "127.0.0.1:4318"
将配置同步到网关:
adc sync -f adc.yaml
更新现有 GatewayProxy 资源中的 pluginMetadata 字段:
apiVersion: apisix.apache.org/v1alpha1
kind: GatewayProxy
metadata:
namespace: aic
name: apisix-config
spec:
provider:
type: ControlPlane
controlPlane:
# 控制面连接配置
# ....
pluginMetadata:
opentelemetry:
collector:
address: "otel-collector.aic.svc.cluster.local:4318"
将配置应用到集群:
kubectl apply -f gateway-proxy.yaml
创建一个带有 opentelemetry 插件的路由:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"id": "otel-tracing-route",
"uri": "/anything",
"plugins": {
"opentelemetry": {
"sampler": {
"name": "always_on"
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org": 1
}
}
}'
services:
- name: httpbin
routes:
- uris:
- /anything
name: otel-tracing-route
plugins:
opentelemetry:
sampler:
name: always_on
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
将配置同步到网关:
adc sync -f adc.yaml
- Gateway API
- APISIX CRD
apiVersion: v1
kind: Service
metadata:
namespace: aic
name: httpbin-external-domain
spec:
type: ExternalName
externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
namespace: aic
name: otel-plugin-config
spec:
plugins:
- name: opentelemetry
config:
sampler:
name: always_on
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
namespace: aic
name: otel-route
spec:
parentRefs:
- name: apisix
rules:
- matches:
- path:
type: PathPrefix
value: /anything
filters:
- type: ExtensionRef
extensionRef:
group: apisix.apache.org
kind: PluginConfig
name: otel-plugin-config
backendRefs:
- name: httpbin-external-domain
port: 80
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: aic
name: httpbin-external-domain
spec:
ingressClassName: apisix
externalNodes:
- type: Domain
name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: aic
name: otel-route
spec:
ingressClassName: apisix
http:
- name: otel-route
match:
paths:
- /anything
upstreams:
- name: httpbin-external-domain
plugins:
- name: opentelemetry
enable: true
config:
sampler:
name: always_on
将配置应用到集群:
kubectl apply -f otel-ic.yaml
发送请求到该路由:
curl "http://127.0.0.1:9080/anything"
你应该收到 HTTP/1.1 200 OK 响应。
在 OpenTelemetry 收集器的日志中,你应该看到类似于以下的信息:
2024-02-18T17:14:03.825Z info ResourceSpans #0
Resource SchemaURL:
Resource attributes:
-> telemetry.sdk.language: Str(lua)
-> telemetry.sdk.name: Str(opentelemetry-lua)
-> telemetry.sdk.version: Str(0.1.1)
-> hostname: Str(e34673e24631)
-> service.name: Str(APISIX)
ScopeSpans #0
ScopeSpans SchemaURL:
InstrumentationScope opentelemetry-lua
Span #0
Trace ID : fbd0a38d4ea4a128ff1a688197bc58b0
Parent ID :
ID : af3dc7642104748a
Name : GET /anything
Kind : Server
Start time : 2024-02-18 17:14:03.763244032 +0000 UTC
End time : 2024-02-18 17:14:03.920229888 +0000 UTC
Status code : Unset
Status message :
Attributes:
-> net.host.name: Str(127.0.0.1)
-> http.method: Str(GET)
-> http.scheme: Str(http)
-> http.target: Str(/anything)
-> http.user_agent: Str(curl/7.64.1)
-> apisix.route_id: Str(otel-tracing-route)
-> apisix.route_name: Empty()
-> apisix.response_source: Str(upstream)
-> http.route: Str(/anything)
-> http.status_code: Int(200)
{"kind": "exporter", "data_type": "traces", "name": "debug"}
要可视化这些追踪,你可以将遥测数据导出到后端服务,例如 Zipkin 和 Prometheus。有关更多详细信息,请参阅 exporters。
自 API7 企业版 3.9.10 和 APISIX 3.17.0 起,每个请求跨度都包含 apisix.response_source 属性,用于分类 HTTP 响应的来源:
apisix— 响应由 APISIX 自身生成,例如插件拒绝、认证失败或路由未找到错误。nginx— 响应由 NGINX 代理层生成,例如连接被拒绝或上游超时错误。upstream— 响应来自实际的上游服务。
此属性可在追踪分析中实现更精确的错误归因,例如区分网关侧拒绝和真实的上游错误。
在日志记录中使用追踪变量
以下示例展示了如何配置 opentelemetry 插件以设置以下内置变量,这些变量可用于日志插件或访问日志:
opentelemetry_context_traceparent:父级链路 ID
opentelemetry_trace_id:当前跨度的链路 IDopentelemetry_span_id:当前跨度的跨度 ID
配置插件元数据以将 set_ngx_var 设置为 true:
- Admin API
- ADC
- Ingress Controller
curl "http://127.0.0.1:9180/apisix/admin/plugin_metadata/opentelemetry" -X PUT \
-H "X-API-KEY: ${ADMIN_API_KEY}" \
-d '{
"set_ngx_var": true
}'
plugin_metadata:
- name: opentelemetry
set_ngx_var: true
将配置同步到网关:
adc sync -f adc.yaml
更新现有 GatewayProxy 资源中的 pluginMetadata 字段,并保留收集器配置:
apiVersion: apisix.apache.org/v1alpha1
kind: GatewayProxy
metadata:
namespace: aic
name: apisix-config
spec:
provider:
type: ControlPlane
controlPlane:
# 控制面连接配置
# ....
pluginMetadata:
opentelemetry:
collector:
address: "otel-collector.aic.svc.cluster.local:4318"
set_ngx_var: true
将配置应用到集群:
kubectl apply -f gateway-proxy.yaml
OpenTelemetry Collector 可访问后,请根据网关部署方式配置网关。
- Host or Docker
- Kubernetes (Helm)
在网关配置文件中新增或更新以下配置,以使用 opentelemetry 插件变量:
nginx_config:
http:
enable_access_log: true
access_log_format: '{"time": "$time_iso8601","opentelemetry_context_traceparent": "$opentelemetry_context_traceparent","opentelemetry_trace_id": "$opentelemetry_trace_id","opentelemetry_span_id": "$opentelemetry_span_id","remote_addr": "$remote_addr"}'
access_log_format_escape: json
❶ access_log_format:自定义访问日志格式以使用 opentelemetry 插件变量。
重新加载网关以使配置更改生效。
对于 Helm 部署,请更新用于渲染网关访问日志格式的 values,并保留 values 文件中的其他配置。
对于 APISIX Helm Chart,设置以下 values:
apisix:
nginx:
logs:
enableAccessLog: true
accessLogFormat: '{"time": "$time_iso8601","opentelemetry_context_traceparent": "$opentelemetry_context_traceparent","opentelemetry_trace_id": "$opentelemetry_trace_id","opentelemetry_span_id": "$opentelemetry_span_id","remote_addr": "$remote_addr"}'
accessLogFormatEscape: json
对于 API7 网关 Helm Chart,设置以下 values:
logs:
enableAccessLog: true
accessLogFormat: '{"time": "$time_iso8601","opentelemetry_context_traceparent": "$opentelemetry_context_traceparent","opentelemetry_trace_id": "$opentelemetry_trace_id","opentelemetry_span_id": "$opentelemetry_span_id","remote_addr": "$remote_addr"}'
accessLogFormatEscape: json
然后使用当前网关 release 对应的 Chart 应用 values 文件:
helm upgrade <release-name> <chart-name> -n <namespace> -f values.yaml
生成请求时,你应该看到类似于以下的访问日志条目:
{"time": "18/Feb/2024:15:09:00 +0000","opentelemetry_context_traceparent": "00-fbd0a38d4ea4a128ff1a688197bc58b0-8f4b9d9970a02629-01","opentelemetry_trace_id": "fbd0a38d4ea4a128ff1a688197bc58b0","opentelemetry_span_id": "af3dc7642104748a","remote_addr": "172.10.0.1"}