文章

轻量级日志收集方案:LAG

前言

之前一直使用的 Elastic Stack 家族的 EFK 方案(ElasticSearch + Fluent Bit + Kibana),在配置集群的情况下,需要占用好几个G的内存。最近上线了个人独立开发的 app 后,配置不是特别好,就研究一下轻量级的日志收集方案:Loki + Alloy + Grafana(简称 LAG),部署完成后大概花费了 300 MB的内存,推荐大家尝试。

如果大家想要了解 EFK 日志方案的话,可以看下我早期的文章:

LAG 介绍

Grafana Loki 采用基于微服务的架构,设计为可水平扩展的分布式系统。该系统具有多个可以单独运行并并行运行的组件。Grafana Loki 的设计将所有组件的代码编译成一个单一的二进制文件或 Docker 镜像。 -target 命令行标志控制该二进制文件将作为哪个组件运行。

Loki 架构图

Loki架构图

Grafana Alloy 是Grafana Labs对OpenTelemetry Collector的发行版。它是一个与OTLP兼容的收集器,内置Prometheus优化,同时也支持跨指标、日志、跟踪和配置文件发送信号。

Alloy 始于Grafana Labs,并于2024年GrafanaCON上宣布。该项目的使命是创建最佳的“大帐篷”收集器,该收集器与最流行的开源可观察性生态系统兼容,并包括企业级功能,以简化在现代云原生基础设施中的大规模运营。

Alloy 架构图

Alloy 架构图

本地快速验证

这里使用 Docker Compose 进行安装,如下是需要部署的组件图(版本:v3.3.x):

Docker Componse 部署组件图

  • Flog :生成日志行。flog 是用于常见日志格式的日志生成器。

  • Grafana Alloy :从 flog 抓取日志行并通过网关推送到 Loki。

  • Gateway (nginx):网关(nginx)接收请求并根据请求的 URL 将它们重定向到相应的容器。

  • Loki Read 组件 :运行查询前端和查询器。

  • Loki Write 组件 :运行一个分发器和一个摄取器。

  • Loki Backend 组件 :运行索引网关、压缩器、规尺、Bloom 规划器(实验性)、Bloom 构建器(实验性)和 Bloom 网关(实验性)。

  • Minio :Loki 用来存储其索引和块的地方。

  • Grafana :提供在 Loki 中捕获的日志行的可视化。

接下来下载最新的脚本进行安装和部署。

下载脚本

 wget https://raw.githubusercontent.com/grafana/loki/main/examples/getting-started/loki-config.yaml -O loki-config.yaml
 wget https://raw.githubusercontent.com/grafana/loki/main/examples/getting-started/alloy-local-config.yaml -O alloy-local-config.yaml
 wget https://raw.githubusercontent.com/grafana/loki/main/examples/getting-started/docker-compose.yaml -O docker-compose.yaml

Docker 中运行

 docker compose up -d

运行情况

docker compose 运行情况

注意:如果你无法拉取镜像,可以参考我下面的生产部署环节。

验证 Loki 运行情况

  • 验证 read 组件是否 ready,访问: http://localhost:3101/ready,如果没问题的话会输出ready字符串,否则报错:Query Frontend not ready: not ready: number of schedulers this worker is connected to is 0

  • 验证 write 组件是否 ready,访问:http://localhost:3102/ready,如果没问题的话会输出ready字符串,否则报错:Ingester not ready: waiting for 15s after being ready

  • 验证 Grafana Alloy 是否启动,访问:http://localhost:12345,如果显示如下 UI 图片表示正常:

image-20241205142723714

使用 Grafana 查看日志

访问地址:http://localhost:3000

Grafana展示日志

关闭应用

 docker compose down

生产部署

01 验证镜像拉取情况

验证下云服务器是否出现无法拉取镜像的问题,需要替换一下docker 镜像源

服务器镜像拉取

02 使用 Github Actions 替换镜像源

参考我之前的文章:国内无法拉取 Docker 镜像解决方案

添加需要镜像的 Docker Images,然后等待 Github Actions 执行完成。

添加需要mirror的images

03 上传配置到服务器

官方下载的文件中有 Alloy 和 Loki 的配置,需要上传到服务器中。可以新建一个 devops 目录,用于存放配置。这里可以使用 SSH、UI 界面、FTP 等方式,取决于你的云服务器和开放的权限。

04 替换 Docker Compose 中的镜像源

 ---
 networks:
   loki:
 ​
 services:
   read:
     image: registry.cn-chengdu.aliyuncs.com/flyeric/loki:latest
     command: "-config.file=/etc/loki/config.yaml -target=read"
     ports:
       - 3101:3100
       - 7946
       - 9095
     volumes:
       - ./loki-config.yaml:/etc/loki/config.yaml
     depends_on:
       - minio
     healthcheck:
       test: [ "CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:3100/ready || exit 1" ]
       interval: 10s
       timeout: 5s
       retries: 5
     networks: &loki-dns
       loki:
         aliases:
           - loki
 ​
   write:
     image: registry.cn-chengdu.aliyuncs.com/flyeric/loki:latest
     command: "-config.file=/etc/loki/config.yaml -target=write"
     ports:
       - 3102:3100
       - 7946
       - 9095
     volumes:
       - ./loki-config.yaml:/etc/loki/config.yaml
     healthcheck:
       test: [ "CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:3100/ready || exit 1" ]
       interval: 10s
       timeout: 5s
       retries: 5
     depends_on:
       - minio
     networks:
       <<: *loki-dns
 ​
   alloy:
     image: registry.cn-chengdu.aliyuncs.com/flyeric/alloy:latest
     volumes:
       - ./alloy-local-config.yaml:/etc/alloy/config.alloy:ro
       - /var/run/docker.sock:/var/run/docker.sock
     command:  run --server.http.listen-addr=0.0.0.0:12345 --storage.path=/var/lib/alloy/data /etc/alloy/config.alloy
     ports:
       - 12345:12345
     depends_on:
       - gateway
     networks:
       - loki
 ​
   minio:
     image: registry.cn-chengdu.aliyuncs.com/flyeric/minio
     entrypoint:
       - sh
       - -euc
       - |
         mkdir -p /data/loki-data && \
         mkdir -p /data/loki-ruler && \
         minio server /data
     environment:
       - MINIO_ROOT_USER=loki
       - MINIO_ROOT_PASSWORD=supersecret
       - MINIO_PROMETHEUS_AUTH_TYPE=public
       - MINIO_UPDATE=off
     ports:
       - 9000
     volumes:
       - ./.data/minio:/data
     healthcheck:
       test: [ "CMD", "curl", "-f", "http://localhost:9000/minio/health/live" ]
       interval: 15s
       timeout: 20s
       retries: 5
     networks:
       - loki
 ​
   grafana:
     image: registry.cn-chengdu.aliyuncs.com/flyeric/grafana:latest
     environment:
       - GF_PATHS_PROVISIONING=/etc/grafana/provisioning
       - GF_AUTH_ANONYMOUS_ENABLED=true
       - GF_AUTH_ANONYMOUS_ORG_ROLE=Admin
     depends_on:
       - gateway
     entrypoint:
       - sh
       - -euc
       - |
         mkdir -p /etc/grafana/provisioning/datasources
         cat <<EOF > /etc/grafana/provisioning/datasources/ds.yaml
         apiVersion: 1
         datasources:
           - name: Loki
             type: loki
             access: proxy
             url: http://gateway:3100
             jsonData:
               httpHeaderName1: "X-Scope-OrgID"
             secureJsonData:
               httpHeaderValue1: "tenant1"
         EOF
         /run.sh
     ports:
       - "3000:3000"
     healthcheck:
       test: [ "CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:3000/api/health || exit 1" ]
       interval: 10s
       timeout: 5s
       retries: 5
     networks:
       - loki
 ​
   backend:
     image: registry.cn-chengdu.aliyuncs.com/flyeric/loki:latest
     volumes:
       - ./loki-config.yaml:/etc/loki/config.yaml
     ports:
       - "3100"
       - "7946"
     command: "-config.file=/etc/loki/config.yaml -target=backend -legacy-read-mode=false"
     depends_on:
       - gateway
     networks:
       - loki
     
 ​
   gateway:
     image: registry.cn-chengdu.aliyuncs.com/flyeric/nginx:latest
     depends_on:
       - read
       - write
     entrypoint:
       - sh
       - -euc
       - |
         cat <<EOF > /etc/nginx/nginx.conf
         user  nginx;
         worker_processes  5;  ## Default: 1
 ​
         events {
           worker_connections   1000;
         }
 ​
         http {
           resolver 127.0.0.11;
 ​
           server {
             listen             3100;
 ​
             location = / {
               return 200 'OK';
               auth_basic off;
             }
 ​
             location = /api/prom/push {
               proxy_pass       http://write:3100\$$request_uri;
             }
 ​
             location = /api/prom/tail {
               proxy_pass       http://read:3100\$$request_uri;
               proxy_set_header Upgrade \$$http_upgrade;
               proxy_set_header Connection "upgrade";
             }
 ​
             location ~ /api/prom/.* {
               proxy_pass       http://read:3100\$$request_uri;
             }
 ​
             location = /loki/api/v1/push {
               proxy_pass       http://write:3100\$$request_uri;
             }
 ​
             location = /loki/api/v1/tail {
               proxy_pass       http://read:3100\$$request_uri;
               proxy_set_header Upgrade \$$http_upgrade;
               proxy_set_header Connection "upgrade";
             }
 ​
             location ~ /loki/api/.* {
               proxy_pass       http://read:3100\$$request_uri;
             }
           }
         }
         EOF
         /docker-entrypoint.sh nginx -g "daemon off;"
     ports:
       - "3100:3100"
     healthcheck:
       test: ["CMD", "service", "nginx", "status"]
       interval: 10s
       timeout: 5s
       retries: 5
     networks:
       - loki
 ​
   flog:
     image: registry.cn-chengdu.aliyuncs.com/flyeric/flog
     command: -f json -d 500ms -l
     networks:
       - loki
 ​

05 配置域名

将 Grafana 3000 端口进行域名映射方便外网访问。

Grafana UI 界面

小结

三百多 MB 的内存就可以运行,还是推荐试一试的。

以上是通过 Docker Compose 的方式快速部署和验证,如果想要进行生产级别使用,可以考虑使用 Kubernetes 云原生,参考官方最新文档大致需要如下组件:

  • Loki:默认开启

  • Promtail:默认开启

  • Fluent Bit:默认关闭

  • Grafana:默认关闭

  • Prometheus:默认关闭

  • Filebeat:默认关闭

  • LogStash:默认关闭

需要根据具体的情况,选择日志收集的工具。

参考

Loki Github

Loki Quick Start

Grafana Alloy


欢迎关注我的公众号“Eric技术圈”,原创技术文章第一时间推送。

License:  CC BY 4.0