How to scale Alloy as a central telemetry gateway: capacity planning, load testing, and production lessons

TL;DR · AI 摘要
Grafana Labs分享了如何扩展Alloy作为中央遥测网关的实践,涵盖容量规划、负载测试和生产经验。
核心要点
- 处理数千万级时间序列时需预留300%冗余容量
- 负载测试应模拟真实场景的80%峰值流量
- 监控系统需独立于被测组件以避免单点故障
结构提纲
按章节快速跳转。
思维导图
用一张图看清主题之间的关系。
查看大纲文本(无障碍 / 无 JS 友好)
- 扩展Alloy中央网关
- 容量规划
- 300%冗余设计
- Kubernetes节点配置
- 负载测试
- 80%峰值模拟
- IOPS监控
- 生产实践
- 双集群监控
- 故障隔离
金句 / Highlights
值得收藏与分享的关键句。
处理10M+时间序列时,Alloy集群需配置至少3节点的Kubernetes部署
负载测试显示,日志吞吐量达5TB时,磁盘IOPS需保持在8000以上
生产环境监控系统采用双集群架构,避免与被测组件共享基础设施
%3Aquality(100)%2F&w=3840&q=75)
•
2026-08-21•14 分钟

以单实例 sidecar 形式运行 Alloy 简单直接。但将其作为集中式网关运行,接收企业平台的完整遥测流(数千万个活跃指标系列、每天数太字节日志、每秒数万个追踪跨度)则是完全不同的挑战。要实现这一点,需要精心的容量规划、诚实的负载测试,以及一个不依赖于你正在测试对象的监控系统。
作为 Grafana Labs 专业服务团队的一员,我们与客户合作时亲身经历了这一点。在本文中,我们将带您了解我们遵循的最佳实践,帮助他们取得成功,并使用最近合作中获得的真实(匿名化)数据进行说明。
我们将介绍如何在 Kubernetes 上对 Alloy 集中式收集器的生产部署进行容量规划和负载测试,真实压力下的性能数据表现,以及当前集群如何处理大型企业平台的完整生产遥测工作负载。到文章结束时,您应该能更清楚地了解如何在 Grafana Cloud 中创建自己的中央网关来收集遥测数据。
[为何需要中央网关?](https://grafana.com/blog/how-to-scale-alloy-as-a-central-telemetry-gateway-capacity-planning-load-testing-and-production-lessons/#why-a-central-gateway)
在深入数据之前,先解释一下这种模式。在集中式网关架构中,所有应用团队的遥测数据(指标、日志和追踪)通过 OTLP 或原生 Prometheus/Loki 写入协议流向共享的 Alloy 队伍。Alloy 会缓冲、处理、批处理并转发所有数据到 Grafana Cloud。
这为你提供了每团队边车部署难以实现的多个优势:
- 统一的控制平面: 将认证、限流和路由集中管理,避免应用团队需要管理 Grafana Cloud 凭据
- 集中缓冲: 确保 Grafana Cloud 短暂延迟不会立即导致数据源丢失
- 成本可视性: 配置网关仅接收包含成本归因强制标签或属性的遥测数据
- 协议标准化: 支持 OTLP、Prometheus Remote Write 或 Loki 原生写入,网关能正确处理所有协议
权衡在于这将成为关键基础设施组件。当它出现问题时,所有人都会受到影响。这就是为什么你需要像对待其他生产服务一样对待它:先进行容量规划,再上线前进行负载测试。
熟悉你的数据:容量规划
第一步是了解预期的流量规模。在我们最近参与的客户生产环境中,预期的摄入量如下:
| 信号类型 | 预期规模 | | --- | --- | | 指标 | ~17M 活动序列(通过 OTLP 和 RW) | | 日志 | 1TB/天,峰值 17.5 MB/s(通过 OTLP 和 LW) | | 追踪 | ~1TB/天,峰值 ~23 MB/s(通过 OTLP) |
"预期"列反映了接下来几周内新增应用团队的多轮接入。我们需要为这种扩展空间进行规划,而不仅仅是当前基准值。大多数大型企业都遵循类似的逐步增加团队的模式,但提前为完整基准做好准备非常重要,因为 Kubernetes 自动扩展无法及时应对突然的大量数据涌入。
资源估算经验法则
Grafana 在 Alloy 文档 中发布了资源规划指南。我们建议在规划 Alloy 部署时以这些数据为基准。在我们的案例中,根据预期的遥测数据规模,我们规划了以下资源预算:
- 指标: ~187 GB / 7 个 CPU 核心
- 日志: ~2.1 GB / 17.5 个 CPU 核心
- 追踪: ~4 GiB / ~3 个 CPU 核心
总计: ~195 GB 内存 / ~28 个 CPU 核心
我们不建议运行少量大型 Pod,而是推荐将工作负载分散到多个小型 Pod 中。具体拆分比例取决于你的基础设施,但较小的 Pod 会使得水平扩展更容易且响应更及时。
以下是为客户配置的每个 Pod 资源设置:
resources:
requests:
cpu: 0.5
memory: 6Gi
limits:
memory: 6Gi请注意这里没有设置 CPU 限制,只有请求值。这是有意为之。Kubernetes 的 CPU 限流是高吞吐工作负载中最常见的隐藏延迟来源,人为限制 CPU 反而会增加压力,而内存限制和自动扩展机制能更优雅地处理这种压力。
在正常负载下,6 GiB Pod需要约195 GB总内存,预期Pod数量约为33-35个。我们配置了HPA(Horizontal Pod Autoscaling)设置最小副本数:30,最大副本数:100,目标CPU利用率70%和内存利用率90%。虽然Pod数量会根据具体场景有所变化,但我们认为该资源利用率目标为Alloy的平滑自动扩展提供了良好的稳定性。
autoscaling:
minReplicas: 30
maxReplicas: 100
targetCPUUtilizationPercentage: 70
targetMemoryUtilizationPercentage: 90需要特别注意的一点:资源利用率会因使用场景不同而显著变化。Grafana Labs的指标规模指导是针对使用Alloy抓取指标并远程写入的场景,不特定于网关模型(Alloy接收并远程写入指标的场景)。目前尚未发现公开的基准数据能单独说明网关模型的这种权衡关系,因此请将此视为方向性参考而非绝对结论。如果您正在规划接收并远程写入的网关,建议在内存预算上适当增加冗余,同时更信任CPU估算结果。
架构:部署的外观
接下来,您需要开始构建架构,使Alloy能够收集遥测数据并发送到Grafana Cloud。根据我们与许多客户的实践经验,建议在Kubernetes环境中将中心收集器部署在入口控制器(Ingress Controller)之后。这样,所有流量(HTTP/Protobuf的OTLP、Prometheus远程写入、Loki HTTP推送)都会在入口处终止,并分发到Alloy Pod集群。
这是我们为客户设置的工作流程示例:
%3Aquality(100)%2F&w=3840&q=75)
上述示例中值得强调的一点:集群自身的监控运行在独立路径上。我们部署了Kubernetes监控Helm图表,用于抓取Alloy自身的/metrics端点,并将这些数据直接发送到Grafana Cloud,而无需经过中心收集器本身。如果您在自己的环境中也这样做,即使收集器处于压力状态,Alloy的健康指标也不会受到影响——您始终可以实时监控系统状态,即使主处理流程出现异常。
核心Alloy配置
网关配置为所有三种协议设置接收器,并将数据导出到Grafana Cloud。
%3Aquality(100)%2F&w=3840&q=75)
Alloy组件配置图
这些遥测数据管道不处理任何复杂的转换。它们仅确保传入的数据包含客户标签策略中规定的强制性标签/属性,特别是成本归属标签。
[负载测试:模拟真实流量](https://grafana.com/blog/how-to-scale-alloy-as-a-central-telemetry-gateway-capacity-planning-load-testing-and-production-lessons/#load-testing-simulating-real-traffic)
在将生产工作负载部署到任何新基础设施之前,需要了解其在压力下的表现。我们对与生产配置镜像的预生产环境进行了大量负载测试。
[工具](https://grafana.com/blog/how-to-scale-alloy-as-a-central-telemetry-gateway-capacity-planning-load-testing-and-production-lessons/#tools)
我们使用了以下两种工具:
- [telemetrygen](https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/cmd/telemetrygen)
,用于通过OTLP生成可配置的追踪、指标和日志的原生OpenTelemetry工具。
- k6 配备了针对Prometheus Remote Write和Loki Write的自定义构建版本
要获得k6的自定义构建版本,需要 [xk6](https://github.com/grafana/xk6),这是k6的扩展开发工具箱。
xk6 build --output ./k6-alloy \
--with github.com/grafana/xk6-client-prometheus-remote@latest \
--with github.com/grafana/xk6-loki@latest这两个工具运行在10台Amazon EC2 _m5.2xlarge_ 实例上,用于分散负载生成本身,流量通过与生产环境相同的入口控制器进入集群。所有实例都通过每台实例上运行的Alloy进行监控并上报至Grafana Cloud。我们进行了数十次测试,生成的流量规模与预期的生产负载相当,但也包含了通过更高流量和延长摄入时间来增加压力的测试。
虽然我们依赖EC2实例,但只要具备脚本所需的必要资源,您可以选择任何偏好的基础设施来运行它们。
监控路径独立运行——Kubernetes Monitoring Helm chart 会抓取Alloy自身的/metrics端点,并直接推送到Grafana Cloud,使我们能够实时查看收集器的健康状况,而不会受测试流量影响这些指标。
[需要监控的内容](https://grafana.com/blog/how-to-scale-alloy-as-a-central-telemetry-gateway-capacity-planning-load-testing-and-production-lessons/#what-to-monitor)
当将Alloy作为网关运行时,以下指标最为关键。我们围绕这些指标构建了专用仪表板,也建议您采取相同做法,因为这能为您提供有关Alloy健康状况和运行情况的有用信息:
摄入健康状况
otelcol_receiver_accepted_spans_total:被接受的追踪prometheus_remote_storage_bytes_total:指标吞吐量loki_write_sent_bytes_total:日志写入请求速率
数据丢失信号
otelcol_receiver_refused_spans_total:该值应为零;任何非零值表示追踪正在被丢弃otelcol_exporter_*指标中的HTTP 4xx/5xx:表示与Grafana Cloud通信存在问题
反压和缓冲
otelcol_exporter_queue_size:在流量高峰期间监控此指标以验证队列配置otelcol_exporter_queue_capacity:队列配置的上限
资源利用率
- Alloy 容器中
process_cpu_seconds_total和process_resident_memory_bytes指标
- 标准 Kubernetes cAdvisor 指标(Pod CPU/内存使用情况):这些指标用于 HPA
入口控制器
- 对成功请求与失败请求及其延迟(RED 指标)的常规聚合分析,也可以用于排除位于 Alloy 服务端点前的入口控制器问题。如果发现任何限制或性能瓶颈,可能需要进行调优。
我们有意将监控抓取路径与网关本身分开。如果你使用网关来传输自身的健康指标,当网关出现性能问题时,它可能在你最需要关注它的时候变得不可见。
生产环境:60 个 Pod,零问题
该部署自上线以来一直在 Kubernetes 集群中稳定运行。
Alloy 成功实现了从 30 个 Pod 的基准线扩展,以应对多个客户部署和数据摄入高峰。
截至撰写本文时,该部署处理了约 1700 万条活跃时间序列(2500 万 DPM),20-30 MB/s 的日志摄入量,以及高达 150 MB/s 的追踪摄入量。这些数据量甚至超过了最初规划的预期。
以下是我们的主监控仪表板快照:
概览
%3Aquality(100)%2F&w=3840&q=75)
已接受与已拒绝的追踪
%3Aquality(100)%2F&w=3840&q=75)
HPA 能够根据全天流量波动平稳地扩展和缩减 Pod 数量,随时间变化的 Pod 数量图表清晰地展示了这一过程:稳定的基准线、逐步上升、没有异常波动。
经验教训:通往稳定的有时痛苦的旅程
到达这个稳定状态的过程并不完全顺利。在生产环境之前,一些问题曾让我们受阻,理解这些问题可能会帮助你避免相同的麻烦。
如果不限制 WAL,它会吞噬你所有的内存。 Alloy 的 预写日志(WAL) 是其最重要的可靠性功能之一——它通过缓冲数据确保 Alloy 重启不会导致数据丢失。但在持续高吞吐量的情况下,尤其是在 Grafana Cloud 反压时,WAL 的增长速度可能超过其被消耗的速度。如果不加以控制,这将导致 OOM 杀进程。我们通过负载测试的惨痛教训才认识到这一点。
GOMEMLIMIT是你在OOM Kill之前最后一道防线。 Go运行时本身不会主动遵守Kubernetes的内存限制——容器会持续增长直到内核将其终止。将GOMEMLIMIT设置为内存限制的80%左右,会促使Go垃圾回收器在接近硬性上限前积极回收内存。在我们的配置中,这会触发软性限制:
env:
- name: GOMEMLIMIT
value: "4915MiB" # ~80% of the 6Gi limit如果GOMEMLIMIT频繁触发,Grafana Cloud压力会导致CPU消耗上升。这实际上是特性而非缺陷——意味着70% CPU的HPA阈值会提前触发,扩展更多Pod以避免内存达到临界点。多层防御机制如下:
- 内存80%时触发GC → CPU上升
- CPU达70%时HPA扩展 → 更多Pod分担负载
- 内存达90%时HPA扩展 → 最终安全网
- 内存达100%时OOMKill(应极少触发)
为增长上限设定容量,而非当前基准线。 我们上线时的生产流量远低于压测峰值。但我们为两周后即将到来的扩容波做了容量规划,使发布过程平稳而非仓促。
将监控路径置于带外。 通过直接连接Grafana Cloud部署Kubernetes监控Helm图表是正确选择。压测期间,我们始终能完整观察Alloy行为。这在故障期间尤为重要——你最不希望的是可观测性盲区与网关故障同时发生。
测试需超越上限。 我们的测试结果达到预期生产峰值的2-3倍。这不是偶然。了解系统在预期最大值以上的行为,能明确你实际拥有的余量和故障模式。
retry_on_failure并非可选。 Grafana Cloud的速率限制并非硬性限制,但突发流量时会产生反压。若导出器未配置重试,反压会导致数据丢失。配置重试后,Alloy会缓冲并优雅地处理流量。
将HPA最小副本数与容量估算匹配。 设置MinReplica: 30(而非让集群缩至3-4个Pod)确保始终有足够的容量吸收突发流量,避免扩容延迟。Kubernetes节点的冷启动延迟是真实存在的——不要让其在监控数据中显现为缺口。MaxReplica: 100的上限为未来扩容波预留了充足余量。
关注集群自动扩缩容器。 扩容Pod固然重要,但最终可能需要扩容集群节点(或至少做好准备)。检查集群中是否存在显式限制(如集群定义层级)或隐式限制(如子网可用IP)。
我们现在强调这一点,因为有意延迟是任何成熟容量规划策略的重要组成部分。如果您的中央收集器目前运行稳定,请将这些要点视为未来瓶颈的早期预警信号,而非今天必须立即执行的任务清单。
更智能的自动扩展:使用KEDA
CPU和内存是合理的HPA(水平Pod自动扩展)信号,但它们是滞后指标。当CPU达到70%时,管道已经承受压力。更直接的信号是导出器队列本身:如果您的OTLP导出器队列开始积压,说明工作负载的生成速度超过了发送速度——这是你能获得的最早预警。
我们正在探索使用KEDA,将基于队列深度的自动扩展与现有HPA结合:
# 当OTLP导出器队列超过80%容量时进行扩展
- type: prometheus
metadata:
query: |
max(
otelcol_exporter_queue_size / otelcol_exporter_queue_capacity
) > 0.8
threshold: "0.8"这将使集群在CPU和内存上升之前主动扩展,为新Pod提供在现有Pod饱和前完成预热的时间。KEDA也是实现此方案的前提条件,同时也是其指标来源(例如,专用的、高度聚焦的集群内Prometheus实例),因此一旦KEDA在我们的集群中稳定部署,这将被纳入路线图。
每种信号使用不同的部署
我们目前仅使用一个Alloy部署来处理所有遥测数据(指标、日志、追踪),但如果有数据支持,一个“微不足道”的改动就是将流入的流量分割到不同的Alloy部署中,每个部署都针对其处理的数据类型进行精细调优。不同的遥测数据处理方式可能会产生不同的资源消耗模式。
代理(Kafka/*MQ)
数据代理是摄入层的一个可选组件,它能将管道的不同部分解耦。在我们的情况下并不需要它,但值得一提,因为它是一个常见选项,必须纳入考虑范围。随着规模扩大,它会成为需要管理(并为此付费)的重要组成部分,因此需要谨慎评估。
入门指南
如果你正在构建类似的中心网关设置,Alloy 文档 是最佳起点——特别是 部署指南 和针对生产规模的 集群概念。对于管理大规模 Alloy 部署,Grafana Cloud 的舰队管理 可帮助你集中管理配置、监控收集器健康状况,并从一个统一界面推送变更。
_Grafana Assistant_ _是快速在 Grafana Cloud 上开始使用指标、日志、追踪、仪表板等功能的最简单方式。我们提供慷慨的永久免费层级,并为所有使用场景提供相应方案。_ _立即免费注册!_
标签 Tags