菜单
开源 RSS

告警与记录规则

Grafana Loki 包含一个名为 ruler 的组件。ruler 负责持续评估一组可配置的查询,并根据结果执行操作。

此示例配置从本地磁盘获取规则。

Ruler 存储提供了更多详细信息。

yaml
ruler:
  storage:
    type: local
    local:
      directory: /tmp/rules
  rule_path: /tmp/scratch
  alertmanager_url: https://
  ring:
    kvstore:
      store: inmemory
  enable_api: true

我们支持两种规则:告警规则和记录规则。

告警规则

我们支持兼容 Prometheus 的告警规则。引自 Prometheus 文档:

告警规则允许您基于 Prometheus 表达式语言表达式定义告警条件,并将触发的告警通知发送给外部服务。

Loki 告警规则与此完全相同,只是表达式使用 LogQL。

示例

一个完整的规则文件示例

yaml
groups:
  - name: should_fire
    rules:
      - alert: HighPercentageError
        expr: |
          sum(rate({app="foo", env="production"} |= "error" [5m])) by (job)
            /
          sum(rate({app="foo", env="production"}[5m])) by (job)
            > 0.05
        for: 10m
        labels:
          severity: page
        annotations:
          summary: High request latency
  - name: credentials_leak
    rules:
      - alert: http-credentials-leaked
        annotations:
          message: "{{ $labels.job }} is leaking http basic auth credentials."
        expr: 'sum by (cluster, job, pod) (count_over_time({namespace="prod"} |~ "http(s?)://(\\w+):(\\w+)@" [5m]) > 0)'
        for: 10m
        labels:
          severity: critical

记录规则

我们支持兼容 Prometheus 的记录规则。引自 Prometheus 文档:

记录规则允许您预先计算常用或计算成本高的表达式,并将结果保存为一组新的时间序列。

查询预计算结果通常比每次需要时执行原始表达式要快得多。这对于仪表盘尤其有用,因为仪表盘每次刷新都需要重复查询相同的表达式。

Loki 允许您运行指标查询以处理您的日志,这意味着您可以从日志中得出数值聚合,例如从 NGINX 访问日志中计算随时间变化的请求数量。

示例

yaml
name: NginxRules
interval: 1m
rules:
  - record: nginx:requests:rate1m
    expr: |
      sum(
        rate({container="nginx"}[1m])
      )
    labels:
      cluster: "us-central1"

这个查询(expr)将每 1 分钟(interval)执行一次,其结果将存储在我们定义的指标名称(record)中。这个名为 nginx:requests:rate1m 的指标现在可以发送到 Prometheus,在那里它将像其他任何指标一样被存储。

限制告警和记录规则样本

类似于Prometheus,您可以为告警规则生成的告警和记录规则生成的样本配置一个限制。此限制可以按组配置。使用限制可以防止错误的规则生成大量告警或记录样本。当超出限制时,规则生成的所有记录样本将被丢弃,如果是告警规则,则该规则的所有告警(活动的、待处理的或非活动的)都将被清除。此事件将记录为评估错误,并且规则健康状态将被设置为 err。限制的默认值为 0,表示没有限制。

示例

这里是一个规则组及其配置的限制示例。

yaml
groups:
  - name: production_rules
    limit: 10
    interval: 1m
    rules:
      - alert: HighPercentageError
        expr: |
          sum(rate({app="foo", env="production"} |= "error" [5m])) by (job)
            /
          sum(rate({app="foo", env="production"}[5m])) by (job)
            > 0.05
        for: 10m
        labels:
          severity: page
        annotations:
          summary: High request latency
      - record: nginx:requests:rate1m
        expr: |
          sum(
            rate({container="nginx"}[1m])
          )
        labels:
          cluster: "us-central1"

远程写入

使用记录规则,您可以按一定间隔持续运行这些指标查询,并将结果指标写入兼容 Prometheus 的远程写入端点。它们从日志条目生成 Prometheus 指标。

在撰写本文时,支持此功能的兼容后端有:

这里是一个将数据发送到本地 Prometheus 实例的远程写入配置示例。

yaml
ruler:
  ... other settings ...

  remote_write:
    enabled: true
    client:
      url: https://:9090/api/v1/write

更多配置选项请参见ruler

操作

请参阅记录规则页面。

用例

Ruler 与 Prometheus 的兼容性进一步强调了指标和日志的结合。对于希望开始基于日志使用指标和告警,或想知道这为何有用的人来说,我们认为以下是一些非常合适的用例。

黑盒监控

我们并不总是控制运行应用程序的源代码。负载均衡器和许多其他组件,无论是开源的还是第三方的闭源组件,都支持我们的应用程序,但它们不暴露我们想要的指标。有些甚至完全不暴露任何指标。Loki 告警和记录规则可以从日志生成指标并对系统状态进行告警,从而利用日志将这些组件纳入我们的可观测性堆栈。这是一种非常强大的方法,可以将高级可观测性引入传统架构。

事件告警

有时您想知道是否发生了 任何 特定事件的实例。基于日志的告警是处理这种情况的好方法,例如查找泄露的身份验证凭据示例

yaml
- name: credentials_leak
  rules:
    - alert: http-credentials-leaked
      annotations:
        message: "{{ $labels.job }} is leaking http basic auth credentials."
      expr: 'sum by (cluster, job, pod) (count_over_time({namespace="prod"} |~ "http(s?)://(\\w+):(\\w+)@" [5m]) > 0)'
      for: 10m
      labels:
        severity: critical

高基数源告警

另一个很好的用例是对高基数源进行告警。这些是难以/昂贵地记录为指标的数据,因为潜在的标签集非常庞大。一个很好的例子是在像 Loki 这样的多租户系统中按租户进行告警。这通常是在希望获得按租户指标和随之而来的基数爆炸(将单个 tenant 标签添加到现有的 Prometheus 指标会使其基数增加租户数量)之间进行的权衡。

在 LogQL 中创建这些告警很吸引人,因为这些指标可以在 查询时 提取,这意味着我们不会在指标存储中遭受基数爆炸的影响。

注意

例如,我们可以使用 LogQL v2 来帮助 Loki 监控 自身,当特定租户的查询耗时超过 10 秒时向我们发出告警!为此,我们将使用以下查询:sum by (org_id) (rate({job="loki-prod/query-frontend"} |= "metrics.go" | logfmt | duration > 10s [1m])

与 Ruler 交互

Lokitool

由于规则文件与 Prometheus 规则文件相同,我们可以通过 lokitool 与 Loki Ruler 交互。

注意

lokitool 旨在针对多租户 Loki 运行。命令需要设置 --id= 标志为 Loki 实例 ID,或设置环境变量 LOKI_TENANT_ID。如果 Loki 运行在单租户模式下,所需的 ID 为 fake

下面包含一个示例工作流程

sh
# lint the rules.yaml file ensuring it's valid and reformatting it if necessary
lokitool rules lint ./output/rules.yaml

# diff rules against the currently managed ruleset in Loki
lokitool rules diff --rule-dirs=./output

# ensure the remote ruleset matches your local ruleset, creating/updating/deleting remote rules which differ from your local specification.
lokitool rules sync --rule-dirs=./output

# print the remote ruleset
lokitool rules print

Terraform

通过用于 Loki 的 Terraform 提供者,您可以使用 Terraform HCL 格式管理告警和记录规则。

tf
terraform {
  required_providers {
    loki = {
      source = "fgouteroux/loki"
    }
  }
}

# Provider config
provider "loki" {
  uri = "http://127.0.0.1:3100"
  org_id = "mytenant"
}

# Create an alert rule
resource "loki_rule_group_alerting" "test" {
  name      = "test1"
  namespace = "namespace1"
  rule {
    alert       = "HighPercentageError"
    expr        = <<EOT
sum(rate({app="foo", env="production"} |= "error" [5m])) by (job)
  /
sum(rate({app="foo", env="production"}[5m])) by (job)
  > 0.05
EOT
    for         = "10m"
    labels      = {
      severity = "warning"
    }
    annotations = {
      summary = "High request latency"
    }
  }
}

# Create a recording rule
resource "loki_rule_group_recording" "test" {
  name      = "test1"
  namespace = "namespace1"
  rule {
    expr   = "sum by (job) (http_inprogress_requests)"
    record = "job:http_inprogress_requests:sum"
  }
}

Cortex rules action

这个Cortex rules action 将 Loki 作为后端引入,这对于在 CI/CD 流水线中管理规则非常方便。它可用于在本地目录和远程 Loki 实例之间对规则进行 linting、diff 和同步。

yaml
- name: Lint Loki rules
  uses: grafana/cortex-rules-action@master
  env:
    ACTION: check
    RULES_DIR: <source_dir_of_rules> # Example: logs/recording_rules/,logs/alerts/
    BACKEND: loki

- name: Deploy rules to Loki staging
  uses: grafana/cortex-rules-action@master
  env:
    CORTEX_ADDRESS: <loki_ingress_addr>
    CORTEX_TENANT_ID: fake
    ACTION: sync
    RULES_DIR: <source_dir_of_rules> # Example: logs/recording_rules/,logs/alerts/
    BACKEND: loki

调度和最佳实践

扩展 Ruler 的一种选择是横向扩展它。然而,在运行多个 Ruler 实例时,它们需要协调以确定哪个实例将评估哪个规则。类似于 ingesters,Rulers 建立一个哈希环来划分评估规则的职责。

所有可能的配置完整列在配置文档中,但为了在多个 Ruler 之间分片规则,必须通过标志 (-ruler.enable-api) 或配置文件参数启用规则 API。其次,Ruler 需要配置自己的环。从那里开始,Rulers 将自动进行规则的分片和分配处理。与 ingesters 不同,Rulers 不会移交职责:每次将 Ruler 添加到或从环中移除时,所有规则都会随机重新分片。

一个完整的启用分片的 Ruler 示例是

yaml
ruler:
  alertmanager_url: <alertmanager_endpoint>
  enable_alertmanager_v2: true # true by default since Loki 3.2.0
  enable_api: true
  enable_sharding: true
  ring:
    kvstore:
      consul:
        host: consul.loki-dev.svc.cluster.local:8500
      store: consul
  rule_path: /tmp/rules
  storage:
    gcs:
      bucket_name: <loki-rules-bucket>

Ruler 存储

Ruler 支持以下存储类型:azure, gcs, s3, swift, coslocal。大多数类型的存储与分片 Ruler 配置以显而易见的方式协同工作,即配置所有 Ruler 使用相同的后端。

本地实现从本地文件系统读取规则文件。这是一个只读后端,不支持通过Ruler API进行规则的创建和删除。尽管它读取本地文件系统,但如果操作员注意将相同的规则加载到每个 Ruler 上,这种方法仍然可以用于分片 Ruler 配置。例如,这可以通过将一个Kubernetes ConfigMap挂载到每个 Ruler Pod 上来实现。

一个典型的本地配置可能看起来像这样

  -ruler.storage.type=local
  -ruler.storage.local.directory=/tmp/loki/rules

使用上述配置,Ruler 将期望以下布局

/tmp/loki/rules/<tenant id>/rules1.yaml
                           /rules2.yaml

Yaml 文件应兼容 Prometheus,但包含本文档开头指定的 LogQL 表达式。

远程规则评估

在较大的部署和复杂的规则下,在本地评估模式下运行 Ruler 会导致结果与您在 Grafana 中看到的结果不一致或不完整的问题。为了解决这个问题,请使用远程评估模式针对查询前端评估规则。更详细的解释可以在可伸缩性文档中找到。

未来改进

为了提高此服务的健壮性,将有几项改进。顺序不分先后:

  • 后端指标存储适配器,用于生成的告警规则数据。

杂项详情:指标后端 vs 内存

目前,Loki Ruler 与后备的 Prometheus 存储是解耦的。通常,评估规则的结果以及告警状态的历史都存储为时间序列。Loki 无法存储/检索这些数据,因此它独立于 Prometheus 等运行。作为一种变通方法,Loki 在内存中保留了一个小型存储,其目的是在重新调度或重新分片 Ruler 时懒加载过去的评估结果。将来,Loki 将支持可选的指标后端,允许存储这些指标以用于审计和性能优化。