Logs 可观测性 | Grafana Loki 架构窥探与实践

相关阅读:

可观测性 | Grafana Loki 日志聚合方案快速体验

前言

在相关阅读中,通过快速部署示例项目,体验通过 Grafana WebUI 查询日志。本文介绍 Loki 栈的配置实现,适用于可观测能力建设的开发人员。

日志聚合系统架构

一个最基本的日志聚合系统通常包含以下四个核心模块:

  1. 日志生成模块,产生日志数据的源头,通常是应用程序、服务器、网络设备等,如 Web 服务器(如 Nginx、Apache)生成的访问日志和错误日志,应用程序(如 Java 应用、Python 应用)通过日志库(如 Log4j、Python 的 logging 模块)生成的日志。

  2. 日志收集模块,负责从日志生成源中收集日志数据,并且能够处理日志的格式化和初步解析,如 Fluentd、Filebeat、Promtail、Logstash 等。

  3. 日志存储模块,用于存储收集到的日志数据,支持高效查询和长期保留,如 Loki、ElasticSearch。日志聚合系统的核心模块,决定了日志的存储效率、查询效率。

  4. 日志查询与可视化模块,提供用户界面,允许用户查询、分析和可视化日志数据,如 Grafana、Kibana。

以下是这四个模块的基本架构示意图,使用 Mermaid 语法表示:

graph TD A[日志生成模块] --> B[日志收集模块] B --> C[日志存储模块] D[日志查询与可视化模块] --> C

Loki 栈聚合 Nginx 日志

graph TD A["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步即可检索日志:

  1. 配置数据源 DataSource
  2. 基于标签 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 日志服务的构建过程,并掌握如何针对实际业务场景进行优化和扩展。

关注微信公众号,获取运维资讯

如果此篇文章对你有所帮助,感谢你的点赞收藏,也欢迎在评论区友好交流。

微信搜索关注公众号:持续运维

参考

  1. Grafana Logs Drilldown, grafana.com/docs/grafan...
  2. Grafana 官方网站, grafana.com/
相关推荐
一人一萧十只猫�1 小时前
Kubernetes 全面解析:从基础设施变革到核心架构详解
云原生·容器·kubernetes
BAOYUCompany3 小时前
暴雨服务器更懂人工智能+
运维·服务器·人工智能
SpiderPex3 小时前
GitHub下载项目完整配置SSH步骤详解
运维·ssh·github
睡觉的时候不会困4 小时前
基于三台主机搭建 Web 服务环境:Nginx、NFS 与 DNS 配置全流程
运维·nginx
@半良人5 小时前
Jenkins流水线部署+webhook2.0
运维·jenkins
瀚高PG实验室6 小时前
CentOS 8 安装HGDB V4.5 psql命令执行报错
linux·运维·centos·瀚高数据库
chaofan9806 小时前
AI驱动的浏览器自动化革命:Claude Code + BrowserCat MCP深度实践指南
运维·自动化·claude code
Fireworkitte7 小时前
DevOps 详解
运维·devops
xdpcxq10297 小时前
Docker用Web应用实例深入容器
前端·docker·容器
平生不喜凡桃李7 小时前
Linux 线程概念与控制
java·linux·运维