雷灵模板

服务器日志太多看不过来?我用 Loki + Promtail + Grafana 搭了一套日志系统,少踩了几个坑

author
·
6
0
🤖AI摘要
本文介绍了作者使用Loki、Promtail和Grafana搭建日志系统的经验。作者之前用`tail -f`和`grep`查日志遇到困难,后尝试Grafana Loki,发现其内存占用低、查询速度快,且与Grafana集成方便。文章详细介绍了部署过程,包括Loki和Grafana的配置、Docker Compose的使用以及Promtail的配置。

我服务器上跑着六七个服务,Nginx、Spring Boot、Redis、MySQL,还有几个自己写的小项目。出问题的时候,查日志是最头疼的事。

之前一直用 tail -fgrep 对付,但问题是:第一,日志散落在不同目录,出问题不知道先看哪个;第二,历史日志要找半年前的错误,得翻一堆按天切割的 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: v13store: 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)