使用ELK对Nginx日志进行分析

GoAccess的分析结果粒度较粗, 在实际的日志分析场景中, 需要更加细致的分析, 故采用ELK这套较为成熟的方案.

1. 确认Nginx日志格式

对于使用默认安装方式进行安装Nginx, 其日志格式为:

1
2
3
'$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent"

即:

1
请求IP地址 - 请求用户 [请求时间] "请求相关信息(请求方法 路径 HTTP版本号)" 请求状态码 请求数据字节数 http_referer 请求用户user_agent

只有这些数据是不够的, 需要进行额外的补充, 比如响应时间(request_time), 对于负载均衡这类情况而言, 还需要知道真正提供服务的主机地址(upstream_addr), 以及相应的upstream响应时间(upstream_response_time)
最终版本的格式可以是这样的:

1
2
3
4
5
6
7
8
9
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" $request_time $upstream_response_time'
'$upstream_addr';

# 使用该日志配置
access_log /var/log/nginx/access.log main;
# 重启nginx
nginx -s reload

2. 配置Logstash

下载和安装就不再贴了, 官网上有非常明确的下载以及安装步骤.
在目录下新建一个nginx_access_log.conf配置文件, 配置文件由input, filter, output三部分组成.含义就是字面儿意思.

  • input
1
2
3
4
5
6
input {
file {
path => "/var/log/nginx/access.log" # 注意, 这里只是作为本地日志分析, 如果是真实环境的线上日志分析的话, 使用filebeat或者其它.
start_position => "beginning" # 从文件开始处读取
}
}
  • filter
    Logstashfilter中, 有这么一个东西: COMBINEDAPACHELOG, 对于默认的nginx日志格式可以直接使用这个
    但是在我们自定义的日志格式中, 就只能自己来写了.
1
%{IPORHOST:clientip} %{USER:ident} %{NOTSPACE:auth} \[%{HTTPDATE:timestamp}\] "(?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion})?|%{DATA:rawrequest})" %{NUMBER:response} (?:%{NUMBER:bytes}|-) %{QS:referrer} %{QS:agent} %{BASE10NUM:request_time} %{BASE10NUM:upstream_request_time} %{IPORHOST:upstream_ip}

大概就是这么一个东西, 具体的怎么写见官网, 这里推荐一个grok debugger.可以在线调试自己写的grok

http://grokdebug.herokuapp.com/

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
filter {
grok {
match => {"message" => "%{IPORHOST:clientip} %{USER:ident} %{NOTSPACE:auth} \[%{HTTPDATE:timestamp}\] "(?:%{WORD:verb} %{NOTSPACE:request}(?: HTTP/%{NUMBER:httpversion})?|%{DATA:rawrequest})" %{NUMBER:response} (?:%{NUMBER:bytes}|-) %{QS:referrer} %{QS:agent} %{BASE10NUM:request_time} %{BASE10NUM:upstream_request_time} %{IPORHOST:upstream_ip}" }
}
# 定义客户端的IP是哪个字段(上面定义的数据格式)
geoip {
source => "clientip"
}

# 定义时间戳的格式
date {
match => [ "timestamp", "yyyy-MM-dd-HH:mm:ss" ]
locale => "cn"
}

}
  • output
1
2
3
4
5
output {
elasticsearch {
hosts => ["localhost:9200"]
}
}

把上面的拼起来就完事儿了.

启动我们的Logstash

1
bin/logstash -f first.conf --config.reload.automatic

相应的启动Kibana以及Elasticsearch, 访问localhost:5601即可.

3. Filebeat配置

这里再额外的补充一下Filebeat的一些配置以及启动时的注意事项.
编辑默认配置文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# vim filebeat.yml

filebeat.prospectors:

# Each - is a prospector. Most options can be set at the prospector level, so
# you can use different prospectors for various configurations.
# Below are the prospector specific configurations.

- type: log

# Change to true to enable this prospector configuration.
enabled: True

# Paths that should be crawled and fetched. Glob based paths.
paths:
- /home/smartkeyerror/access.log
# 或者是/home/smartkeyerror/*.log
#- c:\programdata\elasticsearch\logs\*

# 往下拉, 找到output, 将其推送至Logstash
#----------------------------- Logstash output --------------------------------
output.logstash:
# The Logstash hosts
hosts: ["localhost:5044"]

配置完成后, 执行:

1
2
3
# FileBeat 需要以root身份启动,因此先更改配置文件的权限
sudo chown root filebeat.yml
sudo ./filebeat -e -c filebeat.yml -d "publish"