使用Fluentd将Nginx的访问日志存储到MySQL并进行可视化
背景概述
我在个人管理的服务器上发布了网页,并且想要查看每个页面的访问信息。为了进行日志收集的试行,我也尝试将访问日志可视化。
环境建设政策
-
- Docker, Docker-Composeを使って構築する。
-
- 個人的な経験値から以下のミドルウェアを利用する。
nginx:Webサーバ
fluentd:nginxのアクセスログを収集
mysql:収集したログ情報の格納
metabase:DBに格納したログ情報の可視化
组成

前提环境是指一定条件存在的背景或基础。
-
- 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进行数据可视化

暂时,我们成功地完成了通向可视化的路径。将仪表板的扩展作为未来的任务,并且本次到此为止。
绊倒的地方
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语句)