2. Loki 基础回顾:Loki 日志存储模型、LogQL 查询语言核心概念
在深入变更窗口告警路由与模板通信之前,必须重新夯实 Loki 的两大基石:日志存储模型与LogQL 查询语言。Loki 的设计哲学与 Prometheus 一脉相承——通过标签索引代替全文检索,从而在成本与性能之间取得极致平衡。本节将拆解其存储架构的核心抽象,并梳理 LogQL 中与告警路由最相关的查询模式。
2.1 Loki 日志存储模型:从流到块
Loki 不解析日志内容,而是将日志视为不可变的字节流,按标签(Labels)组织成日志流(Log Stream)。每个日志流由一组唯一的标签键值对标识,同一流内的日志按时间戳递增排列。
核心存储层次:
日志流(Stream) → Chunk(块) → Index(索引)
标签决定流归属,Chunk 是压缩后的日志数据块,Index 仅存储标签与 Chunk 的映射关系。
日志流(Stream) → Chunk(块) → Index(索引)
标签决定流归属,Chunk 是压缩后的日志数据块,Index 仅存储标签与 Chunk 的映射关系。
下表总结了存储模型中各层级的职责与关键属性:
| 层级 | 职责 | 关键属性 | 告警关联 |
|---|---|---|---|
| 日志流 | 标签组合的唯一标识 | 标签基数、流数量 | 告警规则按流聚合 |
| Chunk | 压缩存储日志行 | 压缩算法、大小、时间范围 | 影响查询扫描量 |
| Index | 标签 → Chunk 映射 | 倒排索引、布隆过滤器 | 决定查询速度 |
| Ingester | 内存中构建 Chunk | Flush 策略、副本因子 | 影响实时告警延迟 |
SRE 视角: 告警路由的标签选择器必须与日志流的标签设计对齐。如果变更窗口的日志缺少
deploy_id 或 change_window 标签,LogQL 将无法高效过滤,导致查询扫描大量无关 Chunk。
2.2 LogQL 查询语言核心概念
LogQL 是 Loki 的查询语言,语法上兼容 PromQL 的标签选择器,并扩展了日志行过滤与指标聚合能力。对于变更窗口告警,我们最关注两类查询:日志流选择器和指标查询(Metric Queries)。
2.2.1 日志流选择器(Log Stream Selector)
所有 LogQL 查询必须以日志流选择器开头,用于限定查询的日志流范围。语法与 Prometheus 标签选择器完全一致:
{job="api-server", env="prod", change_window="true"}
支持的操作符包括 =、!=、=~(正则匹配)、!~(正则排除)。
告警路由陷阱: 如果变更窗口的标签值包含特殊字符(如
deploy_id="v2.3.1-rc1"),正则选择器必须正确转义。建议在日志采集侧使用 结构化标签,避免在 LogQL 中做复杂正则匹配。
2.2.2 日志行过滤(Line Filter Expression)
在流选择器之后,可以使用管道操作符 | 对日志内容进行过滤:
{job="api-server", change_window="true"} |= "ERROR" | json
常用过滤操作符:
|= "pattern"— 包含子串!= "pattern"— 不包含子串|~ "regex"— 正则匹配!~ "regex"— 正则排除| json— 解析 JSON 日志行,提取字段| logfmt— 解析 logfmt 格式日志
2.2.3 指标查询(Metric Queries)—— 告警的核心
告警规则必须使用指标查询将日志事件转化为可聚合的时序数据。Loki 提供两类指标函数:
| 函数类别 | 函数 | 含义 | 告警场景示例 |
|---|---|---|---|
| 计数 | rate() |
每秒日志行速率 | 错误率突增 |
count_over_time() |
指定时间窗口内的日志行总数 | 变更后错误总数阈值 | |
| 标签值 | avg_over_time() |
提取数值字段的平均值 | 平均响应时间 |
max_over_time() |
提取数值字段的最大值 | 峰值延迟告警 | |
| 存在性 | absent_over_time() |
时间窗口内无日志则返回 1 | 变更后服务静默 |
一个完整的告警 LogQL 示例:
# 变更窗口内 5 分钟错误日志速率超过 10/s 触发告警
rate(
{job="api-server", change_window="true"}
|= "ERROR"
| json
[5m]
) > 10
性能建议: 在
rate() 或 count_over_time() 之前,尽量使用 |= 或 | json 提前过滤掉无关日志行。这能显著减少 Loki 需要扫描的 Chunk 数量,降低告警延迟。
2.3 标签设计对告警路由的影响
Loki 的标签设计直接决定了告警路由的灵活性与性能。以下是变更窗口场景下的标签设计原则:
- 基数控制: 避免将高基数字段(如
request_id、user_ip)设为标签,应放在日志内容中通过| json提取。 - 窗口标识: 必须包含
change_window或deploy_id等标签,使告警规则能精确限定变更范围。 - 环境与服务:
job、env、service是标准标签,用于告警路由的粗粒度分组。 - 结构化解析: 推荐在采集端使用
json或logfmt解析,避免在 LogQL 中重复解析开销。
最佳实践: 在变更窗口期间,为所有相关 Pod 注入一个临时标签
change_window="true",并在变更结束后移除。告警规则只需在 LogQL 流选择器中加入该标签,即可实现变更期间告警的自动隔离。