日志平台:采集、存储与 SLO 告警
日志平台的目标是以可控成本支持排障、审计和关联分析;告警的目标是发现用户可感知的风险,而不是对每条 ERROR 日志做出反应。本文给出当前可维护的采集、存储和告警基线。
目录
| 章节 | 说明 |
|---|---|
| 架构选择 | Elastic、Loki 与 OpenTelemetry Collector 的适用边界 |
| 采集与缓冲 | Agent、Collector、Kafka 的决策条件 |
| 结构化日志的交付基线 | Google Cloud 实践抽象出的可移植要求 |
| 索引与标签策略 | Schema、基数和保留期 |
| Elastic 生命周期示例 | Data stream 和 ILM 的最小模板 |
| 告警:指标优先,日志辅助 | SLO、症状告警与日志驱动检测 |
| 运行检查清单 | 上线前后应验证的事项 |
架构选择
| 方案 | 优势 | 代价与限制 | 适用场景 |
|---|---|---|---|
| Elastic Stack / Elastic Cloud | 全文检索、聚合、ECS 生态 | 索引与容量规划成本高 | 复杂日志分析、审计检索 |
| Loki + Grafana | 存储成本低、与 Grafana 监控协同 | 主要索引 label,不能无节制地给字段建标签 | 云原生日志、按服务/环境排障 |
| OpenTelemetry Collector + 后端 | 统一接收、处理、路由 logs/metrics/traces | 仍需选择存储和治理策略 | 多语言、多后端或逐步迁移场景 |
Loki 侧推荐 Grafana Alloy 或其他仍受支持的 agent;Promtail 已在 2026-03-02 结束生命周期,不应再作为新部署方案。Grafana 官方说明
采集与缓冲
flowchart LR
A["应用 JSON stdout / 文件"] --> B["Agent 或 OTel Collector"]
B --> C{"是否需要解耦与重放?"}
C -- 是 --> D["Kafka / 持久队列"] --> E["Collector / 处理器"]
C -- 否 --> E
E --> F["Elastic / Loki / 对象存储"]
Kafka 不是“高流量必选项”。在以下情况再引入:下游可能长时间不可用、需要削峰/重放、多个消费者共享事件,或业务明确要求更强的丢失控制。否则,直接由 Agent/Collector 批处理、重试、限流并写后端通常更简单。
采集器选择关注:资源限制、Kubernetes 元数据、处理能力、配置治理与供应商支持,不要把某个版本的内存数字当成选型结论。对新方案优先评估 Alloy、OpenTelemetry Collector、Elastic Agent、Fluent Bit 或 Vector。
结构化日志的交付基线
Google Cloud Logging 的实践表明:单行 JSON 能被直接作为结构化 payload 解析和按字段查询;在容器运行时,将 JSON 写到 stdout 可由集成 agent 采集。这个做法可迁移到任意日志后端,但不要把云厂商特有字段当作团队的唯一 Schema。Google Cloud Structured Logging
每个服务上线前至少验证:
- 一行一个 JSON 事件:禁止多行拼装和非受控的文本前缀;异常堆栈使用 encoder 的 JSON 字段。
- 可查询的固定字段:时间、严重程度、
service.name、环境、trace_id、事件名齐全;在平台实际执行一次字段查询。 - 从告警到上下文:告警携带 dashboard、trace 查询和日志查询链接;而不是让 on-call 从机器名开始猜。
- 最小权限:运行日志、审计日志分 bucket/index/view 授权;敏感字段另设字段级脱敏或不可见策略。
- 可验证保留与删除:按数据分级配置 retention、归档和删除,定期演练查询、恢复和权限回收。
索引与标签策略
所有服务必须遵循 日志体系总览 的统一 Schema。建议索引/标签策略如下:
| 字段 | Elastic 映射建议 | Loki label 建议 |
|---|---|---|
service.name、环境、集群、日志级别 | keyword | 可作为低基数 label |
trace_id、span_id、request_id | keyword | 不作为 label,解析后或正文查询 |
biz.id、user.id | keyword,按访问权限控制 | 不作为 label |
message、error.stack_trace | text / 受控存储 | 正文;必要时解析字段 |
索引与标签一旦接受高基数值,会使查询、内存和成本失控。字段的保留期也应按日志类型分层:短期运行日志、较长期审计记录、归档对象存储,均以安全/合规要求为准。
Elastic 生命周期示例
生产环境优先使用 data stream 与 component template;分片数、rollover 阈值、冷热层时间必须按实际数据量和节点规模压测后设置,以下只是结构示例。
PUT _index_template/app-logs
{
"index_patterns": ["logs-app-*"],
"data_stream": {},
"template": {
"mappings": {
"properties": {
"@timestamp": { "type": "date" },
"log.level": { "type": "keyword" },
"service.name": { "type": "keyword" },
"trace_id": { "type": "keyword" },
"message": { "type": "match_only_text" }
}
}
}
}
PUT _ilm/policy/logs-app-policy
{
"policy": {
"phases": {
"hot": { "actions": { "rollover": { "max_primary_shard_size": "30gb", "max_age": "1d" } } },
"warm": { "min_age": "7d", "actions": { "forcemerge": { "max_num_segments": 1 } } },
"delete": { "min_age": "30d", "actions": { "delete": {} } }
}
}
}
不要使用已废弃的 freeze action;需要低成本长留存时评估冷/冻数据层与 searchable snapshots。当前可用动作以 Elasticsearch ILM 文档 为准。
告警:指标优先,日志辅助
用户可感知的错误率、延迟和可用性应基于 metrics 与 SLO,而非 ERROR 日志数 / 总日志数:后者会被日志级别、采样和调试输出改变,不能代表服务成功率。
| 信号 | 例子 | 处理方式 |
|---|---|---|
| 症状告警 | 5xx 比例或关键支付失败率超过 SLO 的燃尽阈值 | Page;使用多窗口、多燃尽率规则 |
| 性能退化 | P95 延迟持续超目标 | Page 或 ticket,取决于 SLO 影响 |
| 日志驱动异常 | payment.failed 中某稳定 error.code 激增 | 触发告警并附带日志查询链接 |
| 采集健康 | 某服务日志量突然归零、collector 丢弃率上升 | 作为平台告警,避免误判为业务成功 |
降噪机制应包括持续窗口、分组、去重、依赖抑制、发布静默和 runbook。每条 Page 必须明确:影响面、阈值理由、负责人、排障链接和恢复条件。日志用于诊断与检测特定事件,不能替代请求/交易指标。
对于 99.9% 可用性 SLO,可将 Google SRE 的多窗口、多燃尽率作为起始模板,再按业务验证:例如 Page 可分别检查 1h + 5m 的 14.4 倍燃尽率,以及 6h + 30m 的 6 倍燃尽率;Ticket 检查 3d + 6h 的 1 倍燃尽率。短窗口通常约为长窗口的 1/12。它们不是通用阈值,必须以自身 SLO、流量和演练结果调整。Google SRE Workbook — Alerting on SLOs
运行检查清单
- JSON 日志可被解析,字段与 Schema 校验一致,敏感字段脱敏。
- Collector 在后端短暂故障时的队列、重试、丢弃策略已压测并可观测。
trace_id可在日志、指标 exemplars 和追踪后端互相跳转。- 索引模板、生命周期、容量告警和恢复演练已在非生产环境验证。
- 每条高优告警有 SLO 依据、分组抑制、owner 与 runbook;定期复盘误报和漏报。
参考资料
评论 (0)