菜单
文档breadcrumb arrow Grafana Alloybreadcrumb arrow 参考breadcrumb arrow 组件breadcrumb arrow otelcolbreadcrumb arrow otelcol.exporter.loadbalancing
开源

otelcol.exporter.loadbalancing

otelcol.exporter.loadbalancing 接收来自其他 otelcol 组件的日志和跟踪,并使用 OpenTelemetry 协议 (OTLP) 在网络上写入。

注意

otelcol.exporter.loadbalancing 是上游 OpenTelemetry Collector loadbalancing 导出器的包装。如果需要,将转交上游存储库的错误报告或功能请求。

可以通过指定不同的标签来指定多个 otelcol.exporter.loadbalancing 组件。

选择哪个后端取决于跟踪 ID 或服务名称。后端负载不会影响选择。虽然这个负载均衡器不会对批次的轮询进行轮询,但后端之间的负载分布应该非常相似,在当前配置下标准差小于 5%。

otelcol exporter.loadbalancing 特别适用于配置有基于尾部采样器的后端,这些采样器根据完整跟踪的视图选择后端。

当更新后端列表时,一些信号将重新路由到不同的后端。大约R/N的“路由”将被重新路由,其中

  • “路由”要么是跟踪 ID,要么是映射到某个后端的服务名称。
  • “R”是路由总数。
  • “N”是后端总数。

这应该足够稳定,适用于大多数情况,后端数量越多,造成的干扰越小。

使用

alloy
otelcol.exporter.loadbalancing "LABEL" {
  resolver {
    ...
  }
  protocol {
    otlp {
      client {}
    }
  }
}

参数

otelcol exporter.loadbalancing 支持以下参数

名称类型描述默认值必需
routing_key字符串负载均衡的路由策略。"traceID"

routing_key 属性确定如何跨端点路由信号。其值可以是以下之一

  • "service":具有相同 service.name 的跨度将被导出到相同后端。这在使用诸如跨度度量之类的处理器时很有用,因此每个服务的所有跨度都发送到一致的 Alloy 实例进行指标收集。否则,相同服务的指标将发送到不同的实例,导致聚合不准确。
  • "traceID":属于同一 traceID 的跨度将被导出到相同后端。

以下块支持在 otelcol exporter.loadbalancing 定义内

层次结构描述必需
resolverresolver配置发现要导出的端点。
解析器 > 静态静态要导出到的端点的静态列表。
解析器 > dnsdns要导出到的端点的DNS来源列表。
解析器 > kuberneteskubernetes要导出到的端点的Kubernetes来源列表。
解析器 > aws_cloud_mapaws_cloud_map要导出到的端点的AWS CloudMap来源列表。
协议协议协议设置。目前仅支持OTLP。
协议 > otlpotlp配置OTLP导出器。
协议 > otlp > 客户端客户端配置导出器的gRPC客户端。
协议 > otlp > 客户端 > tlstls配置gRPC客户端的TLS。
协议 > otlp > 客户端 > keepalivekeepalive配置gRPC客户端的keepalive设置。
协议 > otlp > 队列队列配置发送前的数据批处理。
协议 > otlp > 重试重试配置失败请求的重试机制。
调试度量调试度量配置产生的度量以监测该组件的状态。

> 符号表示更深的嵌套级别。例如,解析器 > 静态 表示在 解析器 块内部定义的 静态 块。

解析器块

解析器 块配置了如何检索该导出器将要发送数据的端点。

解析器 块内部,必须指定 dns 块或 静态 块。如果同时指定了 dns静态,则 dns 优先。

静态块

静态 块配置了该导出器将要向其发送数据的端点列表。

支持以下参数:

名称类型描述默认值必需
主机名列表(string)要导出到的端点列表。

dns块

dns 块通过DNS的 hostname 属性周期性解析IP地址。然后,将使用通过 port 属性指定的IP地址和端口作为gRPC导出器导出数据的端点。

支持以下参数:

名称类型描述默认值必需
主机名字符串要解析的DNS主机名。
间隔持续时间解析器间隔。"5s"
超时持续时间解析器超时。"1s"
端口字符串与从DNS主机名解析的IP地址一起使用的端口。"4317"

kubernetes块

您可以通过使用 kubernetes 块在AWS基础设施中运行ECS时通过EKS来跨越Kubernetes服务的Pod进行负载均衡。Kubernetes API会在服务中添加或删除新Pod时通知Alloy。与 dns 解析器相比,kubernetes 解析器有更快的响应时间,因为它不需要轮询。

支持以下参数:

名称类型描述默认值必需
服务字符串要解析的Kubernetes服务。
端口列表(number)与从 service 解析的IP地址一起使用的端口。[4317]
超时持续时间解析器超时。"1s"

如果在 service 内部未指定命名空间,将尝试推断该Alloy的命名空间。如果失败,将使用 default 命名空间。

ports 中列出的每个端口将与其他从 service 解析出的IP地址一起使用。

必须将 roles 的“get”、“list”和“watch”权限授予Kubernetes以使解析器正常工作。

aws_cloud_map块

aws_cloud_map 块允许用户在使用AWS基础设施中的EKS运行ECS时使用 otelcol.exporter.loadbalancing

支持以下参数:

名称类型描述默认值必需
命名空间字符串服务注册的CloudMap命名空间。
服务名字符串注册实例时指定的服务名称。
间隔持续时间解析器间隔。"30s"
超时持续时间解析器超时。"5s"
健康状态字符串与从 service 解析的IP地址一起使用的端口。"HEALTHY"(健康)
端口数量用于将跟踪导出到由service解析的地址的端口号。

health_status可以设置为以下之一:

  • HEALTHY(健康):仅返回健康的实例。
  • UNHEALTHY(不健康):仅返回不健康的实例。
  • ALL(所有):返回所有实例,无论其健康状态如何。
  • HEALTHY_OR_ELSE_ALL(健康否则全部):返回健康实例,除非没有实例报告健康状态。在这种情况下,返回所有实例。这也被称为“开启故障”。

如果未设置port,则使用CloudMap中定义的默认端口。

注意

aws_cloud_map解析器返回最多100个主机。一个功能请求旨在处理此场景的分页。

协议块

protocol块配置导出时使用的协议相关设置。目前仅支持OTLP协议。

otlp块

otlp块配置导出时使用的OTLP相关设置。

客户端块

client块配置组件使用的gRPC客户端。客户端块使用的端点是resolver块中的端点。

支持以下参数:

名称类型描述默认值必需
压缩字符串用于请求的压缩机制。"gzip"(gzip)
read_buffer_size字符串gRPC客户端用于读取服务器响应的读取缓冲区的大小。
write_buffer_size字符串gRPC客户端用于写入请求的写入缓冲区的大小。"512KiB"(512KiB)
wait_for_ready布尔型在发送数据之前等待gRPC连接处于READY(就绪)状态。false(false)
headersmap(string)与请求一起发送的附加标头。{}
balancer_name字符串用于请求的gRPC客户端端负载均衡器的名称。round_robin(轮询)
authority字符串覆盖gRPC请求中从gRPC客户端的默认:authority头部。
authcapsule(otelcol.Handler)用于验证请求的从otelcol.auth组件的处理器。

默认情况下,请求会使用Gzip进行压缩。compression参数控制使用哪种压缩机制。支持的字符串是:

  • "gzip"(gzip)
  • "zlib"(zlib)
  • "deflate"(deflate)
  • "snappy"(snappy)
  • "zstd"(zstd)

如果您将compression设置为"none"或空字符串"",则请求不会进行压缩。

balancer_name的支持值列在负载均衡的gRPC文档中

  • pick_first:尝试连接到第一个地址,如果成功连接,则用于所有的RPC,或者在失败时尝试下一个地址(并持续这样做,直到连接成功)。因此,所有的RPC将发送到同一个后端。
  • round_robin:连接到它看到的所有地址,并按顺序依次向每个后端发送一个RPC。例如,第一个RPC发送到后端-1,第二个RPC发送到后端-2,然后第三个RPC发送到后端-1。

gRPC中的:authority头部指定请求发送到的主机。它与HTTP请求中的Host 头部类似。默认情况下,:authority的值是从用于gRPC调用的端点URL派生的。覆盖:authority可能在使用代理(如Envoy)时很有用,该代理根据:authority头部的值做出路由决策

您可以通过以下环境变量配置HTTP代理:

  • HTTPS_PROXY
  • NO_PROXY

HTTPS_PROXY环境变量指定了一个用于代理请求的URL。通过HTTP CONNECT方法建立与代理的连接。

NO_PROXY环境变量是一个可选的主机名列表,用于指定HTTPS代理不应使用的域名。每个域名可以作为IP地址(1.2.3.4)、CIDR表示的IP地址(1.2.3.4/8)、域名(example.com)或*提供。域名匹配该域名及其所有子域名。以点开头的域名(.example.com)仅匹配子域名。NO_PROXY仅在设置了HTTPS_PROXY时读取。

因为otelcol.exporter.loadbalancing使用gRPC,配置的代理服务器必须能够处理和代理HTTP/2流量。

tls block

tls块配置了用于连接到gRPC服务器的TLS设置。

支持以下参数:

名称类型描述默认值必需
ca_file字符串CA文件的路径。
ca_pem字符串用于验证服务器的CA PEM编码文本。
cert_file字符串TLS证书的路径。
cert_pem字符串客户端认证的PEM编码证书文本。
insecure_skip_verify布尔型忽略不安全的服务器TLS证书。
include_system_ca_certs_pool布尔型是否在CA证书旁边加载系统证书颁发机构池。false(false)
insecure布尔型连接到配置的服务器时禁用TLS。
key_file字符串TLS证书密钥的路径。
key_pemsecret客户端认证的PEM编码密钥文本。
max_version字符串连接能够接受的最大TLS版本。"TLS 1.3"
min_version字符串连接能够接受的最小TLS版本。"TLS 1.2"
cipher_suites列表(string)TLS传输可以使用的一组TLS加密套件列表。[]
reload_interval持续时间在证书重新加载之前的时间长度。"0s"
server_name字符串设置时,验证服务器证书的主机名。

如果服务器不支持TLS,必须将insecure参数设置为true

要禁用到服务器的连接的tls,将insecure参数设置为true

如果将reload_interval设置为"0s",则证书永远不会重新加载。

以下参数对是相互排斥的,不能同时设置

  • ca_pemca_file
  • cert_pemcert_file
  • key_pemkey_file

如果留空cipher_suites,则会使用一组安全默认加密套件。有关受支持的加密套件的列表,请参阅Go TLS文档

keepalive block

keepalive块配置了gRPC客户端连接的keepalive设置。

支持以下参数:

名称类型描述默认值必需
ping_wait持续时间在无活动后多常 ping 服务器。
ping_response_timeout持续时间如果服务器没有对ping做出响应,则在关闭非活动连接之前等待的时间。
ping_without_stream布尔型即使没有活跃的流请求,也发送ping。

queue block

queue块配置了在发送到gRPC服务器之前的数据的内存缓冲区。

支持以下参数:

名称类型描述默认值必需
enabled布尔型在向客户端发送数据之前启用内存缓冲区。true
num_consumers数量向队列中写入并并行发送批次的读取器数量。10
queue_size数量同时允许在队列中的未写批次的最大数量。1000

enabled设置为true时,数据首先写入内存缓冲区,然后再发送到已配置的服务器。只要未发送批次的数量不超过配置的queue_size,发送到组件的input导出字段的批次就会被添加到缓冲区中。

queue_size确定端点故障被容忍的时间长度。假设每秒100个请求,默认队列大小1000可以容忍大约10秒的故障。为了计算正确的queue_size值,将每秒平均发出的请求数乘以受容忍的故障时间(以秒为单位)。一个非常高值可能导致内存溢出(OOM)杀死。

num_consumers参数控制从缓冲区中读取并发送数据的读取器的数量。较大的num_consumers值可以通过增加网络流量来更快地发送数据。

重试块

retry块配置了对gRPC服务器的失败请求的重试方式。

支持以下参数:

名称类型描述默认值必需
enabled布尔型启用重试失败请求。true
initial_interval持续时间在重试失败请求之前等待的初始时间。"5s"
max_elapsed_time持续时间在丢弃失败批次之前等待的最大时间。"5m"
max_interval持续时间重试之间的最大等待时间。"30s"
multiplier数量增长重试前等待时间的因子。1.5
randomization_factor数量随机化重试前等待时间的因子。0.5

enabledtrue时,给定间隔后重试失败批次。initial_interval参数指定在第一次重试尝试之前等待多长时间。如果请求持续失败,根据multiplier参数指定的因子增加重试前的等待时间,该因子必须大于1.0max_interval参数指定重试之间的最大等待时间。

randomization_factor参数对于在重试Alloy实例之间添加抖动很有用。如果randomization_factor大于0,则重试前的等待时间乘以一个在范围[ I - randomization_factor * I, I + randomization_factor * I]内的随机因子,其中I是当前间隔。

如果批次仍未成功发送,则在max_elapsed_time指定的时间结束后被丢弃。如果max_elapsed_time设置为"0s",则失败请求将无限期重试,直到它们成功。

debug_metrics块

debug_metrics块配置了该组件生成的可监测其状态的指标。

支持以下参数:

名称类型描述默认值必需
disable_high_cardinality_metrics布尔型是否禁用某些高基数指标。true
level字符串控制包装收集器发出的指标的详细程度。"detailed"

disable_high_cardinality_metrics是Grafana Alloy在OpenTelemetry Collector中的对应于telemetry.disableHighCardinalityMetrics功能的开关。它删除可能导致高基数指标的属性。例如,包含IP地址和端口号的HTTP和gRPC连接指标中的属性被删除。

注意

如果配置了,disable_high_cardinality_metrics仅适用于otelcol.exporter.*otelcol.receiver.*组件。

level是Alloy在OpenTelemetry Collector中对应于telemetry.metrics.level功能开关的等价物。可能的值有"none""basic""normal""detailed"

导出字段

以下字段被导出,可以被其他组件引用

名称类型描述
inputotelcol.Consumer供其他组件使用以发送遥测数据。

input接受针对这些类型遥测信号的OTLP格式otelcol.Consumer数据

  • logs
  • traces

选择负载均衡策略

不同的合金组件需要不同的负载均衡策略。使用otelcol.exporter.loadbalancing仅对有状态组件是必要的。

otelcol.processor.tail_sampling

给定跟踪ID的所有跨度必须发送到同一个尾部采样合金实例。

  • 可以通过配置otelcol.exporter.loadbalancing并设置routing_key = "traceID"来实现。
  • 如果您没有配置routing_key = "traceID",采样决策可能不正确。尾部采样器在做出采样决策时,必须对跟踪有全面的认识。例如,如果同一跟踪的跨度分散到多个合金实例,那么基于rate_limiting尾部采样策略可能错误地放过比预期更多的跨度。

otelcol.connector.spanmetrics

给定service.name的所有跨度必须发送到同一个spanmetrics合金。

  • 可以通过配置otelcol.exporter.loadbalancing并设置routing_key = "service"来实现。
  • 如果您没有配置routing_key = "service",从跨度生成的指标可能不正确。例如,如果同一service.name的类似跨度最终落在不同的合金实例上,那么两个合金将为计算跨度延迟、错误和请求数生成相同的指标系列。当两个合金实例尝试将指标写入如Mimir这样的数据库时,这些系列可能会相互冲突。最坏的情况是,由于指标系列的重叠采样,可能导致数据不准确。

然而,可以在不需要负载均衡器的情况下扩展otelcol.connector.spanmetrics

  1. 每个合金可以添加一个属性,例如collector.id,以确保其系列是唯一的。例如,您可以使用sum by PromQL查询来聚合不同合金的指标。然而,额外的collector.id属性有缺点,即数据库中存储的指标将具有更高的基数
  2. Spanmetrics可以生成在后台数据库中,而不是在合金中。例如,跨度指标可以在Grafana Cloud中由Tempo轨迹数据库生成

otelcol.connector.servicegraph

在多个合金实例上扩展otelcol.connector.servicegraph具有挑战性。对于otelcol.connector.servicegraph正确工作,每个“客户端”跨度必须与一个“服务端”跨度配对以计算如跨度持续时间之类的指标。如果一个“客户端”跨度进入一个合金,但一个“服务端”跨度进入另一个合金,那么没有任何一个合金能够配对这些跨度,指标就不会生成。

otelcol.exporter.loadbalancing可以通过配置routing_key = "traceID"部分解决这个问题。然后,每个合金将能够计算跟踪中每个“客户端”/“服务端”对的 服务图。在另一个跟踪中有类似“服务端”/“客户端”值的跨度被另一个合金处理是有可能的。如果两个不同的合金实例处理了相似的“服务端”/“客户端”跨度,它们将生成相同的服务图指标系列。如果两个合金的系列相同,则在将它们写入后端数据库时会出现问题。您可以通过添加类似"collector.id"这样的属性来区分系列。不同合金的系列可以使用后端指标数据库上的PromQL查询进行聚合。如果指标存储在Grafana Mimir中,可以通过自适应指标解决由于"collector.id"标签引起的基数问题。

在Alloy中,生成服务图指标的一个简单且可扩展的替代方案是直接在后端数据库中生成。例如,服务图可以由 Tempo 跟踪数据库在 Grafana Cloud 中生成,详情请参考此处

混合有状态组件

不同的 Alloy 组件可能需要为 otelcol.exporter.loadbalancing 设置不同的 routing_key。例如,otelcol.processor.tail_sampling 需要 routing_key = "traceID",而 otelcol.connector.spanmetrics 需要 routing_key = "service"。为了负载均衡这两种类型的组件,需要设置两组不同的负载均衡器。

  • 一组 otelcol.exporter.loadbalancing 带有 routing_key = "traceID",将跨度发送到进行尾部抽样而不发送跨度指标的 Alloy。
  • 另一组 otelcol.exporter.loadbalancing 带有 routing_key = "service",将跨度发送到进行跨度指标而不生成服务图的 Alloy。

不幸的是,这也可能导致副作用。例如,如果 otelcol.connector.spanmetrics 配置为生成示例,则尾部抽样 Alloy 可能会删除示例所指向的跟踪。尾部抽样 Alloy 和跨度指标 Alloy 之间没有协调,以确保示例的跟踪 ID 被保留。

组件健康

otelcol.exporter.loadbalancing 仅在给定无效配置的情况下报告为不健康。

调试信息

otelcol.exporter.loadbalancing 不公开任何特定组件的调试信息。

示例

静态解析器

此示例接受通过 gRPC 的 OTLP 日志和跟踪。然后以负载均衡的方式将它们发送到“localhost:55690”或“localhost:55700”。

alloy
otelcol.receiver.otlp "default" {
    grpc {}
    output {
        traces  = [otelcol.exporter.loadbalancing.default.input]
        logs    = [otelcol.exporter.loadbalancing.default.input]
    }
}

otelcol.exporter.loadbalancing "default" {
    resolver {
        static {
            hostnames = ["localhost:55690", "localhost:55700"]
        }
    }
    protocol {
        otlp {
            client {}
        }
    }
}

DNS 解析器

当配置为使用 dns 解析器时,otelcol.exporter.loadbalancing 将定期执行 DNS 查询。跨度被导出到 DNS 查询返回的地址。

alloy
otelcol.exporter.loadbalancing "default" {
    resolver {
        dns {
            hostname = "alloy-traces-sampling.grafana-cloud-monitoring.svc.cluster.local"
            port     = "34621"
            interval = "5s"
            timeout  = "1s"
        }
    }
    protocol {
        otlp {
            client {}
        }
    }
}

以下示例展示了配置两个 Alloy 集群的 Kubernetes 配置

  • 一组负载均衡 Alloy
    • 跨度通过 otelcol.receiver_otlp 从受instrumentation的应用程序接收。
    • 跨度通过 otelcol.exporter.loadbalancing 导出。
  • 一组抽样 Alloy
    • 抽样 Alloy 在无头服务后运行,以使负载均衡器 Alloy 能够发现它们。
    • 跨度通过 otelcol.receiver_otlp 从负载均衡器 Alloy 接收。
    • 通过 otelcol.processor.tail_sampling 对跟踪进行采样。
    • 通过 otelcol.exporter.otlp 将跟踪导出到 Tempo 等OTLP兼容数据库。

在运行示例之前,您必须填写正确的 OTLP 凭据。您可以使用 k3d 启动示例。

bash
k3d cluster create alloy-lb-test
kubectl apply -f kubernetes_config.yaml

要删除集群,请运行

bash
k3d cluster delete alloy-lb-test

Kubernetes 解析器

当您将 otelcol.exporter.loadbalancing 配置为使用 kubernetes 解析器时,Kubernetes API 将在向服务添加或删除新 pod 时通知 Alloy。跨度被导出到 Kubernetes API 的地址,结合所有可能的 端口号

alloy
otelcol.exporter.loadbalancing "default" {
    resolver {
        kubernetes {
            service = "alloy-traces-headless"
            ports   = [ 34621 ]
        }
    }
    protocol {
        otlp {
            client {}
        }
    }
}

以下示例展示了一个Kubernetes配置,该配置设置了两套Alloys。

  • 一组负载均衡 Alloy
    • 跨度通过 otelcol.receiver_otlp 从受instrumentation的应用程序接收。
    • 跨度通过 otelcol.exporter.loadbalancing 导出。
    • 当Kubernetes API通知采样Alloys集合并添加或删除Pod时,负载均衡器Alloys会收到通知。
  • 一组抽样 Alloy
    • 采样Alloys不需要运行在无头服务后面。
    • 跨度通过 otelcol.receiver_otlp 从负载均衡器 Alloy 接收。
    • 通过 otelcol.processor.tail_sampling 对跟踪进行采样。
    • 遥测数据通过 otelcol.exporter.otlp导出到兼容OTLP的数据库,如Tempo。

在运行示例之前,您必须填写正确的 OTLP 凭据。您可以使用 k3d 启动示例。

bash
k3d cluster create alloy-lb-test
kubectl apply -f kubernetes_config.yaml

要删除集群,请运行

bash
k3d cluster delete alloy-lb-test

兼容组件

otelcol.exporter.loadbalancing的导出可以被以下组件消费

注意

连接某些组件可能没有意义,或者组件可能需要进一步配置才能正确连接。有关更多详细信息,请参阅链接文档。