Skip to main content

用fluent-bit 导出nginx logs

在这个章节,我们将会介绍如何使用 fluent-bit,如何配置 nginx,docker 配置日志,以及如何配置 nginx 用 load balancer 和 ssl。

1. 安装 fluent-bit

我们会使用 fluent-bit 的 docker 镜像配合 docker-compose 来安装 fluent-bit。首先,我们需要创建一个 docker-compose.yml 文件,内容如下:

version: "3"
services:
fluent-bit:
image: fluent/fluent-bit
restart: always
command: fluent-bit -c /fluent-bit/etc/fluent-bit.conf
volumes:
- ./conf/fluent-bit:/fluent-bit/etc
- ./log/fluent-bit:/var/log/
network_mode: "host"

解释一下这个文件:

  • fluent-bit: 这是我们的服务名称,我们可以通过这个名称来访问这个服务。
  • image: 我们使用的 docker 镜像,这里我们使用的是 fluent/fluent-bit。
  • restart: 如果服务退出,docker 会自动重启服务。
  • command: 这里我们指定了 fluent-bit 的配置文件,这个配置文件在下面会介绍。
  • volumes: 这里我们指定了 fluent-bit 的配置文件,以及 fluent-bit 的日志文件。
  • network_mode: 这里我们使用了 host 模式,这样我们就可以直接访问宿主机的端口。

我们的文件架构如下:

.
├── conf
│   └── fluent-bit
│   └── fluent-bit.conf
├── data
├── docker-compose.yml
└── log
└── fluent-bit

我们的配置文件如下:

[SERVICE]
Flush 5
Daemon Off
Log_Level info
Log_File /var/log/fluent-bit.log
Parsers_File parsers.conf

[INPUT]
Name forward
Listen 0.0.0.0
Port 24224


[FILTER]
Name Parser
Match *
Parser docker
Key_Name log

[FILTER]
Name Parser
Match *
Parser nginx
Key_Name log

[FILTER]
Name grep
Match *
Exclude remote someip


[OUTPUT]
Name pgsql
Match *
Host somehost
Port 5432
User someuser
Password somepassword
Database fluent
Table fluentbit
Timestamp_Key ts

[OUTPUT]
Name stdout
Match *

解释一下这个文件:

  • SERVICE: 这里我们指定了 fluent-bit 的日志文件,以及日志级别。
  • INPUT: 这里我们指定了 fluent-bit 的监听端口,这里我们使用的是 24224。
  • FILTER: 这里我们指定了 fluent-bit 的过滤器,我们使用了三个过滤器,分别是 Parser,grep,以及 stdout。
    • Parser: 这里我们指定了 docker 和 nginx 的日志格式,顺序是先 docker,然后 nginx。原因是我们是从 docker 容器中导出日志,然后再导出到 fluent-bit,所以我们需要先解析 docker 的日志格式。而 docker 日志里包含了 nginx 日志, 所以再解析 nginx 的日志格式。
    • grep: 这里我们指定了过滤掉一些 ip 地址。
  • OUTPUT: 这里我们指定了 fluent-bit 的输出,我们使用了两个输出,分别是 pgsql 和 stdout。这里我们使用了 pgsql,因为我们需要把日志存储到数据库中,以便后续分析。

2. 配置 nginx

我们使用 nginx 的 docker 镜像,然后配置 nginx 的日志格式,以及 fluent-bit 的日志格式。首先,我们需要创建一个 docker-compose.yml 文件,内容如下:

version: "3"
services:
nginx:
image: nginx
restart: always
ports:
- 80:80
- 443:443
depends_on:
- fluent-bit
volumes:
- ./conf/nginx/nginx.conf:/etc/nginx/nginx.conf
- ./data/nginx:/var/log/nginx
- ./ssl:/etc/ssl
logging:
driver: "fluentd"
options:
fluentd-address: localhost:24224
tag: nginx.access

解释一下这个文件:

  • nginx: 这是我们的服务名称,我们可以通过这个名称来访问这个服务。
  • image: 我们使用的 docker 镜像,这里我们使用的是 nginx。
  • restart: 如果服务退出,docker 会自动重启服务。
  • ports: 这里我们指定了 nginx 的端口,80 端口用来访问 http,443 端口用来访问 https。
  • depends_on: 这里我们指定了依赖的服务,这里我们依赖 fluent-bit。
  • volumes: 这里我们指定了 nginx 的配置文件,以及 nginx 的日志文件。
  • logging: 这里我们指定了 fluent-bit 的地址,以及日志的 tag。
danger

在试验中曾经想尝试用fluentd-address: fluent-bit:24224,但是这样会报错,所以我们使用了fluentd-address: localhost:24224

我们的文件架构如下:

tip

我们有一个 ssl 目录,这个目录是用来存放cloudflareorigin certificates的。里面保存着两个文件common.crtcommon.key

.
├── conf
│   └── nginx
│   └── nginx.conf
├── data
├── docker-compose.yml
├── log
│   └── fluent-bit
└── ssl
├── common.crt
└── common.key

我们的配置文件如下:

events {
worker_connections 2000;
}

http {
ssl_certificate /etc/ssl/common.crt;
ssl_certificate_key /etc/ssl/common.key;
log_format postdata '$remote_addr - $remote_user [$time_local] '
'"$request" $status $bytes_sent '
'"$http_referer" "$http_user_agent" "$request_body"';

upstream loadbalancer {
server ip1;
server ip2;
}

set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 104.16.0.0/13;
set_real_ip_from 104.24.0.0/14;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 131.0.72.0/22;

real_ip_header CF-Connecting-IP;

server {
listen 443 ssl;
location / {
proxy_pass http://loadbalancer;
access_log /dev/stdout postdata;
}
}
}

解释一下这个文件:

  • ssl_certificate: 这里我们指定了 ssl 证书。
  • ssl_certificate_key: 这里我们指定了 ssl 证书的 key。
  • log_format: 这里我们指定了 nginx 的日志格式,我们使用了postdata,这个格式是我们自定义的。里面会包含request_body,这个字段是我们需要的。
  • upstream: 这里我们指定了负载均衡的服务器。
  • set_real_ip_from: 这里我们指定了cloudflare的 ip 地址段。这样就会把cloudflare的 ip 地址替换成真实的 ip 地址。
  • real_ip_header: 这里我们指定了cloudflareCF-Connecting-IP 来获取真实的 ip 地址
  • server: 这里我们指定了 nginx 的端口,以及日志的输出。
    • access_log: 这里我们指定了日志的输出,我们使用了/dev/stdout,这样就会把日志输出到标准输出,然后 fluent-bit 就可以把日志收集起来。因为我们使用了postdata,所以我们的日志格式就是postdata

3. 配置 fluent-bit parsers

我们需要配置 fluent-bit 的 parsers,因为我们需要把request_body字段解析出来。首先,我们需要创建一个 parsers.conf 文件,内容如下:

[PARSER]
Name nginx
Format regex
Regex ^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*?)(?: +\S*)?)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)" "(?<body>[^\"]*)")
Time_Key time
Time_Format %d/%b/%Y:%H:%M:%S %z

[PARSER]
Name docker
Format json
Time_Key time
Time_Format %Y-%m-%dT%H:%M:%S.%L
Time_Keep On

之后如果看到之前的fluentbit.conf文件,里面的parsers_file就是指向这个文件的。

Parsers_File parsers.conf