弹性

如何配置弹性的 OTel Collector 管道

OpenTelemetry Collector 的设计考虑了各种组件和配置,以最大程度地减少遥测数据在处理和导出过程中的丢失。然而,理解可能发生数据丢失的场景以及如何减轻这些风险,对于建立一个弹性的可观察性管道至关重要。

理解 Collector 的弹性

弹性的 Collector 在面临不利条件时,能够维持遥测数据的流和处理能力,确保整体可观察性管道的正常运行。

Collector 的弹性主要体现在其如何处理数据,当配置的端点(追踪、指标或日志的目的地)变得不可用,或者 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 扩展来为发送队列启用持久化存储。

  • 工作原理:发送队列不仅在内存中缓冲数据,还会在尝试导出之前将其写入磁盘上的预写日志(WAL)。

  • 处理 Collector 崩溃:如果 Collector 在数据位于其队列中时崩溃,数据会被持久化到磁盘。当 Collector 重启时,它会从 WAL 中读取数据,并恢复尝试将其发送到端点。

  • 数据丢失场景:如果磁盘发生故障或空间不足,或者即使 Collector 重启后端点仍然不可用且超出重试限制,数据仍然可能丢失。其保证可能不如专用消息队列那么强。

  • 配置

    1. 定义 file_storage 扩展。
    2. 在导出器的 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 层级之间(如代理到网关)或在您的基础设施和供应商后端之间,您可以引入一个专用的消息队列,如 Kafka。

  • 工作原理:一个 Collector 实例(代理)使用 Kafka 导出器将数据导出到 Kafka 主题。另一个 Collector 实例(网关)使用 Kafka 接收器从该 Kafka 主题消费数据。
  • 处理端点/Collector 不可用
    • 如果消费 Collector(网关)宕机,消息会简单地累积在 Kafka 主题中(直到达到 Kafka 的保留限制)。只要 Kafka 正常运行,生产 Collector(代理)就不会受到影响。
    • 如果生产 Collector(代理)宕机,没有新数据进入队列,但消费者可以继续处理现有消息。
    • 如果 Kafka 本身宕机,生产 Collector 需要自己的弹性机制(如发送队列,可能带有 WAL)来缓冲发往 Kafka 的数据。
  • 数据丢失场景:数据丢失主要与 Kafka 本身(集群故障、主题配置错误、数据过期)或生产端在没有足够本地缓冲的情况下发送到 Kafka 的失败有关。
  • 配置
    • 代理 Collector 配置(生产者)

      exporters:
        kafka:
          brokers: ['kafka-broker1:9092', 'kafka-broker2:9092']
          topic: otlp_traces
      
      receivers:
        otlp:
          protocols:
            grpc:
      
      service:
        pipelines:
          traces:
            receivers: [otlp]
            exporters: [kafka]
      
    • 网关 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]
      

数据丢失的场景

在以下情况下可能发生数据丢失

  1. 网络不可用 + 超时:下游端点不可用的时间超过了 retry_on_failure 设置中配置的 max_elapsed_time
  2. 网络不可用 + 队列溢出:下游端点不可用,并且发送队列(内存或持久化)在端点恢复之前已满。新数据将被丢弃。
  3. Collector 崩溃(无持久化):Collector 实例崩溃或被终止,并且它仅使用了内存发送队列。内存中的数据将丢失。
  4. 持久化存储故障:file_storage 扩展使用的磁盘发生故障或空间不足。
  5. 消息队列故障:外部消息队列(如 Kafka)发生中断或数据丢失事件,并且生产 Collector 没有足够的本地缓冲。
  6. 配置错误:导出器或接收器配置不正确,导致数据流中断。
  7. 禁用了弹性:在配置中明确禁用了发送队列或重试机制。

防止数据丢失的建议

遵循以下建议,以最大程度地减少数据丢失并确保可靠的遥测数据收集

  1. 始终使用发送队列:为通过网络发送数据的导出器启用 sending_queue
  2. 监控 Collector 指标:积极监控 otelcol_exporter_queue_sizeotelcol_exporter_queue_capacityotelcol_exporter_send_failed_spans(以及指标/日志的等效指标),以便及早检测潜在问题。
  3. 调整队列大小和重试参数:根据预期的负载、内存/磁盘资源和可接受的端点停机时间,调整 queue_sizeretry_on_failure 参数。
  4. 使用持久化存储(WAL):对于在 Collector 重启期间不允许数据丢失的代理或网关,为发送队列配置 file_storage 扩展。
  5. 考虑使用消息队列:为了在网络段之间实现最大的持久性,或解耦 Collector 层级,如果运营开销可接受,请使用托管消息队列,如 Kafka。
  6. 使用适当的部署模式
    • 采用代理 + 网关的架构。代理处理本地收集,网关处理处理、批处理和弹性导出。
    • 将弹性工作(队列、WAL、Kafka)集中在网络跳跃处:代理 -> 网关 和 网关 -> 后端。
    • 应用程序(SDK)与本地代理(Sidecar/DaemonSet)之间的弹性通常不太关键,因为本地网络通常是可靠的;在此处添加队列有时会因代理不可用而对应用程序产生负面影响。

通过理解这些机制并应用适当的配置,您可以显著提高 OpenTelemetry Collector 部署的弹性并最大程度地减少数据丢失。


最后修改于 2025 年 6 月 24 日:将 prettier 从 3.5.3 升级到 3.6.0 (#7170) (0930994d)