Promtail 是负责收集日志发送给 loki 的代理程序,Promtail 默认通过一个 config.yaml 文件进行配置,其中包含 Promtail 服务端信息、存储位置以及如何从文件中抓取日志等配置。

要指定加载哪个配置文件,只需要在命令行下通过 -config.file 参数传递 YAML 配置文件即可。此外我们还可以通过在配置文件中使用环境变量引用来设置需要的配置,但是需要在命令行中配置 -config.expand-env=true

然后可以使用 ${VAR} 来配置,其中 VAR 是环境变量的名称,每个变量的引用在启动时被环境变量的值替换,替换是区分大小写的,而且在 YAML 文件被解析之前发生,对未定义变量的引用将被替换为空字符串,除非你指定了一个默认值或自定义的错误文本,要指定一个默认值:

 ${VAR:default_value}

其中 default_value 是在环境变量未定义的情况下要使用的默认值。

1.根节点-概览

默认的 config.yaml 配置文件支持的内容格式为:

 #配置影响所有目标的全局设置。
 [global: <global_config>]
 ​
 #为Promtail配置服务器。
 [server: <server_config>]
 ​
 #描述Promtail如何连接到多个实例Grafana Loki,向每个实例发送日志。警告:如果其中一个远程Loki服务器无法响应或响应对于任何可重试的错误,这将影响将日志发送到其他配置的远程Loki服务器。发送是在一个线程上完成的!通常建议并行运行多个Promtail客户端如果您想发送到多个远程Loki实例。
 clients:
   - [<client_config>]
 ​
 #描述如何将读取文件偏移量保存到磁盘
 [positions: <position_config>]
 ​
 # 抓取日志配置
 scrape_configs:
   - [<scrape_config>]
 ​
 #配置此Promtail实例的全局限制
 [limits_config: <limits_config>]
 ​
 #配置跟踪目标的监视方式。
 [target_config: <target_config>]
 ​
 # 配置promtail额外配置
 [options: <options_config>]
 ​
 # 配置跟踪支持
 [tracing: <tracing_config>]

2.根节点-global

global块配置影响所有抓取目标的全局设置:

 #配置轮询磁盘中日志文件的更改频率。
 [file_watch_config: <file_watch_config>]

2.1 file_watch_config

file_watch_config块配置从磁盘轮询日志文件以了解更改的频率:

 # 轮询文件的最低频率。每当检测到文件更改时,轮询频率将重置为此持续时间
 [min_poll_frequency: <duration> | default = "250ms"]
 ​
 # 轮询文件的最大频率。任何时候未检测到文件更改,
 # 轮询频率的值加倍,直到指定的最大持续时间等于这个值
 #
 # 默认设置为与min_poll_frequency相同。
 [max_poll_frequency: <duration> | default = "250ms"]

2.根节点-server

server 属性配置了 Promtail 作为 HTTP 服务器的行为。

 # 禁用 HTTP 和 GRPC 服务
 [disable: <boolean> | default = false]
 ​
 # HTTP 服务监听的主机
 [http_listen_address: <string>]
 ​
 # HTTP 服务监听的端口(0表示随机)
 [http_listen_port: <int> | default = 80]
 ​
 # gRPC 服务监听主机
 [grpc_listen_address: <string>]
 ​
 # gRPC 服务监听的端口(0表示随机)
 [grpc_listen_port: <int> | default = 9095]
 ​
 # 注册指标处理器
 [register_instrumentation: <boolean> | default = true]
 ​
 # 优雅退出超时时间
 [graceful_shutdown_timeout: <duration> | default = 30s]
 ​
 # HTTP 服务读取超时时间
 [http_server_read_timeout: <duration> | default = 30s]
 ​
 # HTTP 服务写入超时时间
 [http_server_write_timeout: <duration> | default = 30s]
 ​
 # HTTP 服务空闲超时时间
 [http_server_idle_timeout: <duration> | default = 120s]
 ​
 # 可接收的最大 gRPC 消息大小
 [grpc_server_max_recv_msg_size: <int> | default = 4194304]
 ​
 # 可发送的最大 gRPC 消息大小
 [grpc_server_max_send_msg_size: <int> | default = 4194304]
 ​
 # 对 gRPC 调用的并发流数量的限制 (0 = unlimited)
 [grpc_server_max_concurrent_streams: <int> | default = 100]
 ​
 # 只记录给定严重程度或以上的信息,支持的值:[debug, info, warn, error]
 [log_level: <string> | default = "info"]
 ​
 # 所有 API 路由服务的基本路径(e.g., /v1/).
 [http_path_prefix: <string>]
 ​
 # 目标管理器检测 promtail 可读的标志,如果设置为 false 检查将被忽略
 [health_check_target: <bool> | default = true]

3.根节点-client

client 属性配置了 Promtail 如何连接到 Loki 的实例。

 # Loki 正在监听的 URL,在 Loki 中表示为 http_listen_address 和 http_listen_port
 # 如果 Loki 在微服务模式下运行,这就是 Distributor 的 URL,需要包括 push API 的路径。
 # 例如:http://example.com:3100/loki/api/v1/push
 url: <string>
 ​
 # 默认使用的租户 ID,用于推送日志到 Loki。
 # 如果省略或为空,则会假设 Loki 在单租户模式下运行,不发送 X-Scope-OrgID 头。
 [tenant_id: <string>]
 ​
 # 发送一批日志前的最大等待时间,即使该批次日志数据未满。
 [batchwait: <duration> | default = 1s]
 ​
 # 在向 Loki 发送批处理之前要积累的最大批处理量(以字节为单位)。
 [batchsize: <int> | default = 102400]
 ​
 # 如果使用了 basic auth 认证,则需要配置用户名和密码
 basic_auth:
   [username: <string>]
   [password: <string>]
   # 包含basic auth认证的密码文件
   [password_file: <filename>]
 ​
 # 发送给服务器的 Bearer token
 [bearer_token: <secret>]
 ​
 # 包含 Bearer token 的文件
 [bearer_token_file: <filename>]
 ​
 # 用来连接服务器的 HTTP 代理服务器
 [proxy_url: <string>]
 ​
 # 如果连接到一个 TLS 服务器,配置 TLS 认证方式。
 tls_config:
   # 用来验证服务器的 CA 文件
   [ca_file: <string>]
   # 发送给服务器用于客户端认证的 cert 文件
   [cert_file: <filename>]
   # 发送给服务器用于客户端认证的密钥文件
   [key_file: <filename>]
   # 验证服务器证书中的服务器名称是这个值。
   [server_name: <string>]
   # 如果为 true,则忽略由未知 CA 签署的服务器证书。
   [insecure_skip_verify: <boolean> | default = false]
 ​
 # 配置在请求失败时如何重试对 Loki 的请求。
 # 默认的回退周期为:
 # 0.5s, 1s, 2s, 4s, 8s, 16s, 32s, 64s, 128s, 256s(4.267m)
 # 在日志丢失之前的总时间为511.5s(8.5m)
 backoff_config:
   # 重试之间的初始回退时间
   [min_period: <duration> | default = 500ms]
   # 重试之间的最大回退时间
   [max_period: <duration> | default = 5m]
   # 重试的最大次数
   [max_retries: <int> | default = 10]
 ​
 # 添加到所有发送到 Loki 的日志中的静态标签
 # 使用一个类似于 {"foo": "bar"} 的映射来添加一个 foo 标签,值为 bar
 # 这些也可以从命令行中指定:
 # -client.external-labels=k1=v1,k2=v2
 # (或 --client.external-labels 依赖操作系统)
 # 由命令行提供的标签将应用于所有在 "clients" 部分的配置。
 # 注意:如果标签的键相同,配置文件中定义的值将取代命令行中为特定 client 定义的值
 external_labels:
   [ <labelname>: <labelvalue> ... ]
 ​
 # 等待服务器响应一个请求的最长时间
 [timeout: <duration> | default = 10s]

4.根节点-positions

positions 属性配置了 Promtail 保存文件的位置,表示它已经读到了文件什么程度。当 Promtail 重新启动时需要它,以允许它从中断的地方继续读取日志。

 # positions 文件的路径
 [filename: <string> | default = "/var/log/positions.yaml"]
 ​
 # 更新 positions 文件的周期
 [sync_period: <duration> | default = 10s]
 ​
 # 是否忽略并覆盖被破坏的 positions 文件
 [ignore_invalid_yaml: <boolean> | default = false]

5.根节点-scrape_configs

scrape_configs块配置 Promtail 如何使用指定的发现方法从一系列目标中抓取日志。 Promtail 使用相同的 Prometheus scrape_configs。这意味着如果您已经拥有 Prometheus 实例,则配置将非常相似:

 #在Promtail UI中标识此任务配置的名称。
 job_name: <string>
 ​
 # 描述如何对目标日志进行结构化
 [pipeline_stages: <pipeline_stages>]
 ​
 # 定义给定任务目标的解压缩行为。
 decompression:
   # 是否应该尝试解压缩。
   [enabled: <boolean> | default = false]
 ​
   # 开始解压之前等待的初始延迟。
   # 在压缩完成之前发现压缩文件的场景特别有用。
   [initial_delay: <duration> | default = 0s]
 ​
   # 压缩格式。 支持的格式有:“gz”、“bz2”和“z”。
   [format: <string> | default = ""]
 ​
 # 描述如何从日志中抓取日志。
 [journal: <journal_config>]
 ​
 # 描述应从哪种编码转换抓取的文件。
 [encoding: <iana_encoding_name>]
 ​
 # 描述如何从syslog接收日志。
 [syslog: <syslog_config>]
 ​
 # 描述如何通过 Loki 推送 API 接收日志(例如从其他 Promtails 或 Docker 日志驱动程序)
 [loki_push_api: <loki_push_api_config>]
 ​
 # 描述如何从 Windows 事件日志中抓取日志。
 [windows_events: <windows_events_config>]
 ​
 # 描述如何拉取/接收 Google Cloud Platform (GCP) 日志的配置。
 [gcplog: <gcplog_config>]
 ​
 # 描述如何获取 Azure 事件中心消息的配置。
 [azure_event_hub: <azure_event_hub_config>]
 ​
 # 描述如何通过 Consumer 组从 Kafka 获取日志。
 [kafka: <kafka_config>]
 ​
 # Describes how to receive logs from gelf client.
 [gelf: <gelf_config>]
 ​
 # 描述如何从gelf客户端接收日志。
 [cloudflare: <cloudflare>]
 ​
 # 描述如何从 Heroku LogPlex 漏斗中提取日志的配置。
 [heroku_drain: <heroku_drain>]
 ​
 # 描述如何重新标记目标以确定它们是否应该进行处理。
 relabel_configs:
   - [<relabel_config>]
 ​
 # 要抓取的静态目标
 static_configs:
   - [<static_config>]
 ​
 # 包含要抓取的目标的文件。
 file_sd_configs:
   - [<file_sd_configs>]
 ​
 # 描述如何发现运行在Kubernetes上同一个主机的服务。
 kubernetes_sd_configs:
   - [<kubernetes_sd_config>]
 ​
 # 描述如何使用 Consul Catalog API 来发现consul集群注册到的服务
 consul_sd_configs:
   [ - <consul_sd_config> ... ]
 ​
 # 描述如何使用 Consul Agent API 发现向 consul agent 注册的服务
 # 与 Promtail 在同一主机上运行。
 consulagent_sd_configs:
   [ - <consulagent_sd_config> ... ]
 ​
 # 描述如何使用 Docker 守护进程 API 来发现运行在其上的容器
 # 与 Promtail 相同的主机。
 docker_sd_configs:
   [ - <docker_sd_config> ... ]

5.1 pipeline_stages

管道阶段用于转换日志条目及其标签。发现过程完成后执行管道。该pipeline_stages对象由与下面列出的项目相对应的阶段列表组成。

在大多数情况下,您可以使用regexjson阶段从日志中提取数据。提取的数据被转换为临时Map对象。然后 Promtail 可以使用该数据,例如作用于labels或作作用于output.此外,除了docker和之外的任何其他阶段cri都可以访问提取的数据。

- [
    <docker> |
    <cri> |
    <regex> |
    <json> |
    <template> |
    <match> |
    <timestamp> |
    <output> |
    <labels> |
    <metrics> |
    <tenant> |
    <replace>
  ]

5.1.1 docker

docker阶段解析来自 Docker 容器的日志内容,并通过名称和空对象进行定义:

docker: {}

docker 阶段将匹配并解析以下格式的日志行:

`{"log":"level=info ts=2019-04-30T02:12:41.844179Z caller=filetargetmanager.go:180 msg=\"Adding target\"\n","stream":"stderr","time":"2019-04-30T02:12:41.8443515Z"}`

自动将时间提取到日志时间戳中,流式传输到标签中,并将日志字段提取到输出中,这非常有帮助,因为 docker 以这种方式包装应用程序日志,这将打开它以进一步对日志内容进行管道处理 。

Docker 阶段只是这个定义的一个方便的包装:

- json:
    expressions:
      output: log
      stream: stream
      timestamp: time
- labels:
    stream:
- timestamp:
    source: timestamp
    format: RFC3339Nano
- output:
    source: output

5.1.2 cri

cri 阶段解析来自 CRI 容器的日志内容,并通过名称和空对象进行定义:

cri: {}

CRI 阶段将匹配并解析以下格式的日志行:

2019-01-01T01:00:00.000000001Z stderr P some log message

自动将time时间戳提取到日志中,stream提取到标签中,并将剩余消息提取到输出中,这非常有帮助,因为 CRI 以这种方式包装您的应用程序日志,这将打开它以进一步对日志内容进行管道处理。

CRI 阶段只是此定义的方便包装:

- regex:
    expression: "^(?s)(?P<time>\\S+?) (?P<stream>stdout|stderr) (?P<flags>\\S+?) (?P<content>.*)$"
- labels:
    stream:
- timestamp:
    source: time
    format: RFC3339Nano
- output:
    source: content

5.1.3 regex

regex 阶段采用正则表达式并提取捕获的命名组以在进一步的阶段中使用。

regex:
  # RE2 正则表达式。 每个捕获组都必须命名。
  expression: <string>

  # 从提取的数据中解析的名称。 如果为空,则使用日志消息。
  [source: <string>]

5.1.4 json

json 阶段将日志行解析为 JSON,并采用 JMESPath表达式从 JSON 中提取数据以供后续阶段使用。

json:
  # JMESPath 表达式的键/值对Set。 关键将是提取数据中的键,而表达式将是值,根据源数据评估为 JMESPath。
  expressions:
    [ <string>: <string> ... ]

  # 从提取的数据中解析的名称。 如果为空,则使用日志消息。
  [source: <string>]

5.1.5 template

template阶段使用 Go 的 text/template语言来操作值。

template:
  # 从提取的数据中解析的名称。如果提取数据中的键不存在,则会为其创建一个条目。
  source: <string>

  # 要使用的Go模板字符串。 除了普通模板函数之外,ToLower、ToUpper、Replace、Trim、TrimLeft、TrimRight、TrimPrefix、TrimSuffix 和 TrimSpace 也可用作函数。
  template: <string>

例子:

template:
  source: level
  template: '{{ if eq .Value "WARN" }}{{ Replace .Value "WARN" "OK" -1 }}{{ else }}{{ .Value }}{{ end }}'

5.1.6 match

当日志条目与可配置的LogQL流选择器匹配时,match阶段有条件地执行一组阶段。

match:
  # LogQL 流选择器。
  selector: <string>

  # 管道名称。 定义后,会在 pipeline_duration_seconds 柱状图中创建一个附加标签,其中值使用下划线与 job_name 连接。
  [pipeline_name: <string>]

  # 仅当选择器与日志条目的标签匹配时才嵌套管道阶段集:
  stages:
    - [
        <docker> |
        <cri> |
        <regex>
        <json> |
        <template> |
        <match> |
        <timestamp> |
        <output> |
        <labels> |
        <metrics>
      ]

5.1.7 timestamp

timestamp阶段解析提取的映射中的数据并覆盖 Loki 存储的日志的最终时间值。如果此阶段不存在,Promtail 会将日志条目的时间戳与读取日志条目的时间相关联。

timestamp:
  # 提取数据中用于时间戳的名称。
  source: <string>

  # 判断如何解析时间字符串。 可以按名称使用预定义格式:[ANSIC UnixDate RubyDate RFC822 RFC822Z RFC850 RFC1123 RFC1123Z RFC3339 RFC3339Nano Unix UnixMs UnixUs UnixNs]。
  format: <string>

  # IANA 时区数据库字符串。
  [location: <string>]

5.1.8 output

output阶段从提取的映射中获取数据并设置将由 Loki 存储的日志条目的内容。

output:
  # 用于日志条目的提取数据的名称。
  source: <string>

5.1.9 labels

labels阶段从提取的地图中获取数据,并在将发送给 Loki 的日志条目上设置附加标签。

labels:
  # Key 是必需的,并且将创建的标签的名称。Value 是可选的,将是提取数据的名称,其值将用作标签的值。 如果为空,则该值将被推断为与键相同。
  [ <string>: [<string>] ... ]

5.1.10 metrics

metrics阶段允许从提取的数据中定义指标。

创建的指标不会推送到 Loki,而是通过 Promtail 的 /metrics端点公开。 Prometheus 应配置为抓取 Promtail,以便能够检索此阶段配置的指标。

# 一个映射,其中键是指标的名称,值是特定的指标类型。
metrics:
  [<string>: [ <counter> | <gauge> | <histogram> ] ...]

5.1.10.1 counter

定义一个计数器指标,其值只会增加。

# 指标类型。必须为 Counter.
type: Counter

# 指标描述
[description: <string>]

# 提取的数据映射中用于指标的键,如果不存在,则默认为指标名称。
[source: <string>]

config:
  # 过滤源数据,并且仅在目标值与提供的字符串完全匹配时才更改指标。 如果不存在,则所有数据都将匹配。
  [value: <string>]

  # 必须是“inc”或“add”(不区分大小写)。 如果选择 inc,则对于收到的通过过滤器的每个日志行,度量值将增加 1。 如果选择添加,则提取的值必须可转换为正浮点数,并且其值将添加到指标中。
  action: <string>

5.1.10.2 gauge

定义一个计量指标,其值可以上升或下降。

#  指标类型。必须为 Gauge.
type: Gauge

# 指标描述
[description: <string>]

# 提取的数据映射中用于指标的键,如果不存在则默认为指标名称。
[source: <string>]

config:
  # 过滤源数据,并且仅在目标值与提供的字符串完全匹配时才更改指标。如果不存在,则所有数据都将匹配。
  [value: <string>]

  # 必须是“set”、“inc”、“dec”、“add”或“sub”。 如果选择 add、set 或 sub,则提取的值必须可转换为正浮点数。 inc 和 dec 将分别将指标值增加或减少 1。
  action: <string>

5.1.10.3 histogram

定义一个柱状图指标,其值是分组的。

# 指标类型。必须为 Histogram(直方图)。
type: Histogram

# 指标描述
[description: <string>]

# 提取的数据映射中用于指标的键,如果不存在则默认为指标名称。
[source: <string>]

config:
  # 过滤源数据,并且仅在目标值与提供的字符串完全匹配时才更改指标。如果不存在,则所有数据都将匹配。
  [value: <string>]

  # 必须是“inc”或“add”(不区分大小写)。 如果选择 inc,则对于收到的通过过滤器的每个日志行,度量值将增加 1。 如果选择add,则提取的值必须可转换为正浮点数,并且其值将添加到指标中。
  action: <string>

  # 保存用于存储指标的所有数字。
  buckets:
    - <int>

5.1.11 tenant

tenant阶段是一个操作阶段,它为日志条目设置租户 ID,从提取的数据映射中的字段中选取它。

tenant:
  # label、source或value配置选项中的一个是必需的,但不是全部(它们是互斥的)。
  
  # 标签中的名称,其值应设置为租户 ID。
  [ label: <string> ]

  # 提取数据中的名称,其值应设置为租户 ID。
  [ source: <string> ]

  # 执行此阶段时用于设置租户ID的值。 当此阶段包含在带有“match”的条件管道中时很有用。
  [ value: <string> ]

5.1.12 replace

replace阶段是一个解析阶段,它使用正则表达式解析日志行并替换日志行。

replace:
  # RE2 正则表达式。 每个命名捕获组都将添加到提取中。每个捕获组和命名捕获组将替换为“replace”中给出的值
  expression: <string>

  # 从提取的数据中解析的名称。如果为空,则使用日志消息。替换的值将分配为source key
  [source: <string>]

  # 捕获的组将替换为的值。捕获的组或命名的捕获组将替换为该值,并且日志行将替换为新的替换值。 空值将从日志行中删除捕获的组。
  [replace: <string>]