Loki 中小项目日志系统的不二之选

Loki 学习总结(1)—— Loki 中小项目日志系统的不二之选

前言

项目做正规了,日志系统是少不了的,目前大部分日志平台推荐基于 ELK 构建,不过 ELK 算是比较重了,架构太大,中小项目不太好 Hold 住,希望找一款简单一些的,如果实在找不到再上 ELK,这个时候一款名叫 Loki 的日志系统横空出世。Loki 是 Grafana Labs 团队最新的开源项目,是一个水平可扩展,高可用性,多租户的日志聚合系统。它的设计非常经济高效且易于操作,因为它不会为日志内容编制索引,而是为每个日志流编制一组标签。项目受 Prometheus 启发,官方的介绍就是:Like Prometheus, but for logs,类似于 Prometheus 的日志系统。

一、Loki 快速上手

Loki 作为日志系统的后起之秀,设计上可以说非常优秀,设计的理念就是为了让日志聚合更简单,它被设计为非常经济高效且易于操作。它不索引日志的内容,而是为每个日志流设置一组标签。它主要由三部分组成:

  • Promtail 是日志收集器,负责收集应用的日志并发送给 Loki。

  • Loki 用于日志的存储和解析,并提供查询 API 给下游展示。

  • Grafana 负责将 Loki 的日志可视化。

 

 

与其他日志聚合系统相比,Loki具有下面的一些特性:

  • 不对日志进行全文索引。通过存储压缩非结构化日志和仅索引元数据,Loki 操作起来会更简单,更省成本。
  • 通过使用与 Prometheus 相同的标签记录流对日志进行索引和分组,这使得日志的扩展和操作效率更高。
  • 特别适合储存 Kubernetes Pod 日志; 诸如 Pod 标签之类的元数据会被自动删除和编入索引。

简单上手

Loki 安装

首先是安装,现在跑 demo 我优先选择快捷方便的 Docker。下面是我修改过的 Docker Compose 脚本,根据自己的需要改改就能一键启动 Loki。

version: "3"

networks:
  loki:

services:
  loki:
    image: grafana/loki:2.2.1
    container_name: loki-service
    volumes:
#    将loki的配置文件挂载到本地 c:/docker/loki 目录
      - c:/docker/loki:/etc/loki/
    ports:
      - "3100:3100"
    command: -config.file=/etc/loki/loki.yml
    networks:
      - loki

  promtail:
    image: grafana/promtail:2.2.1
    container_name: promtail-service
    volumes:  
    #  为了读取本地的日志目录,这个是个默认配置目的就是为跑起来,生产肯定不是这样的。   
      - c:/docker/log:/var/log/
    #  promtail  的配置文件也挂载到本地 c:/docker/promtail目录  
      - c:/docker/promtail:/etc/promtail/
    command: -config.file=/etc/promtail/promtail.yml
    networks:
      - loki

  grafana:
    image: grafana/grafana:latest
    container_name: grafana-service
    ports:
      - "3000:3000"
    networks:
      - loki

上面的挂载目录 c:/docker/loki 和 c:/docker/promtail 可以根据自己的情况修改。

Loki 配置

上面文件中的 -config.file=/etc/loki/loki.yml 是 Loki 的配置文件,我们需要将配置文件 loki.yml 提前放在 c:/docker/loki 下,我使用默认配置:

auth_enabled: false

server:
  http_listen_port: 3100

ingester:
  lifecycler:
    address: 127.0.0.1
    ring:
      kvstore:
        store: inmemory
      replication_factor: 1
    final_sleep: 0s
  chunk_idle_period: 1h       # Any chunk not receiving new logs in this time will be flushed
  max_chunk_age: 1h           # All chunks will be flushed when they hit this age, default is 1h
  chunk_target_size: 1048576  # Loki will attempt to build chunks up to 1.5MB, flushing first if chunk_idle_period or max_chunk_age is reached first
  chunk_retain_period: 30s    # Must be greater than index read cache TTL if using an index cache (Default index read cache TTL is 5m)
  max_transfer_retries: 0     # Chunk transfers disabled

schema_config:
  configs:
    - from: 2020-10-24
      store: boltdb-shipper
      object_store: filesystem
      schema: v11
      index:
        prefix: index_
        period: 24h

storage_config:
  boltdb_shipper:
    active_index_directory: /loki/boltdb-shipper-active
    cache_location: /loki/boltdb-shipper-cache
    cache_ttl: 24h         # Can be increased for faster performance over longer query periods, uses more disk space
    shared_store: filesystem
  filesystem:
    directory: /loki/chunks

compactor:
  working_directory: /loki/boltdb-shipper-compactor
  shared_store: filesystem

limits_config:
  reject_old_samples: true
  reject_old_samples_max_age: 168h

chunk_store_config:
  max_look_back_period: 0s

table_manager:
  retention_deletes_enabled: false
  retention_period: 0s

ruler:
  storage:
    type: local
    local:
      directory: /loki/rules
  rule_path: /loki/rules-temp
  alertmanager_url: http://localhost:9093
  ring:
    kvstore:
      store: inmemory
  enable_api: true

Promtail 的配置

和 Loki 类似,Promtail 也要在本地挂载的 c:/docker/promtail目录下配置 promtail.yml,这里也使用默认配置:

server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /tmp/positions.yaml

clients:
  - url: http://loki:3100/loki/api/v1/push

scrape_configs:
  - job_name: system
    static_configs:
      - targets:
          - localhost
        labels:
          job: varlogs
          # 这个跟挂载的位置有点关系,你可以猜猜
          __path__: /var/log/*log

我猜测 /var/log/*log 就是读取日志的位置,所以我把它挂载到本地 c:/docker/log,等下弄点日志到本地这个目录下,看看能读取出来不。

启动 Loki

配置完毕后执行 docker-compose -f <docker-compose.yml 路径> up 命令,会先下载镜像然后启动三个 Docker 容器。成功后打开 http://localhost:3000/ 登录 Grafana,默认账号密码是 admin/admin。然后在侧边栏添加数据源为 Loki。 

 

 

 然后点击 Log labels 就可以把当前系统采集的日志标签给显示出来,可以根据这些标签进行日志的过滤查询

 然后配置 Loki 的 URL 为 http://loki:3100,然后点确定和测试,有绿色提示就表示成功了。

Promtail 日志代理

目前 Promtail 可以从两个来源跟踪日志:本地日志文件和 systemd 日志,我们上面演示的就是本地日志文件的加载,这种方式是目前我唯一能够使用的途径,另一种途径是通过 K8S 的服务发现能力。

 如果在多个应用服务器上部署对应的多个 Promtail 守护程序就能监视多个应用的静态日志文件,并通过 Loki API 将日志推送到 Loki 中进行聚合式的管理。

 

Promtail动态配置

我们只需要为 Loki 应用部署相关的 Promtail 守护程序即可。这里我仍然使用 Docker 对 Promtail 进行部署,不过我不能再使用默认配置了,这时的​​ config.yml​​ 应该是:

server:
  http_listen_port: 9080
  grpc_listen_port: 0

positions:
  filename: /var/log/positions.yaml

client:
  url: http://${LOKI_HOST}:${LOKI_PORT}/loki/api/v1/push

scrape_configs:
  - job_name: system
    pipeline_stages:
    static_configs:
      - labels:
          app: ${APP_NAME}
          job: varlogs
          host: ${LOG_HOST}
          __path__: /var/log/*log

为了构建一个通用的配置,我将一些参数进行了动态化。这是 ​​Loki2.1+​​​ 版本提供的特性,可以使用​​ ${} 来引用环境变量,甚至你可以为其指定默认值​​ ${VAR:default_value}​​。但是你必须得知道为了开启这一特性需要在 Promtail 启动命令中添加选项​​ -config.expand-env​​。

Promtail Docker 镜像改造

根据这个我对 Promtail 的 Docker 镜像进行了改造,具体的 ​​Dockerfile​​ 为:

FROM grafana/promtail:2.2.1
LABEL AUTHOR = felord.cn
VOLUME ["/var/log/"]
EXPOSE 9080
ENV LOKI_HOST="localhost"
ENV LOKI_PORT=3100
ENV APP_NAME="APP"
ENV LOG_HOST="localhost"
COPY config.yml /etc/promtail/
CMD ["-config.file=/etc/promtail/config.yml", "-config.expand-env"]

你可以通过​​ docker build -t loki-promtail:1.0 .​​命令构建这个自定义 Promtail 镜像。基本的启动命令:

docker run -d  --name promtail-service --network loki -v c:/docker/log:/var/log/  -e LOKI_HOST=loki -e APP_NAME=SpringBoot  loki-promtail:1.0

其中挂载的目录​​ c:/docker/log​​​ 依然是应用的日志目录,​​LOKI_HOST ​​要保证能够同 Loki 服务器通信,无论你通过直连还是 Docker 网络(这里用了 Docker 网桥)。你可以可以使用 Docker Compose 将应用和 Promtail 进行捆绑,所有的 Promtail 将把对应的日志发往 Loki 进行集中式的管理。另外通过自定义的 ​​Label​​ 我们可以通过应用名称来搜索日志了。

 

二、Loki 语法

选择器

对于查询表达式的标签部分,将其包装在花括号中 {},然后使用键值对的语法来选择标签,多个标签表达式用逗号分隔,比如:

|=:日志行包含字符串
!=:日志行不包含字符串
|~:日志行匹配正则表达式
!~:日志行与正则表达式不匹配

 

1 # 精确匹配:|="2020-11-16 "
2 {app_kubernetes_io_instance="admin-service-test2-container-provider"}|="2020-11-16 "

1 # 模糊匹配:|~"2020-11-16 "
2 {app_kubernetes_io_instance="admin-service-test2-container-provider"}|~"2020-11-16 "

1 # 排除过滤:!=/!~ "数据中心"
2 {app_kubernetes_io_instance="admin-service-master-container-provider"}!="数据中心"
3 {app_kubernetes_io_instance="admin-service-master-container-provider"}!~"数据中心"

1 # 正则匹配: |~ "()"
2 {app_kubernetes_io_instance="admin-service-master-container-provider"}!~"(admin|web)"
3 {app_kubernetes_io_instance="admin-service-master-container-provider"}|~"ERROR|error"

其他:

https://huaweicloud.csdn.net/63311dccd3efff3090b52b5e.html?spm=1001.2101.3001.6650.19&utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~activity-19-125220408-blog-125771943.235^v35^pc_relevant_increate_t0_download_v2_base&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~activity-19-125220408-blog-125771943.235^v35^pc_relevant_increate_t0_download_v2_base&utm_relevant_index=26

 

posted @ 2023-05-11 14:38  滴滴滴  阅读(200)  评论(0编辑  收藏  举报