菜单
开源

Promtail Push API

  • 作者:Robert Fratto (@rfratto)
  • 日期:2020 年 2 月 4 日
  • 状态:草稿

尽管 Promtail 是可选软件,但它提供了 Loki 故事的半壁江山:日志转换、服务发现、从日志中提取指标以及在现有指标和日志之间切换上下文。目前,Promtail 只能从非常特定的源消费日志:文件、journal 或 syslog。如果用户想编写自定义工具来发送日志,这些工具就必须绕过 Promtail 直接推送到 Loki。这可能导致用户重新实现 Promtail 已提供的功能,包括其错误重试和批处理代码。

本文档提出了 Promtail 的 Push API。首选的实现方式是复制现有的 Loki Push API,并在 Promtail 中实现它。通过与 Loki Push API 兼容,Promtail Push API 可以一次处理批量日志以优化性能。匹配 Promtail API 还允许用户从现有工具透明地切换推送 URL。最后,详细介绍了一系列替代方案。

配置

Promtail 将有一个名为 HTTPTarget 的新目标,可在 scrape_config 数组中按以下 schema 配置

yaml
# Defines an HTTP target, which exposes an endpoint against the Promtail
# HTTP server to accept log traffic.
http:
  # Defines the base URL for the push path, adding a prefix to the
  # exposed endpoint. The final endpoint path is
  # <base_url>loki/api/v1/push. If omitted, defaults to /.
  #
  # Multiple http targets with the same base_url must not exist.
  base_url: /

  # Map of labels to add to every log line passed through to the target.
  labels: {}

注意事项

用户可以定义多个 http scrape config,但每个实例的基本 URL 值必须不同。这样可以清晰地通过不同的推送端点分离 Pipeline。

用户还必须注意在负载均衡器后使用 HTTP target 运行 Promtail 可能出现的问题:如果负载均衡器在多个 Promtail 实例之间分配 payload,Loki 中的日志顺序会被打乱,导致推送被拒绝。建议用户执行以下操作之一:

  1. 使用专用的 Promtail 实例接收推送。这也适用于使用 syslog target。
  2. 使用单独的 Kubernetes Service,它总是解析到同一个 Promtail Pod,从而绕过负载均衡问题。

实现

如本文档所述,此功能将通过复制现有的 Loki Push API 并在 Promtail 中暴露它来实现。

考虑的替代方案

选择使用现有 API 是因为其简单性以及可用于有趣的配置(例如,将 Promtail 链式连接)。考虑了这些其他选项,但由于不是解决问题的最佳方案而被拒绝。

请注意,选项 3 具有价值,可能会独立于此功能实现。

选项 1:JSON / Protobuf Payload

可以设计一个新的 JSON 和 Protobuf payload 格式来替代现有的 Loki 推送 payload。两种格式都必须暴露,以支持不能或不使用 protobuf 序列化的客户端。

这种方法的主要优点是允许我们独立于 Loki 现有 schema 调整 payload schema,但除此之外可能作用不大,本质上只是代码重复。

选项 2:gRPC Service

logproto.Pusher Service 可以通过 Promtail 暴露。这将支持为支持 gRPC 的语言生成客户端存根,并且为了支持 HTTP/1,一个 gRPC gateway 将嵌入到 Promtail 本身中。

此实现选项类似于最初提出的解决方案,但使用 gRPC gateway 处理 HTTP/1 流量,而不是 Loki 使用的 HTTP/1 shim。这种方法存在一些问题:

  1. gRPC Gateway 反向代理需要与 Promtail 中使用的现有 HTTP mux 良好配合。
  2. 我们无法像 Loki 那样独立控制 HTTP 和 Protobuf 格式。
  3. 由于反向代理,日志行将被双重编码。
  4. 使用进程内反向代理会引入少量开销。
  5. 这打破了我们编写自己的 shim 函数的常规模式;可能增加一些认知负担,因为必须将 gRPC gateway 作为代码中的一个例外来处理。

选项 3:纯文本 Payload

Prometheus 的 Push Gateway API 设计巧妙,我们应该考虑以相同的格式实现我们的 API:用户可以使用纯文本 POST 请求体推送到 http://promtail-url/push/label1/value1?timestamp=now。例如

curl -X POST http://promtail.default/push/foo/bar/fizz/buzz -d “hello, world!”

与非纯文本 payload 相比,这种方法可能稍快,因为不需要进行反序列化。仍然需要解析 URL 路径和时间戳,但这通常比 JSON 带来的反射需求更快。

然而,请注意,此 API 限制 Promtail 每次只能接受一行,并且在尝试处理大量流量时可能会导致性能问题。作为替代方案,此 API 也可以由外部工具实现,并构建在任何其他实现选项之上。

已创建了一个示例实现,并因其简单性和易于集成而获得了积极的支持。