服务器日志太多看不过来?我用 Loki + Promtail + Grafana 搭了一套日志系统,少踩了几个坑
我服务器上跑着六七个服务,Nginx、Spring Boot、Redis、MySQL,还有几个自己写的小项目。出问题的时候,查日志是最头疼的事。
之前一直用 tail -f 加 grep 对付,但问题是:第一,日志散落在不同目录,出问题不知道先看哪个;第二,历史日志要找半年前的错误,得翻一堆按天切割的 log 文件;第三——也是最烦的——凌晨三点服务挂了,等你早上起来查,那段时间的日志可能已经被 logrotate 转走了。
ElasticSearch 那套太重了,单台 2C4G 的服务器跑不动。后来试了 Grafana Loki,意外地顺滑——内存占用不到 200MB,查询速度足够快,而且跟我已经在用的 Grafana(监控面板)无缝集成。
下面把我实际部署的过程记下来,包括踩过的几个坑。
Loki + Promtail + Grafana 是什么关系
- Promtail 是日志采集端,装在每台服务器上,尾巴一样跟在日志文件后面,把增量日志推给 Loki
- Loki 是日志存储和查询引擎,不索引全文(跟 ES 不一样),只索引标签(labels),大幅降低存储开销
- Grafana 是可视化前端,你已经在用它看 Prometheus 指标的话,加一个 Loki 数据源就能直接查日志
架构长这样:
你的服务器 → Promtail → Loki → Grafana
(多台也行) (推日志) (存日志) (查日志)
Docker Compose 一把梭
我用 docker-compose 把 Loki 和 Grafana 跑在同一台机器上,Promtail 装在生产服务器上。
先建目录结构:
mkdir -p /opt/loki/{config,data}
mkdir -p /opt/promtail/config
Loki 配置
/opt/loki/config/loki-config.yaml:
auth_enabled: false
server:
http_listen_port: 3100
common:
path_prefix: /loki
storage:
filesystem:
chunks_directory: /loki/chunks
rules_directory: /loki/rules
replication_factor: 1
ring:
instance_addr: 127.0.0.1
kvstore:
store: inmemory
schema_config:
configs:
- from: 2024-01-01
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
注意 schema: v13 和 store: tsdb——这是 Loki 3.x 的默认推荐。网上很多教程还在用 boltdb-shipper + v11 schema,那个是 2.x 时代的,3.x 改了。
Docker Compose
/opt/loki/docker-compose.yml:
version: "3"
services:
loki:
image: grafana/loki:3.1.0
container_name: loki
ports:
- "3100:3100"
volumes:
- ./config/loki-config.yaml:/etc/loki/local-config.yaml
- ./data:/loki
command: -config.file=/etc/loki/local-config.yaml
restart: unless-stopped
grafana:
image: grafana/grafana:11.0.0
container_name: grafana
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=改一个强密码
volumes:
- grafana-data:/var/lib/grafana
restart: unless-stopped
volumes:
grafana-data:
docker-compose up -d 跑起来。
Promtail 配置
在生产服务器上,不需要 Docker,直接二进制跑更省资源。去 GitHub Release 下载 promtail 二进制,扔到 /usr/local/bin/。
/opt/promtail/config/promtail-config.yaml:
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /var/lib/promtail/positions.yaml
clients:
- url: http://你的Loki服务器IP:3100/loki/api/v1/push
scrape_configs:
- job_name: nginx
static_configs:
- targets:
- localhost
labels:
job: nginx
__path__: /var/log/nginx/access.log
- job_name: springboot
static_configs:
- targets:
- localhost
labels:
job: springboot
__path__: /opt/app/logs/*.log
用 systemd 管理:
[Unit]
Description=Promtail
After=network.target
[Service]
ExecStart=/usr/local/bin/promtail -config.file=/opt/promtail/config/promtail-config.yaml
Restart=always
User=root
[Install]
WantedBy=multi-user.target
systemctl enable --now promtail 完事。
我踩过的坑
坑 1:Promtail 连接 Loki 一直 404
确认 URL 写对了:http://IP:3100/loki/api/v1/push,注意结尾没有斜杠。
我一开始写的 http://IP:3100/api/v1/push(少了 /loki),Promtail 日志里全是 404。查了半天才发现 Loki 3.x 的 push 路径是 /loki/api/v1/push 不是 /api/v1/push。
坑 2:Promtail 不读取历史日志
默认情况下 Promtail 从文件末尾开始读,已有的历史日志不会采集。如果你部署完成后想看老日志,需要把 positions 文件删掉让它从头读:
systemctl stop promtail
rm /var/lib/promtail/positions.yaml
systemctl start promtail
注意这个操作会让 Promtail 重新推送所有日志,短时间内 Loki 的写入量会暴增。
坑 3:Loki 存储空间膨胀
Loki 不索引全文,但如果日志量大的话,磁盘还是会涨。我在 Loki 配置里加了 retention:
limits_config:
retention_period: 720h # 保留 30 天
720 小时就是 30 天,按自己的磁盘空间调整。
坑 4:Grafana 查日志时 LogQL 写不对
LogQL 语法跟 PromQL 很像,但不要直接照搬。最常用的查询:
{job="nginx"} |= "404"
|= 是包含,!= 是不包含,|~ 是正则。注意:Loki 默认不索引日志内容,正则查询比 ES 慢,尽量用标签过滤缩小范围后再做内容匹配。
错误示例:
{job="nginx"} |~ "404" # 正则是 |~ 不是 |=,这里 404 用 |= 就够了
坑 5:时区对不上
Loki 默认 UTC,Grafana 会在前端转成你的浏览器时区。但 positions.yaml 里存的时间戳是 UTC,如果你手动改过系统时间再重启 Promtail,可能导致日志重复采集或漏采。别手动调时间。
跟 ELK 比一下
| 对比维度 | ELK (ElasticSearch) | Loki |
|---|---|---|
| 内存占用 | 2-4GB 起步 | 200-500MB |
| 全文索引 | 是,但代价是存储爆炸 | 不索引全文,只索引标签 |
| 日志内容搜索 | 快 | 够用(正则会慢点) |
| 与 Grafana 集成 | 要配插件 | 原生支持 |
| 适合场景 | 大量非结构化日志、需要全文检索 | 结构化/半结构化日志、已有 Grafana |
对个人服务器和小团队来说,Loki 的资源消耗友好太多了。我之前试过在 2C4G 的轻量云上搭 ELK,ElasticSearch 刚启动就吃了 1.5G 内存,加上 Logstash 和 Kibana,直接 OOM。Loki 这套跑了一个月没出过问题。
总结
如果你的服务器已经在用 Grafana 看 Prometheus 指标,加 Loki 就是顺手的事——同一个面板里既能看 CPU 曲线又能查对应时间的日志,排查问题的效率高了一大截。
没有 Grafana 的话,这套组合也是一次性把监控和日志都解决了。Prometheus + Grafana + Loki,三件套下来总内存不到 1G,个人服务器完全能跑。
评论 (0)