如何配置具有韧性的 OTel Collector 流水线。
OpenTelemetry Collector 提供多种组件和配置,用于尽量减少遥测数据处理、导出过程中的数据丢失。但要构建可靠的可观测性流水线,必须理解哪些情形仍可能丢失数据,以及如何缓解这些问题。
理解 Collector 的韧性
具有韧性的 Collector 即使遇到不利条件,也能维持遥测数据流转与处理能力,使整个可观测性流水线保持运转。
Collector 的韧性主要体现在两类情况的数据处理:配置的端点——也就是 trace、metric 或 log 的目的地——不可用,以及 Collector 实例自身出现崩溃等问题。
发送队列:内存缓冲
Collector 导出器内置的最基本韧性机制是发送队列。
- 工作方式:导出器通常包含一个发送队列,在将数据发送到下游端点之前先放入内存缓冲。如果端点可用,数据会很快通过队列。
- 端点不可用时:如果端点因网络问题或后端重启等原因不可用,导出器就无法立即发送数据。它会将数据加入内存发送队列,而不是立即丢弃。
- 重试机制:Collector 使用带随机抖动的指数退避,在等待一定间隔后反复尝试发送缓冲数据。默认最多重试 5 分钟。
- 可能丢失数据的情形:
- 队列已满:内存队列大小可配置,默认值通常为 1000 个批次或请求。如果端点持续不可用,而新数据不断到来,队列就可能填满。此后新到的数据会被丢弃,以避免 Collector 耗尽内存。
- 重试超时:如果端点不可用的时间超过配置的最长重试时间,默认 5 分钟,Collector 会停止重试队列中最旧的数据,并将其丢弃。
- 配置:可以在导出器设置中配置队列大小与重试行为:
exporters:
otlp:
endpoint: otlp.example.com:4317
sending_queue:
storage: file_storage
queue_size: 5_000 # Increase queue size (default 1000)
retry_on_failure:
initial_interval: 5s
max_interval: 30s
max_elapsed_time: 10m # Increase max retry time (default 300s)
持久化存储:预写日志(WAL)
为了防止 Collector 实例自身崩溃或重启时丢失数据,可以使用 file_storage 扩展为发送队列启用持久化存储。
- 工作方式:发送队列不再仅将数据缓冲在内存中,而是在尝试导出之前将其写入磁盘上的预写日志(Write-Ahead Log,WAL)。
- Collector 崩溃时:如果 Collector 在队列仍有数据时崩溃,数据已经持久化到磁盘。重启后,Collector 会从 WAL 读取数据,并继续尝试将其发送到端点。
- 可能丢失数据的情形:磁盘故障、磁盘空间耗尽,或 Collector 重启后端点不可用的时间仍超过重试限制,都可能导致数据丢失。此机制提供的保证也可能不及专用消息队列。
配置步骤:
- 定义
file_storage扩展。 - 在导出器的
sending_queue配置中引用该存储实例的 ID。
extensions:
file_storage: # Define the extension instance
directory: /var/lib/otelcol/storage # Choose a persistent directory
exporters:
otlp:
endpoint: otlp.example.com:4317
sending_queue:
storage: file_storage # Reference the storage extension instance
service:
extensions: [file_storage] # Enable the extension in the service pipeline
pipelines:
traces:
receivers: [otlp]
exporters: [otlp]
消息队列
若需要最高级别的韧性,尤其是在不同 Collector 层级之间——如 Agent 到 Gateway——或基础设施与供应商后端之间,可以引入 Kafka 等专用消息队列。
- 工作方式:一个 Collector 实例(Agent)通过 Kafka exporter 将数据导出到 Kafka topic;另一个 Collector 实例(Gateway)通过 Kafka receiver 消费该 topic 中的数据。
- 端点或 Collector 不可用时:
- 如果消费数据的 Collector(Gateway)停机,消息会积压在 Kafka topic 中,直到达到 Kafka 保留策略的限制。只要 Kafka 可用,生产数据的 Collector(Agent)就不受影响。
- 如果生产数据的 Collector(Agent)停机,不会有新数据进入队列,但消费者仍可处理已有消息。
- 如果 Kafka 自身停机,生产数据的 Collector 就需要自己的韧性机制,例如发送队列,必要时配合 WAL,以缓冲发往 Kafka 的数据。
- 可能丢失数据的情形:主要与 Kafka 自身有关,例如集群故障、topic 配置错误、数据过期;另一种情形是生产者无法将数据发送到 Kafka,且没有足够的本地缓冲。
Agent Collector 配置:生产者
exporters:
kafka:
brokers: ['kafka-broker1:9092', 'kafka-broker2:9092']
topic: otlp_traces
receivers:
otlp:
protocols:
grpc:
service:
pipelines:
traces:
receivers: [otlp]
exporters: [kafka]
Gateway Collector 配置:消费者
receivers:
kafka:
brokers: ['kafka-broker1:9092', 'kafka-broker2:9092']
topic: otlp_traces
initial_offset: earliest # Process backlog
exporters:
otlp:
endpoint: otlp.example.com:4317
# Consider queue/retry for exporting *from* Gateway to Backend
service:
pipelines:
traces:
receivers: [kafka]
exporters: [otlp]
会导致数据丢失的情形
以下情况下可能丢失数据:
- 网络不可用且重试超时:下游端点不可用的时间超过
retry_on_failure中配置的max_elapsed_time。 - 网络不可用且队列溢出:下游端点不可用,发送队列——内存或持久化队列——在端点恢复之前达到容量上限,新数据因此被丢弃。
- Collector 崩溃且未持久化:Collector 崩溃或被终止,而它只使用内存发送队列,内存数据会丢失。
- 持久化存储故障:
file_storage扩展使用的磁盘故障或空间耗尽。 - 消息队列故障:Kafka 等外部消息队列发生停机或数据丢失,而生产数据的 Collector 没有足够的本地缓冲。
- 配置错误:导出器或接收器配置错误,导致数据无法流转。
- 禁用韧性机制:在配置中明确禁用了发送队列或重试机制。
防止数据丢失的建议
遵循以下建议,尽量减少数据丢失并确保遥测数据采集可靠:
- 始终使用发送队列:为通过网络发送数据的导出器启用
sending_queue。 - 监控 Collector 指标:主动监控
otelcol_exporter_queue_size、otelcol_exporter_queue_capacity、otelcol_exporter_send_failed_spans,以及对应的 metric/log 指标,尽早发现潜在问题。 - 调整队列大小与重试:根据预期负载、内存和磁盘资源,以及端点可接受的停机时长调整
queue_size与retry_on_failure。 - 使用持久化存储(WAL):对于不能接受 Collector 重启期间数据丢失的 Agent 或 Gateway,为发送队列配置
file_storage扩展。 - 考虑消息队列:若运维开销可以接受,可使用 Kafka 等托管消息队列,获得跨网络链路的最大持久性,或解耦 Collector 各层级。
- 使用适当的部署模式:
- 采用 Agent + Gateway 架构。Agent 负责本地采集;Gateway 负责处理、批处理和具有韧性的导出。
- 将队列、WAL、Kafka 等韧性措施集中在网络跳点:Agent → Gateway,以及 Gateway → Backend。
- 应用程序 SDK 与本地 Agent(Sidecar/DaemonSet)之间通常有可靠的本地网络,因此这段链路的韧性往往没那么关键。如果 Agent 不可用,在此处增加队列有时会对应用程序产生负面影响。
理解这些机制并采用适当配置,可以显著提高 OpenTelemetry Collector 部署的韧性,尽量减少数据丢失。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END











暂无评论内容