集中式日志管理实践:ELK 与 Loki 的选型与架构设计
日志不是"写进文件就行",而是"出了问题能快速找到原因"。本文从日志采集、存储、查询三个环节出发,讨论 ELK(Elasticsearch + Logstash + Kibana)和 Loki + Grafana 两种主流方案的架构差异和选型建议——适合正在搭建或优化日志系统的后端开发者和运维工程师。
先说结论:日志系统的核心不是”存了多少”,而是”能多快找到”
很多团队搭建日志系统时只关注”能不能把日志收集起来”,忽略了”出问题时能不能快速定位”。一个存了几个 TB 日志但查询要等几分钟的系统,还不如一个只存了 7 天但秒级响应的系统。
1. 方案对比
ELK(Elasticsearch + Logstash + Kibana)
应用 → Filebeat → Logstash → Elasticsearch → Kibana
- 对日志内容建立全文索引,搜索灵活
- 存储成本高(需要大量磁盘和内存)
- 适合需要全文搜索和复杂聚合分析的场景
Loki + Grafana
应用 → Promtail → Loki → Grafana
- 只对标签建立索引,不索引日志内容
- 存储成本低
- 适合按标签过滤查询的场景
选型建议
| 维度 | ELK | Loki |
|---|---|---|
| 查询灵活性 | 全文搜索,任意字段 | 基于标签,有限内容搜索 |
| 存储成本 | 高 | 低 |
| 查询速度 | 快(全文索引) | 快(标签过滤) |
| 运维复杂度 | 高(3 个组件) | 低(1 个组件 + Grafana) |
| 适合场景 | 需要全文搜索、复杂分析 | 按标签过滤、K8s 环境 |
2. 日志分级
级别定义
const logLevels = {
ERROR: '记录导致功能不可用的错误,需要立即处理',
WARN: '记录潜在问题,不需要立即处理但需要关注',
INFO: '记录关键操作,如用户登录、订单创建',
DEBUG: '记录详细调试信息,只在排查问题时开启',
};
生产环境配置
// 生产环境:只记录 WARN 及以上
const logger = winston.createLogger({
level: 'warn',
transports: [new winston.transports.Console()],
});
3. 日志内容规范
结构化日志
// ❌ 非结构化
"用户登录失败"
// ✅ 结构化
{
"timestamp": "2026-07-21T10:00:00Z",
"level": "WARN",
"service": "auth-service",
"requestId": "req-123",
"userId": "user-456",
"message": "用户登录失败",
"reason": "密码错误",
"duration_ms": 120
}
必填字段
| 字段 | 说明 | 示例 |
|---|---|---|
| timestamp | 事件时间 | 2026-07-21T10:00:00Z |
| level | 日志级别 | ERROR, WARN, INFO, DEBUG |
| service | 服务名 | auth-service |
| requestId | 请求追踪 ID | req-abc123 |
| message | 描述 | 用户登录失败 |
| duration_ms | 耗时(毫秒) | 120 |
4. 日志查询
常见查询模式
# 查询某个服务的所有错误
{service="auth-service"} |= "ERROR"
# 查询某个请求的完整链路
{requestId="req-abc123"}
# 查询某个时间段内的错误
{level="ERROR"} | logfmt | duration_ms > 1000
总结
| 环节 | 核心原则 | 常见错误 |
|---|---|---|
| 方案选型 | 按查询需求选,不是按名气选 | 不管量多大都上 ELK |
| 日志级别 | 生产环境只记 WARN 以上 | 生产环境开 DEBUG |
| 日志格式 | 结构化 JSON,包含必填字段 | 字符串拼接,无法解析 |
| 查询 | 用 requestId 串联请求链路 | 没有追踪 ID,查不到上下文 |
日志系统的价值不在于”存了多少日志”,而在于”出问题时能多快找到原因”。 一个设计良好的日志系统,应该让排查问题的过程从”大海捞针”变成”按图索骥”。
需要日志系统设计或运维服务?联系我们,说清你的服务规模与查询需求,24 小时内回可行性。
常见问题
ELK 和 Loki 的核心区别是什么?
ELK 对日志内容建立全文索引,搜索速度快,但存储成本高(需要大量磁盘和内存)。Loki 只对日志的元数据(标签)建立索引,不索引日志内容,存储成本低,但复杂查询(如全文搜索)的性能不如 ELK。选型建议:如果日志量很大(每天几百 GB)且主要查询是按标签过滤,选 Loki;如果需要全文搜索和复杂聚合分析,选 ELK。
日志应该保留多久?
取决于业务需求。建议分层策略:热存储(快速查询)保留 7 天,温存储(可查询但较慢)保留 30 天,冷存储(归档,需要时恢复)保留 1 年。按重要程度:安全日志保留 1 年以上,业务日志保留 30-90 天,调试日志保留 7 天。
日志采集用什么工具?
Filebeat(ELK 生态)和 Promtail(Loki 生态)是最常用的日志采集 Agent。两者的共同特点是:轻量级(占用资源少)、支持多种输入源(文件、Stdout、Syslog)、支持自动发现(新创建的日志文件自动开始采集)。如果你的应用跑在 Docker 或 K8s 中,优先采集容器的 Stdout 日志,不要写日志文件。
日志太多会影响应用性能吗?
会。日志写得太频繁(尤其是每个请求写几十行调试日志),磁盘 I/O 会成为瓶颈。建议:① 生产环境只记录 WARN 和 ERROR 级别的日志,INFO 用于关键操作,DEBUG 只在排查问题时开启;② 使用异步日志记录(如 Winston 的异步传输),不阻塞主流程;③ 设置日志轮转,避免单个日志文件过大。