使用Fluentd将Nginx的访问日志存储到MySQL并进行可视化

背景概述

我在个人管理的服务器上发布了网页,并且想要查看每个页面的访问信息。为了进行日志收集的试行,我也尝试将访问日志可视化。

环境建设政策

    • Docker, Docker-Composeを使って構築する。

 

    • 個人的な経験値から以下のミドルウェアを利用する。

nginx:Webサーバ
fluentd:nginxのアクセスログを収集
mysql:収集したログ情報の格納
metabase:DBに格納したログ情報の可視化

组成

構成図2.png

前提环境是指一定条件存在的背景或基础。

    • OS : Ubunt 20.04.4 LTS

 

    • Docker : 20.10.17, build 100c701

 

    Docker compose : version 1.29.1, build c34c88b2

建立

使用以下步骤进行构建:
1. 创建目录结构
2. 创建docker-compose文件
3. 构建mysql容器
4. 构建fluentd容器
5. 构建Metabase容器

1. 创建目录

我创建了以下的目录结构。关于个别容器的配置文件等内容将在后面提到。

/home/com/homepage 
 ├─ nginx
 │  ├─ conf
 │  │  └─ nginx.conf
 │  └─ log
 │     └─ access.log ・・・nginxのアクセスログファイル
 ├─ contents ・・・webページのコンテンツ
 │  └─ index.html
 ├─ fluented
 │  ├─ data
 │  │  └─ nginx_access.log.pos ・・・最終読み込み位置の保持ファイル
 │  ├─ Dockerfile   
 │  └─ fluent.conf ・・・Fluentdの設定ファイル
 ├─ mysql
 │  ├─ scripts
 │  │  └─ create_tabel.sql ・・・テーブル作成のSQLファイル
 │  └─ dbvolume
 ├─ metabase
 └─ docker-compose.yaml

创建docker-compose文件

我按照以下方式创建了docker-compose文件。
[特殊事项]
– 从fluentd容器中引用nginx的日志文件。

version: '3'
services:
  nginx:
    image: nginx:1.23
    ports:
      - 80:80
    volumes:
      - ./contents:/usr/share/nginx/html
      - ./nginx/log:/var/log/nginx
      - ./nginx/conf/nginx.conf:/etc/nginx/conf.d/nginx.conf
    environment:
      TZ: Asia/Tokyo
    restart: always

  metabase:
    image: metabase/metabase:v0.46.2
    restart: always
    volumes:
      - ./metabase:/metabase-data
    ports:
      - 3000:3000
    environment:
      MB_DB_FILE: /metabase-data/metabase.db

  fluentd:
    build:
      context: .
      dockerfile: ./fluentd/Dockerfile
    ports:
      - 24224:24224
    volumes:
      - ./nginx/log:/var/log/nginx
      - ./fluentd/fluent.conf:/fluentd/etc/fluent.conf
      - ./fluentd/data:/fluentd/log

  db:
    image: mysql:8.0
    restart: always
    volumes:
     - ./mysql/dbvolume:/var/lib/mysql
     - ./mysql/scripts:/docker-entrypoint-initdb.d
    ports:
     - 3306:3306
    environment:
      - MYSQL_DATABASE=log
      - MYSQL_USER=log
      - MYSQL_PASSWORD=password
      - MYSQL_ROOT_PASSWORD=passwordpassword
      - TZ=Asia/Tokyo

3. 构建一个 MySQL 容器

我进行了以下步骤:
1. 创建了表定义文件。
2. 对容器启动时的表进行了自动化创建。

创建表定义文件

我查阅了Fluend的官方网页,确认了解析nginx访问日志时的输出元素。
我将这些项目作为列创建表的SQL语句输出到文件中。

CREATE TABLE `nginx_access_log` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT,
  `time_jst` datetime NOT NULL DEFAULT '1000-01-01 00:00:00',
  `remote_ip` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8_general_ci DEFAULT NULL,
  `host_ip` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8_general_ci DEFAULT NULL,
  `user_id` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8_general_ci DEFAULT NULL,
  `method` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8_general_ci DEFAULT NULL,
  `access_path` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8_general_ci DEFAULT NULL,
  `size` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8_general_ci DEFAULT NULL,
  `referer` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8_general_ci DEFAULT NULL,
  `agent` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8_general_ci DEFAULT NULL,
  `http_code` varchar(100) CHARACTER SET utf8mb3 COLLATE utf8_general_ci DEFAULT NULL,
  `xforwarded` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3;

参考
流畅的 nginx 解析插件

3-2. 自动化容器启动时的表格创建

当在启动Fluentd容器时,如果表格不存在,Fluentd会出现错误。因此,当表格不存在时,我们自动创建表格。
将脚本文件存储在docker-entrypoint-initdb.d中,这样它将在容器启动时自动执行。因此,我们将在3-1中创建的脚本挂载到容器中。

  db:
    image: mysql:8.0
    restart: always
    volumes:
     - ./mysql/dbvolume:/var/lib/mysql
     - ./mysql/scripts:/docker-entrypoint-initdb.d←これを追加

参考【Docker】【MySQL】当容器首次启动时执行脚本

4. 建立 fluentd 容器

完成以下步骤:
1. 安装MySQL插件
2. 配置日志收集

4-1. 安装 MySQL 插件

为了将通过fluentd读取的nginx日志批量插入到mysql中,需要在td-agent中添加mysql插件。
fluentd的默认容器映像中不包含mysql插件。因此需要准备一个Dockerfile并在容器启动时进行安装构建。

【特别记载】
– 要安装的插件是fluent-plugin-mysql。
– 为了不增加文件大小,请指定–no-document选项。
– 用户flunet没有安装权限,需要切换到root用户。
– 要将容器的时区更改为JST。

FROM fluent/fluentd:v1.16-1

USER root

RUN apk add --no-cache --virtual .build-deps \
    build-base \
    ruby-dev \
    tzdata && \
    cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \
    echo "Asia/Tokyo" > /etc/timezone && \
    apk add --no-cache \
    mariadb-dev && \
    gem install fluent-plugin-mysql --no-document && \
    apk del .build-deps

USER fluent

参考
Docker映像【流利/流利的】- Docker映像
【Docker环境】使用Fluentd和MySQL的批量插入进行日志收集【上篇】

4-2. 日志收集设置

创建配置文件,以便读取nginx的日志并将其注册到MySQL服务器。

<source>
  @type tail
  format nginx
  path /var/log/nginx/access.log
  pos_file /fluentd/data/nginx_access.log.pos
  tag nginx.access
</source>

<match nginx.access>
  @type mysql_bulk
  host 192.168.2.10
  port 3307
  database log
  username log
  password password
  
  column_names id,time_jst,remote_ip,host_ip,user_id,method,access_path,http_code,size,referer,agent,xforwarded
  key_names id,host,user,${time},method,path,version,code,size,referer,agent,xforwarded
  table nginx_access_log
  
  flush_interval 10s
</match>

参考:在Docker中尝试使用Fluentd获取Nginx访问日志

5. 使用Metabase进行数据可视化

image.png

暂时,我们成功地完成了通向可视化的路径。将仪表板的扩展作为未来的任务,并且本次到此为止。

绊倒的地方

1. 日志文件的权限

当启动fluentd容器时,出现以下错误,导致容器无法启动。

意料之外的错误 error_class=Errno::EACCES 错误=”权限被拒绝 @ rb_file_s_stat – `/var/log/nginx/access.log”

Fluentd没有读取Nginx的访问日志(access.log)的权限,因此导致出现错误。
为了让Fluentd能够访问,我改变了access.log文件的权限设置。

修改/home/com/homepage/web/log/access.log文件的权限为775。

重启了fluentd容器后,上述错误消除了,但是接下来又出现了另一个错误。

意外错误 错误类型=Errno::EACCES 错误信息=”权限被拒绝 @ rb_sysopen – /fluentd/log/nginx_access.log.pos”

当Fluentd读取Nginx的访问日志(access.log)时,会创建一个名为access.log.pos的文件,以保存读取的进度信息。但由于无法创建该文件,导致出现错误。为了能够创建该文件,我改变了目录的权限。

将./fluentd/data的权限设置为777。

这样一来,容器就能够没有错误地启动了。

参考
rb_file_s_stat #2425的权限被拒绝。

2. 查看 fluentd 的日志记录

为了查看Fluentd日志,我尝试连接到Fluentd容器并执行以下命令,但是由于Fluentd容器中没有bash,所以无法连接。

使用Docker执行命令连接到homepage_nginx_1容器并打开终端:/bin/bash。

由于已安装了sh而不是bash,因此通过以下命令进行连接,成功启动。

在中国的自然语言,将以下内容重新叙述:
使用docker exec -it homepage_nginx_1 /bin/sh命令。

在连接之后,在控制台上执行命令可以查看日志。

使用中文本地方式重新表达以下命令,仅需要一种选项:

fluentd -vv -c /fluentd/etc/fluent.conf

Fluentd的详细日志模式,配置文件路径为/fluentd/etc/fluent.conf。

参考:在运行Fluentd Docker镜像时的笔记:Fluentd日志记录。

3. fluentd容器的时区

在开始阶段,时间是以协调世界时(UTC)表示的。在docker-compose中,即使在环境变量中指定了时区,也无法反映出来。
通过参考以下网站,我们修改了Dockerfile并更改了容器镜像。
我们将Docker容器(Fluentd)的时区从UTC更改为日本标准时间(JST)。

其他的建议 tā de

1. 读取现有的日志

为了可视化已经启动的Web服务器的访问日志,希望从日志文件的开头开始读取。
在Fluentd的初始设置中,它只会读取末尾的信息,所以需要更改设置。
将read_from_head设置为True。

流利。配置

<source>
  @type tail
  format nginx
  path /var/log/nginx/access.log
  pos_file /fluentd/data/nginx_access.log.pos
  tag nginx.access
  read_from_head true ← 追加!!
</source>

理解 fluentd in_tail 插件的运作方式。

2. 缩短监视间隔

默认设置下,监视日志文件更新的间隔为60秒。为了进行操作确认,更短的时间间隔更方便,因此进行了设置更改。fluent.conf。

<source>
  @type tail
  format nginx
  path /var/log/nginx/access.log
  pos_file /fluentd/data/nginx_access.log.pos
  tag nginx.access
  read_from_head true
  refresh_interval 10 ← 追加!!
</source>

理解fluentd的in_tail插件的工作方式。

3. 初始化表的自增列

当尝试将数据存储到数据库中时,由于自动递增,ID的值不断增长。
为了在开始运行时从1开始,我们初始化了自动递增的值。
执行以下SQL语句可以进行初始化。

修改表<表名>的自增属性为1。

在本次案例中,以下为SQL代码。

修改 nginx_access_log 表的 AUTO_INCREMENT 值为 1。

如果使用truncate table语句删除所有记录,递增也会被初始化。

清空表格

参考:如何在MySQL中重置AUTO_INCREMENT值和删除所有数据(使用TRUNCATE TABLE语句)

批量插入:当向关系数据库(RDB)的表中添加行时,通过一次SQL语句的执行添加多行数据。
广告
将在 10 秒后关闭
bannerAds