饮墨

子安饮墨馀三斗,留与卿儿作赋来

用 Grafana Alloy 统一遥测采集:3 步替代 Grafana Agent + Prometheus Agent,告别多组件碎片化

痛点:遥测采集组件碎片化,运维成本越来越高

一个典型的可观测性栈,你可能同时跑着:

  • Grafana Agent 采集 metrics
  • Promtail 收日志发到 Loki
  • Grafana Agent Traces 收 traces 转发到 Tempo
  • 可能还有 OpenTelemetry Collector 处理 OTLP 数据

每个组件独立配置、独立升级、独立排障。配置格式不统一(YAML、River、TOML 各来一套),监控采集器本身就成了运维负担。

2024 年 4 月,Grafana Labs 正式发布 Alloy —— 一个统一的、OpenTelemetry 原生的遥测采集器,直接替代上面所有组件。Grafana Agent 进入维护模式,官方明确推荐迁移到 Alloy。

如果你正在用 Grafana 生态做可观测性,现在是迁移的最佳时机。


方案:Alloy 是什么,凭什么能统一

Grafana Alloy 的核心设计:

特性 说明
统一采集 Metrics、Logs、Traces、Profiles 四合一,单二进制搞定
Alloy 配置语法 基于 HCL 风格的声明式语法(原 River),组件化、可组合、支持条件逻辑
OpenTelemetry 原生 内置 OTLP receiver/exporter,兼容 OTel Collector 的 receiver/processor
Prometheus 兼容 完整支持 prometheus.scrape、服务发现、relabel,配置可一键转换
内置 UI 自带 DAG 可视化界面(默认 :12345),实时查看数据流向和组件状态
集群模式 多实例自动分片采集目标,无需外部协调器

一句话总结:Alloy = Grafana Agent + Promtail + OTel Collector 的合体,配置更直观,功能更强


实操:3 步从 Grafana Agent 迁移到 Alloy

第 1 步:安装 Alloy

Debian/Ubuntu:

# 添加 Grafana APT 源(如果已有可跳过)
sudo apt-get install -y apt-transport-https software-properties-common
sudo mkdir -p /etc/apt/keyrings/
wget -q -O - https://apt.grafana.com/gpg.key | gpg --dearmor | sudo tee /etc/apt/keyrings/grafana.gpg > /dev/null
echo "deb [signed-by=/etc/apt/keyrings/grafana.gpg] https://apt.grafana.com stable main" | sudo tee /etc/apt/sources.list.d/grafana.list

# 安装 Alloy
sudo apt-get update && sudo apt-get install -y alloy

# 验证安装
alloy --version

Docker 方式(推荐测试环境):

docker run -d --name alloy \
  -p 12345:12345 \
  -p 4317:4317 \
  -p 4318:4318 \
  -v /etc/alloy:/etc/alloy \
  grafana/alloy:latest \
  run /etc/alloy/config.alloy

第 2 步:编写 Alloy 配置(同时采集 Metrics + Logs)

创建 /etc/alloy/config.alloy

// ===== Metrics 采集:替代 Prometheus Agent =====

// 服务发现:抓取本机 node_exporter
prometheus.scrape "node" {
  targets = [{
    __address__ = "localhost:9100",
  }]
  forward_to = [prometheus.remote_write.mimir.receiver]
  scrape_interval = "15s"
}

// Kubernetes Pod 自动发现(K8s 环境启用)
// prometheus.kubernetes "pods" {
//   role = "pod"
// }
// prometheus.scrape "k8s_pods" {
//   targets    = prometheus.kubernetes.pods.targets
//   forward_to = [prometheus.remote_write.mimir.receiver]
// }

// 远程写入到 Mimir / Prometheus
prometheus.remote_write "mimir" {
  endpoint {
    url = "http://mimir:9009/api/v1/push"
    // 如需认证:
    // basic_auth {
    //   username = "admin"
    //   password = env("MIMIR_PASSWORD")
    // }
  }
}

// ===== 日志采集:替代 Promtail =====

// 采集本机系统日志
local.file_match "syslog" {
  path_targets = [{
    __path__ = "/var/log/syslog",
    job      = "syslog",
    host     = constants.hostname,
  }]
}

loki.source.file "syslog" {
  targets    = local.file_match.syslog.targets
  forward_to = [loki.write.default.receiver]
}

// 采集容器日志(Docker 环境)
// loki.source.docker "containers" {
//   host       = "unix:///var/run/docker.sock"
//   targets    = discovery.docker.linux.targets
//   forward_to = [loki.write.default.receiver]
// }

// 写入 Loki
loki.write "default" {
  endpoint {
    url = "http://loki:3100/loki/api/v1/push"
  }
}

// ===== OTLP 接收:替代 OTel Collector =====

otelcol.receiver.otlp "default" {
  grpc {
    endpoint = "0.0.0.0:4317"
  }
  http {
    endpoint = "0.0.0.0:4318"
  }

  output {
    traces  = [otelcol.exporter.otlp.tempo.input]
    metrics = [otelcol.exporter.prometheus.mimir.input]
  }
}

// Traces 转发到 Tempo
otelcol.exporter.otlp "tempo" {
  client {
    endpoint = "tempo:4317"
    tls {
      insecure = true
    }
  }
}

// OTLP Metrics 转 Prometheus 格式写入
otelcol.exporter.prometheus "mimir" {
  forward_to = [prometheus.remote_write.mimir.receiver]
}

配置语法解读:

  • 每个 block 是一个组件,通过 forward_to / output 连接成 DAG
  • 组件间解耦,新增采集源只需加 block + 连线,不影响已有配置
  • 支持 env() 函数引用环境变量,敏感信息不硬编码

第 3 步:启动并验证

# 启动服务
sudo systemctl enable --now alloy

# 检查状态
sudo systemctl status alloy

# 查看日志确认无报错
journalctl -u alloy -f --no-pager | head -50

# 打开内置 UI 查看组件 DAG 和数据流
echo "访问 http://<your-ip>:12345 查看 Alloy UI"

验证数据链路:

# 确认 metrics 正在被抓取
curl -s http://localhost:12345/metrics | grep alloy_component_controller_running_components

# 确认 OTLP 端口可达
curl -s http://localhost:4318/v1/traces -X POST -H "Content-Type: application/json" -d '{}' 
# 应返回 200 或 protobuf 相关响应,而非 connection refused

从 Grafana Agent 迁移的快捷方式

如果你已有 Grafana Agent 的 YAML 配置,Alloy 提供一键转换工具:

# 将 Grafana Agent Flow 配置转换为 Alloy 格式
alloy convert --source-format=flow --output=config.alloy agent-config.river

# 将 Grafana Agent Static 配置转换
alloy convert --source-format=static --output=config.alloy agent-config.yaml

# 将 Promtail 配置转换
alloy convert --source-format=promtail --output=promtail.alloy promtail.yaml

# 将 OpenTelemetry Collector 配置转换
alloy convert --source-format=otelcol --output=otel.alloy otel-config.yaml

转换后review 一下生成的配置,大多数场景可以直接使用。


避坑指南

坑 1:配置语法从 River 更名为 Alloy,旧文档别照抄

Alloy 1.0 之前叫 Grafana Agent Flow,用 River 语法。正式发布后语法名改为 Alloy syntax,关键字和结构不变,但文件后缀是 .alloy,不是 .river。搜到的旧教程如果写 grafana-agent run --config.file=xxx.river,需要改用 alloy run config.alloy

坑 2:集群模式下 target 分片需要显式启用

Alloy 支持多实例自动分片(类似 Prometheus Operator 的 sharding),但需要配置集群 block:

// 启用集群分片
cluster "default" {
  enabled = true
  // 使用 Kubernetes headless service 发现其他实例
  join_addresses = ["alloy-headless.monitoring.svc:7946"]
}

不加这段配置,多副本部署会导致每个实例都抓全量 target,造成重复数据。

坑 3:内存默认无上限,生产环境必须设 limiter

Alloy 默认不限内存,大量采集目标场景下可能 OOM。生产配置必加:

// 全局内存限制,到达 80% 时开始丢弃数据而非 OOM
otelcol.processor.memory_limiter "default" {
  check_interval = "1s"
  limit          = "512MiB"  // 根据实际调整
}

同时 systemd unit 中设置 MemoryMax=

# /etc/systemd/system/alloy.service.d/override.conf
[Service]
MemoryMax=768M

总结

维度 迁移前(碎片化) 迁移后(Alloy)
组件数 3-4 个独立进程 1 个二进制
配置格式 YAML + River + TOML 统一 Alloy syntax
OTel 支持 需额外部署 Collector 内置原生支持
排障 多处日志交叉排查 单一 UI + DAG 可视化
升级 各组件版本矩阵 单版本统一发布

迁移建议:

  1. 新项目直接用 Alloy,不要再装 Grafana Agent
  2. 存量环境用 alloy convert 转换配置,逐节点灰度替换
  3. 生产环境务必配置内存限制 + 集群分片
  4. 善用内置 UI(:12345)排查数据流向问题

Grafana Agent 已进入维护模式,不再接受新功能。Alloy 是 Grafana 可观测性栈的标准采集层,早迁早受益。

您还没有登录,请登录后发表评论。