相关阅读:
可观测性 | Grafana Loki 日志聚合方案快速体验
前言
在相关阅读中,通过快速部署示例项目,体验通过 Grafana WebUI 查询日志。本文介绍 Loki 栈的配置实现,适用于可观测能力建设的开发人员。
日志聚合系统架构
一个最基本的日志聚合系统通常包含以下四个核心模块:
-
日志生成模块,产生日志数据的源头,通常是应用程序、服务器、网络设备等,如 Web 服务器(如 Nginx、Apache)生成的访问日志和错误日志,应用程序(如 Java 应用、Python 应用)通过日志库(如 Log4j、Python 的 logging 模块)生成的日志。
-
日志收集模块,负责从日志生成源中收集日志数据,并且能够处理日志的格式化和初步解析,如 Fluentd、Filebeat、Promtail、Logstash 等。
-
日志存储模块,用于存储收集到的日志数据,支持高效查询和长期保留,如 Loki、ElasticSearch。日志聚合系统的核心模块,决定了日志的存储效率、查询效率。
-
日志查询与可视化模块,提供用户界面,允许用户查询、分析和可视化日志数据,如 Grafana、Kibana。
以下是这四个模块的基本架构示意图,使用 Mermaid 语法表示:
Loki 栈聚合 Nginx 日志
(日志生成模块)"] --> B["Promtail 服务
(日志收集模块)"] B --> C["Loki 服务
(日志存储模块)"] D["Grafana
(日志查询与可视化模块)"] --> C
日志生成模块:Nginx 服务
Nginx 的日志能力主要包括:访问日志(Access Log) 和 错误日志(Error Log) 两大类,开发和运维人员通常通过这些日志来监控服务器状态、排查问题、优化性能和分析用户行为。
Nginx 日志由配置文件 nginx.conf
定义,日志默认存储路径:
/var/log/nginx/access.log
/var/log/nginx/error.log
也可以在配置文件中显示定义:
lua
server {
// 忽略其他代码
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log error;
}
access.log
示例:
arduino
172.19.0.1 - - [18/Jun/2025:14:55:11 +0000] "GET /api/core/video/slide HTTP/1.1" 404 53893 "http://localhost/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36" "-"
172.19.0.1 - - [18/Jun/2025:14:55:11 +0000] "GET /api/core/collection/list HTTP/1.1" 404 53893 "http://localhost/" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36" "-"
172.19.0.1 - - [18/Jun/2025:14:55:12 +0000] "GET / HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36" "-"
在使用 Docker 启动 Nginx 容器时,容器内部的日志默认存储在其文件系统中,而容器的文件系统是隔离的,为了暴露给其他服务,需要挂载到宿主机。
因此,可以在docker-compose.yaml
中设置配置文件:
我极力推荐任何情况下都使用 docker-compose.yaml 启动项目服务,即使是单容器
bash
volumes:
- ./volumes/logs:/var/log/nginx # 将 Nginx 容器的 /var/log/nginx目录挂在宿主机相对路径
日志采集模块:Promtail
日志采集工具如 Promtail 的主要任务是把服务器上的日志文件内容收集起来,然后发送给日志存储模块如 Loki。可以把它想象成一个"日志搬运工",它把日志从一个地方(服务器上的文件)搬到另一个地方(Loki)。
从开发人员的角度来看,日志采集工具 Promtail 的工作包括 找到日志文件 、解析日志文件 、发送日志文件 这三个部分。
采集 Nginx 日志的 Promtail 配置文件:
yaml
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients: # 发送日志文件到 Loki 服务
- url: http://loki-front:3100/loki/api/v1/push
scrape_configs:
- job_name: 'magic-nginx'
static_configs:
- targets: # 找到日志文件
- localhost
labels:
job: nginx-access
__path__: /var/log/access.log
- targets:
- localhost
labels:
job: nginx-error
__path__: /var/log/error.log
pipeline_stages: # 解析日志文件
# 处理访问日志
- match:
selector: '{job="nginx-access"}'
stages:
- regex:
expression: '(?P<remote_addr>\S+) \S+ \S+ [(?P<time_local>[^]]+)] "(?P<request>[^"]+)" (?P<status>\d+) (?P<body_bytes_sent>\d+) "(?P<http_referer>[^"]*)" "(?P<http_user_agent>[^"]*)"'
- timestamp:
source: time_local
format: "02/Jan/2006:15:04:05 -0700"
- labels: # 为日志项添加 label 标签
remote_addr:
status:
http_user_agent:
# 处理错误日志
- match:
selector: '{job="nginx-error"}'
stages:
- regex:
expression: '[(?P<time_local>[^]]+)] (?P<level>\w+): (?P<message>.+)'
- timestamp:
source: time_local
format: "YYYY/MM/DD HH:mm:ss"
- labels:
level:
上述配置文件中需要关注的是,容器间文件系统相互独立,宿主机承担了文件共享的桥梁。
需要将宿主机上的 Nginx 日志挂载到 Promtail 容器内。
yaml
- targets:
- localhost # Promtail 容器的 localhost
labels:
job: nginx-access
__path__: /var/log/access.log
在 docker-compose.yaml
中挂载
yaml
promtail-front:
image: grafana/promtail:3.4
volumes:
# 设置目录挂载
- ./volumes/logs:/var/log # 挂载宿主机上的的日志到 promtail 容器
容器间是否可以直接访问呢?即 Nginx 容器和 Promtail 共享磁盘空间。
答案是否定的。
在 Docker 网络设计理念中,同一网桥(bridge)下的容器服务在网络上互相联通,其核心实现原理基于 Linux 的虚拟网桥(bridge)和虚拟以太网对(veth pair)技术。
对开发者来说,可以通过服务名(service-name)进行网络通信,但是磁盘空间是隔离的。
我的验证:将 promtail 配置文件中 targets 变更为 nginx 容器服务名,无法正常使用。
yaml
static_configs:
- targets:
- front-nginx # 1. nginx 服务名称
labels:
job: nginx-access
__path__: /var/log/nginx/access.log # 2.1 nginx 服务内的访问日志位置
- targets:
- front-nginx
labels:
job: nginx-error
__path__: /var/log/nginx/error.log # 2.2 nginx 服务内的错误日志位置
日志存储模块:Loki
日志存储模块主要承担 2 个功能:Log Server 和 Log Storage,即为日志服务器和日志存储。
Loki-Architecture-Components:

Loki 的架构设计使其可以高效地处理大规模日志数据,同时保持较低的资源消耗。
Log Server,Loki 的核心组件,负责接收来自 Alloy、Promtail 等代理的日志数据,并将其存储到后端存储系统中。Log Server 包含多个微服务组件,如 Distributor、Ingester、Query Frontend 和 Querier。
Log Storage,Loki 的存储后端,用于存储压缩的日志块(chunks)和索引(index)。 支持多种存储后端,包括本地文件系统、AWS S3、Google Cloud Storage 等。Loki 仅索引日志的元数据(标签),而不是日志内容本身,这大大减少了存储空间和查询时间。
最简单地,使用单体模式部署,本地磁盘存储。
生产环境中,推荐微服务(组件化)部署,S3 对象存储。
创建 loki/config.yaml
配置文件,如下
yaml
auth_enabled: false # 关闭鉴权
server:
http_listen_port: 3100 # 默认服务器端口号
common: # 常规配置
ring: # 一致性哈希环,可先忽略
instance_addr: 127.0.0.1
kvstore:
store: inmemory
replication_factor: 1 # 日志条目副本数量
path_prefix: /tmp/loki
schema_config: #
configs:
- from: 2020-05-15
store: tsdb
object_store: filesystem
schema: v13
index:
prefix: index_
period: 24h
storage_config:
filesystem: # 文件系统,本地磁盘
directory: /tmp/loki/chunks
启动 Loki 服务时,设置配置文件,容器内配置文件为 /etc/loki/config.yaml
:
bash
volumes:
- ./loki/config.yaml:/etc/loki/config.yaml:ro
command:
- "--config.file=/etc/loki/config.yaml"
日志查询模块:Grafana
Grafana 最初与 Prometheus 协同工作,迅速在系统监控领域崭露头角,并逐渐成为事实上的标准。现在,Grafana 在可观测性上全面出击,其中就包括日志服务。
Grafana 是一个开箱即用的 WebUI 服务,只需要2步即可检索日志:
- 配置数据源 DataSource
- 基于标签 Label 和日志查询语言 LogQL 检索
配置数据源
方式一:手动在 Grafana WebUI 的 Data sources 选项中配置。

增加日志源 Loki,可以看到 Grafana 对数据源的支持非常广泛。

方式二(推荐):使用配置文件定义数据源 Grafana Provisioning
,优势是可跟随 Git 版本管理提交,易于迁移。
Grafana Provisioning 支持配置数据源 Data sources 和 仪表盘 Dashboards。
创建配置文件 loki-datasource.yaml
yaml
apiVersion: 1
datasources:
- name: loki
type: loki # 数据源类型
access: proxy
origId: 1
url: http://loki-service:3100 # Loki Server 地址,同一 bridge 下使用服务名访问
basicAuth: false
version: 1
editable: false
在 Grafana 启动时,将其作为 provisioning 配置文件挂载到容器中
yaml
# Grafana
# 默认端口 3000
grafana-service:
image: grafana/grafana:11.3.2-ubuntu
volumes:
# 挂载 provisioning 数据源配置
- ./grafana/provisioning/etc/datasources:/etc/grafana/provisioning/datasources:ro
environment:
TZ: Asia/Shanghai # 中国时区
# 匿名登陆
GF_AUTH_ANONYMOUS_ENABLED: true
GF_AUTH_ANONYMOUS_ORG_ROLE: Admin
GF_USERS_ALLOW_SIGN_UP: false
将以上配置提交到代码仓库,可以很方便地实现配置迁移,避免繁琐的手动配置过程,且对于使用者来说可以忽略不相关步骤。
日志检索 Explore | Drilldown
在 Grafana 的 Web UI 中,Explore 是一个强大的交互式界面,用于实时探索和分析数据。它提供了快速查询、可视化和调试数据的功能,支持多种数据源,包括 Prometheus 和 Loki。
在 Prometheus 系统监控中,Explore 主要承担调试和临时分析的作用,监控仪表盘在 Dashboards 中构建,并供展示。
在 Loki 日志服务中,Explore 主要作为日志查询的入口,用于故障诊断和日志分析等。
Grafana 家族的产品都是用标签 label 来汇聚数据条目,同时支持时间范围界定。

不同的是,Prometheus 基于 PromQL 查询语言,Loki 基于 LogQL 查询语言。
除了最基本地基于时间、标签索引聚合日志,也支持模糊查询,并使用逻辑与、或、非等表达式来过滤。
在 Loki 日志服务中,Drilldown 是 Grafana 提供的一种功能,全称为 Grafana Logs Drilldown。它提供一种无查询(queryless)体验,允许用户在不编写复杂 LogQL 查询的情况下浏览和分析 Loki 日志。
Drilldown 与 Explore 对比
特性 | Grafana Logs Drilldown | Grafana Explore |
---|---|---|
查询方式 | 无需手动编写 LogQL 查询,自动可视化 | 需要用户输入 LogQL 查询语句 |
功能定位 | 简化日志浏览和分析,适合初学者 | 提供更灵活的查询和分析工具,适合高级用户 |
适用场景 | 快速定位和分析日志,无需深入了解 LogQL | 开发监控仪表板、告警规则,验证查询语句 |
可视化能力 | 自动生成可视化图表 | 支持多种视图(日志流、表格、图表等) |
灵活性 | 功能较为固定,适合快速分析 | 功能丰富,支持复杂查询和自定义视图 |
总的来说,Grafana Logs Drilldown 专注于简化日志分析过程,通过自动化的可视化和过滤功能,让用户无需编写复杂查询即可快速获取日志洞察,特别适合初学者或需要快速分析的场景。
后续将对 Drilldown 功能做专门的介绍,在此文中不做过多描述。
总结
一个完整的日志聚合系统(日志服务)通常包含以下四大核心模块:日志生成模块、日志采集模块、日志存储模块以及日志查询模块。本文对每个模块作了简要介绍和功能概述。
通过构建一个入门级别的 Loki-Nginx 项目,描述了其核心配置的实现过程,帮助读者从架构层面理解 Loki 日志服务的工作原理和设计思路。
在后续的篇章中,我们将从业务需求的角度出发,深入探讨每个模块的配置和实现细节。我们希望通过这些内容,能够更全面地理解 Grafana Loki
日志服务的构建过程,并掌握如何针对实际业务场景进行优化和扩展。
关注微信公众号,获取运维资讯
如果此篇文章对你有所帮助,感谢你的点赞 与收藏,也欢迎在评论区友好交流。
微信搜索关注公众号:持续运维
参考
- Grafana Logs Drilldown, grafana.com/docs/grafan...
- Grafana 官方网站, grafana.com/